Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SVG: About using <defs> and <use> with variable text values

Tags:

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?

like image 548
Lukman Avatar asked Sep 14 '09 15:09

Lukman


People also ask

Can I use variables in SVG?

There is no such thing as variables in SVG. What you can do is dynamically generate (or modify) an SVG using Javascript.

Can SVG contain text?

SVG treats a text element in much the same way that it treats graphical and shape elements. You position text with x and y coordinates and use fill and stroke options to color text the same way you would with a <circle> or <rect> element.

How do I use SVG DEFS?

The SVG <defs> element is used to embed definitions that can be reused inside an SVG image. Using the SVG <defs> elements you can group SVG shapes together and reuse them as a single shape. The shapes defined inside the <defs> element will be displayed when you reference it by a <use> element.

How do I put text inside an SVG path?

To create SVG text that follows a path you use a <textPath> element in combination with a path you define inside <defs> tags. To refer to the path you'll use an xlink:href attribute on the <textPath> . Note: SVG 2.0 is dropping the xlink: and will simply use href to refer to the path.


2 Answers

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> 
like image 92
autotroph Avatar answered Oct 12 '22 06:10

autotroph


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.

like image 24
räph Avatar answered Oct 12 '22 05:10

räph