23

I have the following SVG source code that generates a number of boxes with texts:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
       "http://www.w3.org/TR/2001/REC-SVG-20050904/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="600" height="600">
  <defs>
  </defs>
  <title>Draw</title>
  <g transform="translate(50,40)">
    <rect width="80" height="30" x="0" y="-20" style="stroke: black; stroke-opacity: 1; stroke-width: 1; fill: #9dc2de" />
    <text text-anchor="middle" x="40">Text</text>
  </g>
  <g transform="translate(150,40)">
    <rect width="80" height="30" x="0" y="-20" style="stroke: black; stroke-opacity: 1; stroke-width: 1; fill: #9dc2de" />
    <text text-anchor="middle" x="40">Text 2</text>
  </g>
  <g transform="translate(250,40)">
    <rect width="80" height="30" x="0" y="-20" style="stroke: black; stroke-opacity: 1; stroke-width: 1; fill: #9dc2de" />
    <text text-anchor="middle" x="40">Text 3</text>
  </g>
</svg>

As you can see, I repeated the <g></g> three times to get three such boxes, when SVG has <defs> and <use> elements that allow reusing elements using id references instead of repeating their definitions. Something like:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
       "http://www.w3.org/TR/2001/REC-SVG-20050904/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="600" height="600">
  <defs>
    <marker style="overflow:visible;fill:inherit;stroke:inherit"
            id="Arrow1Mend" refX="0.0" refY="0.0" orient="auto">
      <path transform="scale(0.4) rotate(180) translate(20,0)"
            style="fill-rule:evenodd;stroke-width:2.0pt;marker-start:none;"
            d="M 0.0,-15.0 L -20.5,0.0 L 0.0,15.0 "/>
    </marker>
      <line marker-end="url(#Arrow1Mend)" id="systemthread" x1="40" y1="10" x2="40" y2="410" style="stroke: black; stroke-dasharray: 5, 5; stroke-width: 1; "/>
  </defs>
  <title>Draw</title>
  <use xlink:href="#systemthread" transform="translate(50,40)" />
  <use xlink:href="#systemthread" transform="translate(150,40)" />
  <use xlink:href="#systemthread" transform="translate(250,40)" />
</svg>

Unfortunately I can't do this with the first SVG code since I need the texts to be different for each box, while the <use> tag simply duplicates 100% what's defined in <defs>.

Is there any way to use <defs> and <use> with some kind of parameters/arguments mechanism like function calls?

Lukman
  • 18,462
  • 6
  • 56
  • 66
  • I put a class on the , then used Javascript/Jquery to access that item by class and manipulate its attributes. Works fine. – john k Oct 29 '14 at 18:52

2 Answers2

26

I was searching for an answer to my own SVG question. Your question helped me solve my answer, so I am answering yours.

.... Read your question more closely. Included TWO code samples

Sample #1. Boxes with text

Sample #2. Arrows with text

Sample 1

<html>
  <svg xmlns="http://www.w3.org/2000/svg"
       xmlns:xlink="http://www.w3.org/1999/xlink"
       width="600" height="900">
    <defs>
      <g id="my_box"
         desc="my rectangle template">
        <rect width="80" height="30" x="0" y="-20" style="stroke: black; stroke-opacity: 1; stroke-width: 1; fill: #9dc2de" />
      </g>
    </defs>

    <g transform="translate(50 40)">
      <text text-anchor="middle" x="40"> This little box went to market </text>
      <use xlink:href="#my_box" />
    </g>

    <g transform="translate(150 140)">
      <use xlink:href="#my_box" />
      <text text-anchor="middle" x="40"> This little box stayed home </text>
    </g>

    <g transform="translate(250 240)">
      <use xlink:href="#my_box" />
      <text text-anchor="middle" x="40"> This little box had roast beef </text>
    </g>
  </svg>

</html>

Note in sample 1 that the order of the box and text are important.

Sample 2

<html>
  <svg xmlns="http://www.w3.org/2000/svg"
       xmlns:xlink="http://www.w3.org/1999/xlink"
       width="600" height="900">
    <defs>
      <g id="arrow"
         desc="arrow with a long dashed tail">

         <marker style="overflow:visible;fill:inherit;stroke:inherit"
                 id="Arrow1Mend" refX="0.0" refY="0.0" orient="auto">
         <path transform="scale(0.4) rotate(180) translate(20,0)"
               style="fill-rule:evenodd;stroke-width:2.0pt;marker-start:none;"
               d="M 0.0,-15.0 L -20.5,0.0 L 0.0,15.0 "
               desc="The actual commands to draw the arrow head"
         />
         </marker>

        <line transform="translate(0 -450)"
              marker-end="url(#Arrow1Mend)"
              x1="40" y1="10" x2="40" y2="410"
              style="stroke: black; stroke-dasharray: 5, 5; stroke-width: 1; "
              desc="This is the tail of the 'arrow'"
        />
      </g>
    </defs>

    <g transform="translate(100 450)">
      <text> Text BEFORE xlink </text>
      <use xlink:href="#arrow" />
    </g>

    <g transform="translate(200 550)">
      <use xlink:href="#arrow" />
      <text> More to say </text>
    </g>

    <g transform="translate(300 650)">
      <use xlink:href="#arrow" />
      <text> The last word </text>
    </g>

    <g transform="translate(400 750)">
      <use xlink:href="#arrow" />
      <text> Text AFTER xlink </text>
    </g>

  </svg>
</html>
autotroph
  • 261
  • 3
  • 4
  • 1
    +1, I didn't think to use `text` and `use` with no positioning params. It's not the optimal solution, but (still) as good as SVG can do without resorting to scripting. – Courtney Christensen Aug 31 '11 at 02:20
9

A way to achieve this with the current svg recommendation is not known to me.

But there is a working draft for a svg 2.0 module, see: SVG Referenced Parameter Variables. The example with the flowers there is exactly what you are looking for I suppose! But then you probably have to wait until june 2010 or even longer until this is a W3C recommendation and supported by clients I assume.

For now you could probably solve it with scripting.

räph
  • 3,634
  • 9
  • 34
  • 41
  • aww too bad i'm ahead of the standard :P .. i guess i'll just stick to repeating the elements inside the svg document since i'd prefer not to use scripting in svg unless if absolutely necessary. The svg document will be generated by php backend anyway ... – Lukman Sep 15 '09 at 06:17
  • @räph do you have an example of how I could solve this with scripting and use elements? The only way I could come up with a scripting solution would be to repeat the whole element instead of a `` tag – Thawn Apr 25 '18 at 09:32