Ricardo Cruz
Ricardo Cruz

Reputation: 3593

Repeating a SVG path

Say that I have the following arrow, which I want to repeat several times at different locations within the svg:

<svg width="400" height="400">
<path transform="translate(150,100)" fill="black" d="M 0.5,0.5 l-100,0 -25,20 25,20 100,0 z" />
<path transform="translate(300,200)" fill="black" d="M 0.5,0.5 l-100,0 -25,20 25,20 100,0 z" />
<path transform="translate(150,300)" fill="black" d="M 0.5,0.5 l-100,0 -25,20 25,20 100,0 z" />
</svg>

arrows

I might want to change the path shape in the future, so I would prefer to avoid copy-pasting the d attribute all over the place.

Is it possible to define path's shape somewhere and then place it at different x, y coordinates, without manipulating it from javascript?

Two thoughts:

Is there any way to avoid copy past the entire thing, short of injecting it from javascript?

Upvotes: 5

Views: 6802

Answers (2)

Paul LeBeau
Paul LeBeau

Reputation: 101938

This answer provided as an extension to JCD's answer in order to show OP what I by the <symbol> not being required here. <symbol> elements provide some features that are not needed when you are simply reusing an element.

<svg width="400" height="400">
  <defs>
    <path id="mypath" fill="black" d="M 0,20 l25,20 100,0 0,-40 -100,0 z" />
  </defs>
  <use xlink:href="#mypath" x="50" y="100" />
  <use xlink:href="#mypath" x="200" y="200" />
  <use xlink:href="#mypath" x="50" y="300" />
</svg>

Upvotes: 8

jered
jered

Reputation: 11591

<defs> does in fact support <path>, since it is a "Shape Element" as listed under the "Permitted Content" section of the documentation. However, <defs> by itself doesn't do much, it's just a semantic way to organize your SVG. What you're looking for are <symbol> and <use>.

<symbol> defines a template that you can use and re-use.

<use> creates an instance of a given symbol.

<svg width="400" height="400">
  <defs>
    <symbol id="mypath">
      <path fill="black" d="M 0,20 l25,20 100,0 0,-40 -100,0 z" />
    </symbol>
  </defs>
  <use xlink:href="#mypath" x="50" y="100" />
  <use xlink:href="#mypath" x="200" y="200" />
  <use xlink:href="#mypath" x="50" y="300" />
</svg>

Your <path> data is kind of weird because it starts on the left side of the element and then proceeds to draw even further to the left, necessitating the transform property. Note how I do it in the above snippet (starting the line at the left edge of the element and never drawing further left than that) which works a bit better and doesn't need transform to avoid accidental cropping.

https://developer.mozilla.org/en-US/docs/Web/SVG/Element/symbol

Upvotes: 8

Related Questions