svg circle color change at certain point

198 Views Asked by At

I have a svg that circle is moving around through path. I want the circles' color are changed at some points (ex. mid of the path)

https://codepen.io/lzwdct/pen/poRYVXZ

<circle r="20" fill="blue" mask="url(#myMask)">
    <animateMotion dur="5s" repeatCount="indefinite"
      path="M718.54,66.06L294.41,490.19c-48.89,48.89-128.09,48.95-176.91,0.13c-48.82-48.82-48.76-128.02,0.13-176.91
            s128.09-48.95,176.91-0.13 M294.28,313.55l424.13,424.13c48.89,48.89,128.09,48.95,176.91,0.13c48.82-48.82,48.76-128.02-0.13-176.91
            c-48.89-48.89-128.09-48.95-176.91-0.13" />
</circle>

Please guide me how to update the color. The color eventually will be changed multiple times with long paths.

2

There are 2 best solutions below

0
On

You need to tweak it for your paths, basic concept is to add an animate on the element you want to change and use values and keyTimes (the whole animation is 0 to 1)

As you will notice, you get a color-gradient for free.
If you don't want that, add more keyTimes so the color fades occur faster

<svg width="450" height="180">
<path id="PATH" d="M 50 90 H400" stroke="black"/>
  <g>  
    <circle class="circle" r="30" fill="black"></circle>
    <circle class="circle" r=25 fill="red" >
      <animate 
         attributeName="fill"
         attributeType="XML"
         values="red;green;yellow;hotpink;blue"
         keyTimes= "0;0.4;0.6;0.8;1"
         dur="3s"
         repeatCount="indefinite"/>
    </circle>
    <animateMotion dur="3s" repeatCount="indefinite">
      <mpath href="#PATH" />
    </animateMotion>
  </g>       
</svg>

svga

0
On

I'm not sure if there's anything in SVG that would enable you to do that directly.

But you can check currentTime vs the duration of the animateMotion element and set a color via javascript based on that.

const color = (n) => {
  const R = Math.round((255 * n) / 100);
  const G = Math.round((255 * (100 - n)) / 100);
  const B = 0;
  return `rgb(${R}, ${G}, ${B})`;
};

const circles = document.querySelectorAll("circle");

window.setInterval(() => {
  circles.forEach(circle => {
    const ani = circle.querySelector('animateMotion');
    const duration = ani.getSimpleDuration();
    const currentTime = ani.getCurrentTime() % duration;
    const colorValue = color((currentTime / duration) * 100);
    circle.parentNode.style.fill = colorValue;
  });
}, 500);
circle {
  transition: 500ms;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 2549.62 3338.72" style="enable-background:new 0 0 2549.62 3338.72;" xml:space="preserve">
<style type="text/css">
    .st0{fill:none;stroke:#8EA5AE;stroke-width:50;stroke-miterlimit:10;}
    .st1{fill:none;stroke:#8EA5AE;stroke-width:50;stroke-linecap:round;stroke-miterlimit:10;}
    .st2{fill:none;stroke:#758992;stroke-width:50;stroke-miterlimit:10;}
    .st3{fill:none;stroke:#758992;stroke-width:50;stroke-linecap:round;stroke-miterlimit:10;}
    .st4{fill:none;stroke:#4E5F65;stroke-width:50;stroke-miterlimit:10;}
    .st5{fill:none;stroke:#4E5F65;stroke-width:50;stroke-linecap:round;stroke-miterlimit:10;}
</style>
<g>
  <mask id="myMask">
    <!--   Pixels under white are rendered   -->
    <rect x="0" y="0" width="1015" height="855" fill="white" />
    <!--   Pixels under black are hidden   -->
    <rect class="moveme" x="315" y="335" height="150" width="150" transform="rotate(45 395 395)">
      <animateTransform attributeName="transform"
                          attributeType="XML"
                          type="scale"
                          keyTimes="0; 0.25999; 0.26; 1"
                          values="1; 1; 0; 0"
                          dur="5s"
                          additive="sum"
                          repeatCount="indefinite"/>
    </rect>
  </mask>
    <g>
        <path class="st0" d="M718.54,66.06L294.41,490.19c-48.89,48.89-128.09,48.95-176.91,0.13c-48.82-48.82-48.76-128.02,0.13-176.91
            s128.09-48.95,176.91-0.13" />
        <path class="st1" d="M683.19,30.7L258.92,454.97c-29.29,29.29-76.78,29.29-106.07,0c-29.29-29.29-29.29-76.78,0-106.07
            c29.29-29.29,76.78-29.29,106.07,0"/>
        <path class="st2" d="M753.9,101.42c0,0-424.26,424.26-424.26,424.26c-68.34,68.34-179.15,68.34-247.49,0s-68.34-179.15,0-247.49
            s179.15-68.34,247.49,0"/>
      
    </g>
    <g>
        <path class="st0" d="M294.28,313.55l424.13,424.13c48.89,48.89,128.09,48.95,176.91,0.13c48.82-48.82,48.76-128.02-0.13-176.91
            c-48.89-48.89-128.09-48.95-176.91-0.13"/>
        <path class="st2" d="M329.63,278.19L753.9,702.46c29.29,29.29,76.78,29.29,106.07,0c29.29-29.29,29.29-76.78,0-106.07
            s-76.78-29.29-106.07,0"/>
        <path class="st1" d="M258.92,348.9c0,0,424.26,424.26,424.26,424.26c68.34,68.34,179.15,68.34,247.49,0s68.34-179.15,0-247.49
            s-179.15-68.34-247.49,0"/>
    </g>
</g>
  <g mask="url(#myMask)">
<circle r="20" mask="url(#myMask)">
    <animateMotion dur="5s" repeatCount="indefinite"
      path="M718.54,66.06L294.41,490.19c-48.89,48.89-128.09,48.95-176.91,0.13c-48.82-48.82-48.76-128.02,0.13-176.91
            s128.09-48.95,176.91-0.13 M294.28,313.55l424.13,424.13c48.89,48.89,128.09,48.95,176.91,0.13c48.82-48.82,48.76-128.02-0.13-176.91
            c-48.89-48.89-128.09-48.95-176.91-0.13" />
</circle>
<circle r="20">
    <animateMotion dur="5s" repeatCount="indefinite"
      path="M753.9,101.42c0,0-424.26,424.26-424.26,424.26c-68.34,68.34-179.15,68.34-247.49,0s-68.34-179.15,0-247.49
            s179.15-68.34,247.49,0 M329.63,278.19L753.9,702.46c29.29,29.29,76.78,29.29,106.07,0c29.29-29.29,29.29-76.78,0-106.07 s-76.78-29.29-106.07,0" />
</circle>
<circle r="20">
    <animateMotion id="circle1" dur="5s" repeatCount="indefinite"
      path="M683.19,30.7L258.92,454.97c-29.29,29.29-76.78,29.29-106.07,0c-29.29-29.29-29.29-76.78,0-106.07 c29.29-29.29,76.78-29.29,106.07,0 M258.92,348.9c0,0,424.26,424.26,424.26,424.26c68.34,68.34,179.15,68.34,247.49,0s68.34-179.15,0-247.49 s-179.15-68.34-247.49,0" /></circle></g>
</svg>