SVG 'set' animation not looping as expected - svg

I have a fairly simple SVG with 2 text elements. I want them to switch every 2 seconds (e.g. "2019", wait 2 seconds, "2020", wait 2 seconds, repeat forever).
For the life of me, nothing happens after the first "2019" is shown (e.g 2019 shows, then never goes away and 2020 never appears). If I change the show2019 begin to "3s;hide2020.end" it doesn't show up for 3 seconds, as expected, but still doesn't continue.
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="49" height="64">
<rect x="0" y="0" width="49" height="64" rx="5" ry="5" stroke="#F00" fill="#FFF" stroke-width="1" />
<text x="50%" text-anchor="middle" font-family="sans-serif" font-size="9pt" fill="#F00">
<tspan x="50%" y="1em">Check</tspan>
<tspan x="50%" y="2em">Terms</tspan>
<tspan x="50%" y="3em">for</tspan>
</text>
<text x="50%" text-anchor="middle" font-family="sans-serif" font-size="9pt" font-weight="bold" fill="#F00" visibility="hidden">
<tspan x="50%" y="4.5em">2019</tspan>
<set id="show2019" attributeName="visibility" to="visible" dur="2s" repeatCount="123456" begin="0s;hide2020.end" />
<set id="hide2019" attributeName="visibility" to="hidden" dur="2s" repeatCount="123456" begin="show2019.end + 2s" />
</text>
<text x="50%" text-anchor="middle" font-family="sans-serif" font-size="9pt" font-weight="bold" fill="#F00" visibility="hidden">
<tspan x="50%" y="4.5em">2020</tspan>
<set id="show2020" attributeName="visibility" to="visible"dur="2s" repeatCount="123456" begin="hide2019.end" />
<set id="hide2020" attributeName="visibility" to="hidden" dur="2s" repeatCount="123456" begin="show2020.end + 2s" />
</text>
</svg>
CodePen

Well, I bring you an even nicer solution which resembles a path transformation. Instead of using set...attributeName I used animate...attributeName which allows you to do the same with better look and less code.
See the code here:
<svg xmlns="http://www.w3.org/2000/svg" width="49" height="64">
<rect x="0" y="0" width="49" height="64" rx="5" ry="5" stroke="#F00" fill="#FFF" stroke-width="1" />
<text x="50%" text-anchor="middle" font-family="sans-serif" font-size="9pt" fill="#F00">
<tspan x="50%" y="1em">Check</tspan>
<tspan x="50%" y="2em">Terms</tspan>
<tspan x="50%" y="3em">for</tspan>
</text>
<text x="50%" text-anchor="middle" font-family="sans-serif" font-size="9pt" font-weight="bold" fill="#F00" opacity="1">
<tspan x="50%" y="4.5em">2019</tspan>
<animate attributeName="opacity" from="1" to="0" begin="0s" dur="3s" values="0;1;0" calcMode="linear" repeatCount="indefinite"/>
</text>
<text x="50%" text-anchor="middle" font-family="sans-serif" font-size="9pt" font-weight="bold" fill="#F00" opacity="1">
<tspan x="50%" y="4.5em">2020</tspan>
<animate attributeName="opacity" from="0" to="1" begin="0s" dur="3s" values="1;0;1" calcMode="linear" repeatCount="indefinite"/>
</text>
</svg>
If you play around with the start duration and values can just adjust it as much as to meet your needs.

Related

Center Text on Rectangle in SVG

I am trying to center some text ("Go") onto a blue rectangle in an SVG image, however the text is only appearing at the top left corner.
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
<g>
<rect fill="#8080ff" height="400" width="400" y="0" x="0"/>
<text font-weight="bold" stroke="black" dominant-baseline="middle" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" stroke-width="0" fill="#000000">Go</text>
</g>
</svg>
I think you are missing x="50%" y="50%" then it will work.
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
<g>
<rect fill="#8080ff" height="400" width="400" y="0" x="0"/>
<text font-weight="bold" stroke="black" x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" stroke-width="0" fill="#000000">Go</text>
</g>
</svg>

SVG text - one text left align and other text in same line has to be right align

I have the following items list and its prices to be displayed in SVG format.
Bottles ...........$5.00
Description of the bottles
Desktop accessories...........$25.00
Description of the Desktop accessories
Can anyone help me to layout the price at the right hand side of svgList as shown in the image also shown below.
Bottles ................................. $5.00
Description of the bottles
Desktop accessories........... $25.00
Description of the Desktop accessories
The SVG code is as follows :
<svg id=“svgList” width="816" height="400" class="myBGImage">
<g id="main">
<g id="subGroup01" class="group" transform="translate(20,100)" style="cursor: move; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">
<text alignment-baseline="baseline" text-anchor="start" data-type="itemtitle" id="itemtitle_h0f0" class="roboto_global fontSize_20g" stroke-width="2" color="#000000">
<tspan class="item" text-anchor="start" x="0" y="0">Bottles</tspan>
<tspan class="dots" text-anchor="start">...............</tspan>
<tspan class="price" text-anchor="start">$5.00</tspan>
<tspan class="item-desc" text-anchor="start" x="0" y="20">Description </tspan>
</text>
</g>
<g id="subGroup02" class="group" transform="translate(20,150)" style="cursor: move; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">
<text alignment-baseline="baseline" text-anchor="start" data-type="itemtitle" id="itemtitle_h0f1" class="roboto_global fontSize_20g" stroke-width="2" color="#000000">
<tspan class="item" text-anchor="start" x="0" y="0">Desktop accessories</tspan>
<tspan class="dots" text-anchor="start">...............</tspan>
<tspan class="price" text-anchor="start">$25.00</tspan>
<tspan class="item-desc" text-anchor="start" x="0" y="20">Description </tspan>
</text>
</g>
</g>
</svg>
Link to fiddle
You are using text-anchor="start", did you try text-anchor="end"?
That deals with the alignment issue. The only slightly tricky bit is how to do the variable width dots, without having to have to work out exactly how many dots you need to use in each case.
The approach I've used in my solution (see bottom example) is to use a dotted line.
<svg id="svgList" width="816" height="400" class="myBGImage">
<g transform="translate(20,100)">
<line x1="0" y1="0" x2="250" y2="0" stroke="black" stroke="1" stroke-dasharray="2 2"/>
<text class="item" text-anchor="start" x="0" y="0">Bottles</text>
<text class="price" text-anchor="end" x="250">$5.00</text>
</g>
</svg>
Then to hide the dots behind the text, we add an extra copy of the text behind the original text. Then we give that extra copy of the text a thick white stroke to hide the relevant section of the dotted line. It has the effect of a white "halo" around the text to obliterate the part of the dotted line behind our text.
In this little snippet, I've made the stroke/halo blue to show what's happening.
<svg id="svgList" width="816" height="400" class="myBGImage">
<g transform="translate(20,100)">
<line x1="0" y1="0" x2="250" y2="0" stroke="black" stroke="1" stroke-dasharray="2 2"/>
<use xlink:href="#row1" stroke="blue" stroke-width="6"/>
<g id="row1" fill="white">
<text class="item" text-anchor="start" x="0" y="0">Bottles</text>
<text class="price" text-anchor="end" x="250">$5.00</text>
</g>
<text class="item-desc" text-anchor="start" x="0" y="20">Description </text>
</g>
</svg>
The final result:
<svg id="svgList" width="816" height="400" class="myBGImage">
<g id="main">
<g id="subGroup01" class="group" transform="translate(20,100)" style="cursor: move; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">
<line x1="0" y1="0" x2="250" y2="0" stroke="black" stroke="1" stroke-dasharray="2 2"/>
<use xlink:href="#row1" stroke="white" stroke-width="4"/>
<g id="row1">
<text class="item" text-anchor="start" x="0" y="0">Bottles</text>
<text class="price" text-anchor="end" x="250">$5.00</text>
</g>
<text class="item-desc" text-anchor="start" x="0" y="20">Description </text>
</g>
<g id="subGroup02" class="group" transform="translate(20,150)" style="cursor: move; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">
<line x1="0" y1="0" x2="250" y2="0" stroke="black" stroke="1" stroke-dasharray="2 2"/>
<use xlink:href="#row2" stroke="white" stroke-width="4"/>
<g id="row2">
<text class="item" text-anchor="start" x="0" y="0">Desktop accessories</text>
<text class="price" text-anchor="end" x="250">$25.00</text>
</g>
<text class="item-desc" text-anchor="start" x="0" y="20">Description </text>
</g>
</g>
</svg>

why the text path are not rendered?

I really got puzzled why these two text are not displayed along the line and path. Could someone point me out?
<svg width="300px" height="300px">
<line id="ok" x1="10" y1="20" x2="100" y2="100" stroke="red" stroke-width=10>
<text>
<textPath stroke="black" xlink:href="#ok">OHHHHSUHDIAU</textPath>
</text>
</line>
<path id="io" d="M10,10 L100,10" stroke="blue" stroke-width=10>
<text>
<textPath stroke="black" xlink:href="#io">io</textPath>
</text>
</path>
</svg>
you can only do a <textPath> on a <path>
placing the <text> inside the <line> or <path> elements were causing them not to be rendered.
here is my best guess at what you're trying to accomplish, I hope this helps
<svg width="300px" height="300px">
<defs>
<path id="io" d="M10,10 L100,10" />
<path id="ok" d="M10,20 L100,100" />
</defs>
<use xlink:href="#io" stroke-width="10" stroke="blue" />
<use xlink:href="#ok" stroke-width="10" stroke="red" />
<text>
<textPath stroke="black" xlink:href="#io">io</textPath>
<textPath stroke="black" xlink:href="#ok">OHHHHSUHDIAU</textPath>
</text>
</svg>

Drawing a line after an arbitrary number of SVG tspan elements

I'd like to use SVG to create an XSLT template to generate PDFs of orders placed in a system. The idea is that I have N order positions (say between 3 and 10) which I want displayed row by row and with a horizontal line after the bottom-most row and the usual total row.
Here's is an illustration:
My problem is that I cannot find out how to position the horizontal line and the final total row relative the last order position row. Here's what I have so far:
http://jsfiddle.net/hg3hzd4j/
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="300" height="250" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g transform="translate(10, 15)">
<rect x="0" y="0" height="100%" width="100%" style="stroke:#000; fill: #FFFF00" fill-opacity="0.2" stroke-opacity="0.2"></rect>
<g transform="translate(10, 0)">
<line id="guide1" x1="160" y1="0" x2="160" y2="100%" style="stroke:rgb(255,0,0);stroke-width:1" />
<line id="guide2" x1="220" y1="0" x2="220" y2="100%" style="stroke:rgb(255,0,0);stroke-width:1" />
<g>
<text x="0" y="20">
<tspan>Mono layer</tspan>
<tspan x="100">$50</tspan>
<tspan x="160" style="text-anchor:end">4</tspan>
<tspan x="220" style="text-anchor:end">$200</tspan>
<tspan x="0" dy="20">Single layer</tspan>
<tspan x="100">$25</tspan>
<tspan x="160" style="text-anchor:end">3</tspan>
<tspan x="220" style="text-anchor:end">$75</tspan>
<tspan x="0" dy="20">Double layer</tspan>
<tspan x="100">$45</tspan>
<tspan x="160" style="text-anchor:end">3</tspan>
<tspan x="220" style="text-anchor:end">$135</tspan>
<tspan x="0" dy="20">Triple layer</tspan>
<tspan x="100">$65</tspan>
<tspan x="160" style="text-anchor:end">1</tspan>
<tspan x="220" style="text-anchor:end">$65</tspan>
<!-- I'd like a line here -->
<!-- And the grand total row -->
<tspan x="0" dy="30">Total</tspan>
<tspan x="100"></tspan>
<tspan x="160" style="text-anchor:end">11</tspan>
<tspan x="220" style="text-anchor:end">$475</tspan>
</text>
<line x1="0" y1="150" x2="100%" y2="150" style="stroke:rgb(0,0,0);stroke-width:2" />
</g>
</g>
</g>
</svg>
I'm by no means an expert so any suggestion is greatly appreciated. I thought I could define each position row with something similar to a DIV and that everything would shift down automatically. But obviously not.
Add the value the dy attribute of each order line to the y coordinate of the <text> element. That will get you the absolute Y position of the baseline of the last order line.
20 + (20 + 20 + 20) = 80.
Add an appropriate amount of extra padding to get you below the descenders of characters in the last row (eg. 10).
Then set the y1 and y2 coords of your line to the final value (90 in this example).
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="300" height="250" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g transform="translate(10, 15)">
<rect x="0" y="0" height="100%" width="100%" style="stroke:#000; fill: #FFFF00" fill-opacity="0.2" stroke-opacity="0.2"></rect>
<g transform="translate(10, 0)">
<line id="guide1" x1="160" y1="0" x2="160" y2="100%" style="stroke:rgb(255,0,0);stroke-width:1" />
<line id="guide2" x1="220" y1="0" x2="220" y2="100%" style="stroke:rgb(255,0,0);stroke-width:1" />
<g>
<text x="0" y="20">
<tspan>Mono layer</tspan>
<tspan x="100">$50</tspan>
<tspan x="160" style="text-anchor:end">4</tspan>
<tspan x="220" style="text-anchor:end">$200</tspan>
<tspan x="0" dy="20">Single layer</tspan>
<tspan x="100">$25</tspan>
<tspan x="160" style="text-anchor:end">3</tspan>
<tspan x="220" style="text-anchor:end">$75</tspan>
<tspan x="0" dy="20">Double layer</tspan>
<tspan x="100">$45</tspan>
<tspan x="160" style="text-anchor:end">3</tspan>
<tspan x="220" style="text-anchor:end">$135</tspan>
<tspan x="0" dy="20">Triple layer</tspan>
<tspan x="100">$65</tspan>
<tspan x="160" style="text-anchor:end">1</tspan>
<tspan x="220" style="text-anchor:end">$65</tspan>
<!-- I'd like a line here -->
<!-- And the grand total row -->
<tspan x="0" dy="30">Total</tspan>
<tspan x="100"></tspan>
<tspan x="160" style="text-anchor:end">11</tspan>
<tspan x="220" style="text-anchor:end">$475</tspan>
</text>
<line x1="0" y1="90" x2="100%" y2="90" style="stroke:rgb(0,0,0);stroke-width:2" />
</g>
</g>
</g>
</svg>

reusable parameters/ variables for svg graphic

For a study project I'm asked to write an easy customizable svg graphic.
Is there any concept of variables?
The best I came up with so far is the following:
<g id="box">
<rect x="0" y="0" width="25" height="20" rx="3" ry="3" style="fill:transparent;stroke-width:1;stroke:rgb(0,0,0)">
</g>
<g id="month">
<!-- first row -->
<g transform="translate(50 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Monday</text>
</g>
<g transform="translate(75 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Tuesday</text>
</g>
<g transform="translate(100 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Wednesday</text>
</g>
<g transform="translate(125 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Thursday</text>
</g>
<g transform="translate(150 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Friday</text>
</g>
<g transform="translate(175 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Saturday</text>
</g>
<g transform="translate(200 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Sunday</text>
</g>
....
</g>
Now the problem is, that if I change the the width of the box I need to adjust the translate parameter for each element in the month group.
Would be great to have something like this:
<param name="box-height" value="20" />
<param name="box-width" value="25" />
<g id="box">
<rect x="0" y="0" width="box-width" height="box-height" rx="3" ry="3" style="fill:transparent;stroke-width:1;stroke:rgb(0,0,0)">
</g>
<g id="month">
<!-- first row -->
<g transform="translate(2*box-width 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Monday</text>
</g>
<g transform="translate(3*box-width 40)">
<use xlink:href='#box'/>
<text x="5" y="15" fill="grey">Tuesday</text>
</g>
...
</g>
But I didnt find anything so far. Does something like this exist, or any other helpful ideas.
Thank you.
The answer is no.
Parameters have been suggested in the past, and have even had draft specs written, but haven't made it to any implementation of SVG AFAIK.
However you can create and manipulate SVG elements with Javascript. You can use plain old JS, or one of the specialty libraries like d3 or Raphaels.

Resources