Search code examples
animationsvgmasking

How to get SVG mask to work with animation?


I cannot seem to get this mask to work with my animation in SVG. What is wrong with this code? The green arrow should be masked out from the rightmost side of the circle, so that the arrow appears to be consumed by the circle upon contact.

<svg height="200" width="1200" viewBox="0 0 200 200">
<defs>
<mask id="mask1" x="0" y="0" width="700" height="110" >
<rect x="0" y="0" width="550" height="110" style="stroke:none; fill:white" />
<rect x="550" y="0" width="50" height="110" style="stroke:none; fill:black"/>
</mask>
</defs>

<polygon id="arrow" z-index="1" points="0,5 0,105 105,55" mask="url(#mask1)" fill="green">
<animateTransform attributeName="transform" type="translate" attributeType="XML" values="0, 0; 550, 0; 550, 0" keyTimes="0; .7; 1" dur="3s" repeatCount="indefinite" additive="sum"/> 
<animate attributeName="opacity" values="1; 1; 0" keyTimes="0; .5; 1" dur="3s" repeatCount="indefinite" /> 
</polygon>

<circle z-index="1" cx="550" cy="55" r="49" stroke-width="6" stroke="black" fill="gray"/>
<circle z-index="2" cx="550" cy="55" r="49" stroke-width="6" stroke="black" fill="none"/>

<circle id="greenCircle" z-index="2" cx="550" cy="55" r="49" stroke-width="6" stroke="green" fill="none"/>
<animate id="fillGreen" xlink:href="#greenCircle" attributeName="stroke-dasharray" values="154, 0, 154, 0; 0, 308, 0, 0; 0, 308, 0, 0" keyTimes="0; 0.5; 1" dur="3s" repeatCount="indefinite" /> 

<circle id="blackCircle" z-index="2" cx="550" cy="55" r="49" stroke-width="6" stroke="green" fill="none"/>
<animate id="fillBlack" xlink:href="#blackCircle" attributeName="stroke-dasharray" values="0, 154, 0, 154; 0, 154, 0, 154; 0, 0, 308, 0" dur="3s" keyTimes="0; 0.5; 1" repeatCount="indefinite" />
</circle>
</svg>


Solution

  • The transform applies to the mask too so as the polygon moves, so does the mask. You need to set the mask on something that doesn't move e.g.

    <svg height="200" width="1200" viewBox="0 0 200 200">
    <defs>
    <mask id="mask1" x="0" y="0" width="700" height="110" >
    <rect x="0" y="0" width="550" height="110" style="stroke:none; fill:white" />
    <rect x="550" y="0" width="50" height="110" style="stroke:none; fill:black"/>
    </mask>
    </defs>
    
    <g mask="url(#mask1)" >
    <polygon id="arrow" z-index="1" points="0,5 0,105 105,55" fill="green">
    <animateTransform attributeName="transform" type="translate" attributeType="XML" values="0, 0; 550, 0; 550, 0" keyTimes="0; .7; 1" dur="3s" repeatCount="indefinite" additive="sum"/> 
    <animate attributeName="opacity" values="1; 1; 0" keyTimes="0; .5; 1" dur="3s" repeatCount="indefinite" /> 
    </polygon>
    </g>
    
    <circle z-index="1" cx="550" cy="55" r="49" stroke-width="6" stroke="black" fill="gray"/>
    <circle z-index="2" cx="550" cy="55" r="49" stroke-width="6" stroke="black" fill="none"/>
    
    <circle id="greenCircle" z-index="2" cx="550" cy="55" r="49" stroke-width="6" stroke="green" fill="none"/>
    <animate id="fillGreen" xlink:href="#greenCircle" attributeName="stroke-dasharray" values="154, 0, 154, 0; 0, 308, 0, 0; 0, 308, 0, 0" keyTimes="0; 0.5; 1" dur="3s" repeatCount="indefinite" /> 
    
    <circle id="blackCircle" z-index="2" cx="550" cy="55" r="49" stroke-width="6" stroke="green" fill="none"/>
    <animate id="fillBlack" xlink:href="#blackCircle" attributeName="stroke-dasharray" values="0, 154, 0, 154; 0, 154, 0, 154; 0, 0, 308, 0" dur="3s" keyTimes="0; 0.5; 1" repeatCount="indefinite" />
    </circle>
    </svg>