0

Given the following example:

<svg xmlns="http://www.w3.org/2000/svg">

    <defs>
        <rect id="rectangle" fill="red" width="25" height="25">
            <animate 
                attributeName="fill" 
                values="red;blue;green;red"
                dur="1s" 
                repeatCount="indefinite"
            />
            <animate 
                attributeName="x" 
                values="0;50;0" 
                dur="1s" 
                repeatCount="indefinite"
            />            
        </rect>
    </defs>

    <!-- i want this to have both animations -->
    <use id="rect1" href="#rectangle" />

    <!-- i want this one to inherit only the fill animation  -->
    <use id="rect2" href="#rectangle" y="50" />

</svg>

How can I make it so that "rect2" only inherits the "fill" animation?

OBS: What I didn't wanted to do was to create an intermediate "use" element inside the defs, so the main rect would have the fill animation and the intermediate use element would reference the main rect, and also declare the "x" animation. And of course, use differente "hrefs" on the external elements.

5
  • You can leave the fill animation for the rect and animate the x of the first <use> Commented Oct 14, 2024 at 19:49
  • Don't use use. Just create two independent shapes. Commented Oct 14, 2024 at 19:52
  • I know! But I need both animate tags to remain on the rect in defs. Commented Oct 14, 2024 at 19:52
  • 1
    Not possible. Use elements are not appropriate for your use case. Commented Oct 14, 2024 at 19:53
  • 1
    Besides, you could easily achieve these animations with CSS - applying/removing animations by selector rules. Rule of thumb: you can't really override attributes or properties in a symbol/defs reference from the <use> instance. So element specific attributes or animations shouldn't be included in the definition of a reusable element Commented Oct 14, 2024 at 22:20

2 Answers 2

0

Like said in the comments, you can't access the required attributes on <use>

Thus you have to create the SVG yourself for every instance.

This also helps you to avoid the global ID trap,
<defs> always get you into to trouble when using multiple SVGs in the page.
id="rectangle" would have been a global ID, first declaration used by every SVG on the page

<svg-rect></svg-rect>
<svg-rect fill ></svg-rect>
<svg-rect x ></svg-rect>
<svg-rect fill x dur="2s"></svg-rect>

and a native Web Component does it all:

customElements.define("svg-rect", class extends HTMLElement{
  connectedCallback(){
    this.style.display = "block";
    let dur = this.getAttribute("dur") || "1s"
    let svg = `<svg width="100px" viewBox="0 0 75 25" style="background:pink">`;
    svg += `<rect fill="red" width="25" height="25">`;
    
    if (this.hasAttribute("fill")) {
      let colors = this.getAttribute("colors") || "red;blue;green;red";
      svg += `<animate attributeName="fill" values="${colors}" dur="${dur}" repeatCount="indefinite"/>`;
    }
    
    if (this.hasAttribute("x")) {
      svg += `<animate attributeName="x" values="0;50;0" dur="${dur}" repeatCount="indefinite"/>`
    }
    
    svg += `</rect>`;
    this.innerHTML = svg;
  }
})
<svg-rect></svg-rect>
<svg-rect fill dur="3s" ></svg-rect>
<svg-rect x ></svg-rect>
<svg-rect fill x dur="2s"></svg-rect>

Sign up to request clarification or add additional context in comments.

Comments

0

As commented, maybe the <use> is not that useful in this case. You can move both the fill attribute and the <animate> elements from the <rect> to the <use> elements.

<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <rect id="rectangle" width="25" height="25"/>
  </defs>
  <!-- i want this to have both animations -->
  <use id="rect1" href="#rectangle" fill="red">
    <animate
      attributeName="x" 
      values="0;50;0" 
      dur="1s" 
      repeatCount="indefinite"/>   
    <animate 
      attributeName="fill" 
      values="red;blue;green;red"
      dur="1s" 
      repeatCount="indefinite"/>
  </use>
  <!-- i want this one to inherit only the fill animation  -->
  <use id="rect2" href="#rectangle" y="50"  fill="red">
    <animate 
      attributeName="fill" 
      values="red;blue;green;red"
      dur="1s" 
      repeatCount="indefinite"/>
  </use>
</svg>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.