I am using animateMotion to have an animation on my path. Here is the simple code:
<!DOCTYPE html>
<html>
<head>
<title>Example Of Many Things!</title>
</head>
<body>
<svg width="465pt" height="188pt" viewBox="0.00 0.00 465.00 188.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 184)">
<g id="3" class="cluster loop-node">
</g>
<g id="4" class="node cu-node">
<path fill="#ffffff" stroke="#a4a4a4" d="M92.6667,-53C92.6667,-53 119.3333,-53 119.3333,-53 121.6667,-53 124,-55.3333 124,-57.6667 124,-57.6667 124,-62.3333 124,-62.3333 124,-64.6667 121.6667,-67 119.3333,-67 119.3333,-67 92.6667,-67 92.6667,-67 90.3333,-67 88,-64.6667 88,-62.3333 88,-62.3333 88,-57.6667 88,-57.6667 88,-55.3333 90.3333,-53 92.6667,-53"></path>
<text text-anchor="start" x="100.6663" y="-57.6" font-family="font-awesome" font-size="6.00" fill="#000000">1:12</text>
</g>
<g id="5" class="node cu-node">
<path fill="#ffffff" stroke="#a4a4a4" d="M167.3333,-25C167.3333,-25 195.6667,-25 195.6667,-25 199.3333,-25 203,-28.6667 203,-32.3333 203,-32.3333 203,-39.6667 203,-39.6667 203,-43.3333 199.3333,-47 195.6667,-47 195.6667,-47 167.3333,-47 167.3333,-47 163.6667,-47 160,-43.3333 160,-39.6667 160,-39.6667 160,-32.3333 160,-32.3333 160,-28.6667 163.6667,-25 167.3333,-25"></path>
<text text-anchor="start" x="176.1663" y="-33.6" font-family="font-awesome" font-size="6.00" fill="#000000">1:13</text>
</g>
<g id="4t5" class="edge">
<path fill="none" stroke="#717070" d="M124.2764,-54.1903C133.5025,-51.2575 144.8656,-47.6454 155.028,-44.4149" id="path4t5"></path>
<polygon fill="#717070" stroke="#717070" points="155.6709,-46.0469 159.9058,-42.8644 154.6106,-42.7114 155.6709,-46.0469"></polygon>
<g id="6" class="node cu-node">
<path fill="#ffffff" stroke="#a4a4a4" d="M246.3333,-25C246.3333,-25 274.6667,-25 274.6667,-25 278.3333,-25 282,-28.6667 282,-32.3333 282,-32.3333 282,-39.6667 282,-39.6667 282,-43.3333 278.3333,-47 274.6667,-47 274.6667,-47 246.3333,-47 246.3333,-47 242.6667,-47 239,-43.3333 239,-39.6667 239,-39.6667 239,-32.3333 239,-32.3333 239,-28.6667 242.6667,-25 246.3333,-25"></path>
<text text-anchor="start" x="255.1663" y="-33.6" font-family="font-awesome" font-size="6.00" fill="#000000">1:14</text>
</g>
<g id="5t6" class="edge">
<path fill="none" stroke="#717070" d="M203.0871,-36C212.5795,-36 223.8229,-36 233.8327,-36" id="path5t6"></path>
<polygon fill="#717070" stroke="#717070" points="233.939,-37.7501 238.939,-36 233.939,-34.2501 233.939,-37.7501"></polygon>
</g>
</g>
</svg>
</body>
<script type="text/javascript">
var g8t3 = document.getElementById('4t5');
var path = document.getElementById('4t5').getElementsByTagName('path')[0]
path.setAttribute("id", "path4t5");
var circleAnim = ' <circle r="1" fill="green"><animateMotion id="myMoveAnimation4t5" dur="3s" begin="0s;myMoveAnimation5t6.end"><mpath xlink:href="#path4t5"></mpath></animateMotion></circle>'
g8t3.insertAdjacentHTML( 'beforeend', circleAnim );
// // now move circle on the path
var g8t4 = document.getElementById('5t6');
var path = document.getElementById('5t6').getElementsByTagName('path')[0]
path.setAttribute("id", "path5t6");
var circleAnim = ' <circle r="1" fill="green"><animateMotion id="myMoveAnimation5t6" dur="3s" begin="myMoveAnimation4t5.end"><mpath xlink:href="#path5t6"></mpath></animateMotion></circle>'
g8t4.insertAdjacentHTML( 'beforeend', circleAnim );
</script></html>
As you can see, there is a green circle on the path which is moving, which is correct.
But there is something weird: There is also another green circle on the left bottom of the graph, which is redundant. I don't how it appears and how I can get rid of it.
Any help?
Instead of appending two circles in your svg, append the two <animateMotion>s inside a single circle. Also, you'll probably want to set your <animationMotion>'s fill attribute to "fill".
As you wrote it, when your circles are in idle state, they will come back to their initial position (unset).
var g8t3 = document.getElementById('4t5');
var path = document.getElementById('4t5').getElementsByTagName('path')[0]
path.setAttribute("id", "path4t5");
var circleAnim = '<circle r="1" fill="green">' +
// first part of the anim
'<animateMotion id="myMoveAnimation4t5" dur="3s" begin="0s;myMoveAnimation5t6.end"><mpath xlink:href="#path4t5" fill="freeze"></mpath></animateMotion>' +
// second part of the anim
'<animateMotion id="myMoveAnimation5t6" dur="3s" begin="myMoveAnimation4t5.end" fill="freeze"><mpath xlink:href="#path5t6"></mpath></animateMotion>' +
'</circle>'
g8t3.insertAdjacentHTML('beforeend', circleAnim);
<svg width="465pt" height="188pt" viewBox="0.00 0.00 465.00 188.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 184)">
<g id="3" class="cluster loop-node">
</g>
<g id="4" class="node cu-node">
<path fill="#ffffff" stroke="#a4a4a4" d="M92.6667,-53C92.6667,-53 119.3333,-53 119.3333,-53 121.6667,-53 124,-55.3333 124,-57.6667 124,-57.6667 124,-62.3333 124,-62.3333 124,-64.6667 121.6667,-67 119.3333,-67 119.3333,-67 92.6667,-67 92.6667,-67 90.3333,-67 88,-64.6667 88,-62.3333 88,-62.3333 88,-57.6667 88,-57.6667 88,-55.3333 90.3333,-53 92.6667,-53"></path>
<text text-anchor="start" x="100.6663" y="-57.6" font-family="font-awesome" font-size="6.00" fill="#000000">1:12</text>
</g>
<g id="5" class="node cu-node">
<path fill="#ffffff" stroke="#a4a4a4" d="M167.3333,-25C167.3333,-25 195.6667,-25 195.6667,-25 199.3333,-25 203,-28.6667 203,-32.3333 203,-32.3333 203,-39.6667 203,-39.6667 203,-43.3333 199.3333,-47 195.6667,-47 195.6667,-47 167.3333,-47 167.3333,-47 163.6667,-47 160,-43.3333 160,-39.6667 160,-39.6667 160,-32.3333 160,-32.3333 160,-28.6667 163.6667,-25 167.3333,-25"></path>
<text text-anchor="start" x="176.1663" y="-33.6" font-family="font-awesome" font-size="6.00" fill="#000000">1:13</text>
</g>
<g id="4t5" class="edge">
<path fill="none" stroke="#717070" d="M124.2764,-54.1903C133.5025,-51.2575 144.8656,-47.6454 155.028,-44.4149" id="path4t5"></path>
<polygon fill="#717070" stroke="#717070" points="155.6709,-46.0469 159.9058,-42.8644 154.6106,-42.7114 155.6709,-46.0469"></polygon>
<g id="6" class="node cu-node">
<path fill="#ffffff" stroke="#a4a4a4" d="M246.3333,-25C246.3333,-25 274.6667,-25 274.6667,-25 278.3333,-25 282,-28.6667 282,-32.3333 282,-32.3333 282,-39.6667 282,-39.6667 282,-43.3333 278.3333,-47 274.6667,-47 274.6667,-47 246.3333,-47 246.3333,-47 242.6667,-47 239,-43.3333 239,-39.6667 239,-39.6667 239,-32.3333 239,-32.3333 239,-28.6667 242.6667,-25 246.3333,-25"></path>
<text text-anchor="start" x="255.1663" y="-33.6" font-family="font-awesome" font-size="6.00" fill="#000000">1:14</text>
</g>
<g id="5t6" class="edge">
<path fill="none" stroke="#717070" d="M203.0871,-36C212.5795,-36 223.8229,-36 233.8327,-36" id="path5t6"></path>
<polygon fill="#717070" stroke="#717070" points="233.939,-37.7501 238.939,-36 233.939,-34.2501 233.939,-37.7501"></polygon>
</g>
</g>
</g>
</svg>
I am trying to convert an svg graph to a png image. To do so, I am first converting my svg graph to a canvas using the library 'canvg', and then I use the method canvas.toDataURL('image/png') to finally convert my graph into a png image. The reason why I am using the library 'canvg' is because I needed my code to work on ie9 and I couldn't find another way around, although I haven't tested on it yet.
All seems to work perfectly until I get the result, when I have noticed that all my paths are thicker than in the initial svg graph. So, trying to find out what I was doing wrong, I start doing small tests on http://canvg.github.io/canvg/examples/index.htm. It is then when I noticed that if I do not set the attribute fill to none either inline or in a css file then the path is thicker than one pixel. As my svg graph have some of the styles in a separate css file, I tried to flatten them (I took the idea from Convert embedded SVG to PNG in-place):
function flatten_svg_element_css(target){
if (target.nodeType != Node.TEXT_NODE) {
var cssStyle = window.getComputedStyle(target);
if (cssStyle) {
var fillStyle = '';
if( cssStyle.getPropertyValue('fill') == 'none' && cssTyle.getPropertyValue('stroke') == 'rgb(0, 0, 0)'){
fillStyle = 'fill:none; stroke:rgb(0, 0, 0);';
}
target.style.cssText = fillStyle + cssStyle.cssText;
}
}
}
function flatten_svg_css(target) {
for (var i = 0; i < target.childNodes.length; i++) {
var child = target.childNodes[i];
if (child.childNodes != null && child.childNodes.length > 0) {
flatten_svg_css(child);
}
else{
flatten_svg_element_css(child);
}
}
}
But it seems that it never gets into the condition cssStyle.getPropertyValue('fill') == 'none' && cssTyle.getPropertyValue('stroke') == 'rgb(0, 0, 0).
When the target is a path, the function getPropertyValue('fill') returns rgb(0, 0, 0) instead of none. But if I test directly the element with Firebug window.getComputedStyle(d3.select('.domain').node()).getPropertyValue('fill'), I got the value to none.
This is the svg graph that I am trying to convert to a png image. The graph has been generated using the library 'dc.js':
<svg width="1166" height="317">
<g>
<g class="grid-line horizontal" transform="translate(50,10)">
<line x1="1" y1="265" x2="1066" y2="265" opacity="0" />
<line x1="1" y1="239" x2="1066" y2="239" opacity="0" />
<line x1="1" y1="212" x2="1066" y2="212" opacity="0" />
<line x1="1" y1="186" x2="1066" y2="186" opacity="0" />
<line x1="1" y1="159" x2="1066" y2="159" opacity="0" />
<line x1="1" y1="133" x2="1066" y2="133" opacity="0" />
<line x1="1" y1="106" x2="1066" y2="106" opacity="0" />
<line x1="1" y1="80" x2="1066" y2="80" opacity="0" />
<line x1="1" y1="53" x2="1066" y2="53" opacity="0" />
<line x1="1" y1="27" x2="1066" y2="27" opacity="0" />
<line x1="1" y1="0" x2="1066" y2="0" opacity="0" />
</g>
<g class="chart-body" transform="translate(50, 10)"
clip-path="url(http://127.0.0.1:1234/index.jsp?gwt.codesvr=127.0.0.1:9997#analysis_charts_first_chart-clip)">
<g class="stack _0">
<rect class="bar" fill="#1f77b4" y="133" height="132" width="532"
x="1">
<title>ds1 - missing: 50%</title>
</rect>
<rect class="bar" fill="#1f77b4" y="133" height="132" width="532"
x="534">
<title>ds3 - missing: 50%</title>
</rect>
</g>
<g class="stack _1">
<rect class="bar" fill="#ffbb78" y="87" height="46" width="532"
x="1">
<title>ds1 - something else: 17%</title>
</rect>
<rect class="bar" fill="#ffbb78" y="133" height="0" width="532"
x="534">
<title>ds3 - something else: 0%</title>
</rect>
</g>
<g class="stack _2">
<rect class="bar" fill="#aec7e8" y="0" height="87" width="532"
x="1">
<title>ds1 - total: 33%</title>
</rect>
<rect class="bar" fill="#aec7e8" y="0" height="133" width="532"
x="534">
<title>ds3 - total: 50%</title>
</rect>
</g>
</g>
<g class="axis x" transform="translate(50,275)">
<g class="tick" style="opacity: 1;" transform="translate(266.5,0)">
<line y2="6" x2="0" />
<text dy=".71em" style="text-anchor: middle;" y="9" x="0">ds1
</text>
</g>
<g class="tick" style="opacity: 1;" transform="translate(799.5,0)">
<line y2="6" x2="0" />
<text dy=".71em" style="text-anchor: middle;" y="9" x="0">ds3
</text>
</g>
<path class="domain" d="M0,6V0H1066V6" />
</g>
<text class="x-axis-label" transform="translate(583,305)"
text-anchor="middle">Datasets</text>
<g class="axis y" transform="translate(50,10)">
<g class="tick" style="opacity: 1;" transform="translate(0,265)">
<line x2="-6" y2="0" />
<text dy=".32em" style="text-anchor: end;" x="-9" y="0">0%</text>
</g>
<g class="tick" style="opacity: 1;" transform="translate(0,239)">
<line x2="-6" y2="0" />
<text dy=".32em" style="text-anchor: end;" x="-9" y="0">10%</text>
</g>
<g class="tick" style="opacity: 1;" transform="translate(0,212)">
<line x2="-6" y2="0" />
<text dy=".32em" style="text-anchor: end;" x="-9" y="0">20%</text>
</g>
<g class="tick" style="opacity: 1;" transform="translate(0,186)">
<line x2="-6" y2="0" />
<text dy=".32em" style="text-anchor: end;" x="-9" y="0">30%</text>
</g>
<g class="tick" style="opacity: 1;" transform="translate(0,159)">
<line x2="-6" y2="0" />
<text dy=".32em" style="text-anchor: end;" x="-9" y="0">40%</text>
</g>
<g class="tick" style="opacity: 1;" transform="translate(0,133)">
<line x2="-6" y2="0" />
<text dy=".32em" style="text-anchor: end;" x="-9" y="0">50%</text>
</g>
<g class="tick" style="opacity: 1;" transform="translate(0,106)">
<line x2="-6" y2="0" />
<text dy=".32em" style="text-anchor: end;" x="-9" y="0">60%</text>
</g>
<g class="tick" style="opacity: 1;" transform="translate(0,80)">
<line x2="-6" y2="0" />
<text dy=".32em" style="text-anchor: end;" x="-9" y="0">70%</text>
</g>
<g class="tick" style="opacity: 1;" transform="translate(0,53)">
<line x2="-6" y2="0" />
<text dy=".32em" style="text-anchor: end;" x="-9" y="0">80%</text>
</g>
<g class="tick" style="opacity: 1;" transform="translate(0,27)">
<line x2="-6" y2="0" />
<text dy=".32em" style="text-anchor: end;" x="-9" y="0">90%</text>
</g>
<g class="tick" style="opacity: 1;" transform="translate(0,0)">
<line x2="-6" y2="0" />
<text dy=".32em" style="text-anchor: end;" x="-9" y="0">100%</text>
</g>
<path class="domain" d="M-6,0H0V265H-6" />
</g>
<text transform="translate(12,142.5),rotate(-90)" class="y-axis-label y-label"
text-anchor="middle">Data Quality</text>
</g>
<defs>
<clipPath id="analysis_charts_first_chart-clip">
<rect width="1066" height="265" transform="translate(-0, -0)" />
</clipPath>
</defs>
</svg>
So I guess I am doing something wrong when trying to flatten the styles recursively.
I have a d3 / nvd3 graph which seems to be "clipped" by half...
Hereafter is the code (sorry, quite long, but a copy/paste in an html file works). Normally I have one bar by hour (so 24 bars) here I put only three hours.
The html is splitter in sections :
The legend [g class="nv-x nv-axis" transform="translate(0,235)"]
Y axis: [g class="nv-y nv-axis"]
One bar by hours: [g class="nv-barsWrap"]
We see only the top half of the Y axis and Bars, the bottom legend is lost. But it does exist on the html ! and we can "inspect" it... I don't get what is happening, but there is this "clip" rectangle I don't master... ( [clipPath id="nv-x-label-clip-6678"] )
<div id="chart">
<svg>
<g class="nvd3 nv-wrap nv-discreteBarWithAxes">
<g transform="translate(60,15)">
<defs>
<clipPath id="nv-x-label-clip-6678">
<rect width="20.912863070539423" height="16" x="-10.456431535269711">
</rect>
</clipPath>
</defs>
<g class="nv-x nv-axis" transform="translate(0,235)">
<g class="nvd3 nv-wrap nv-axis">
<g>
<g transform="translate(6.390041493775935,0)" style="opacity: 1;">
<line class="tick" y2="-235" x2="0">
</line>
<text y="3" dy=".71em" transform="translate(0,5)" x="0" style="text-anchor: middle;">00</text>
</g>
<g transform="translate(18.008298755186722,0)" style="opacity: 1;">
<line class="tick" y2="-235" x2="0">
</line>
<text y="3" dy=".71em" transform="translate(0,17)" x="0" style="text-anchor: middle;">01</text>
</g>
<g transform="translate(29.62655601659751,0)" style="opacity: 1;">
<line class="tick" y2="-235" x2="0">
</line>
<text y="3" dy=".71em" transform="translate(0,5)" x="0" style="text-anchor: middle;">02</text>
</g>
<path class="domain">
</path>
<text class="nv-axislabel" text-anchor="middle" y="36" x="140.00000000000003" transform="translate(0,17)">
</text>
</g>
</g>
</g>
<g class="nv-y nv-axis">
<g class="nvd3 nv-wrap nv-axis">
<g>
<g transform="translate(0,235)" style="opacity: 1;">
<line class="tick zero" x2="280" y2="0">
</line>
<text x="-3" dy=".32em" opacity="0" y="0" style="text-anchor: end;">0.0</text>
</g>
<g transform="translate(0,192.54290876242095)" style="opacity: 1;">
<line class="tick" x2="280" y2="0">
</line>
<text x="-3" dy=".32em" opacity="1" y="0" style="text-anchor: end;">200.0</text>
</g>
<g transform="translate(0,150.0858175248419)" style="opacity: 1;">
<line class="tick" x2="280" y2="0">
</line>
<text x="-3" dy=".32em" opacity="1" y="0" style="text-anchor: end;">400.0</text>
</g>
</g>
</g>
</g>
<g class="nv-barsWrap">
<g class="nvd3 nv-wrap nv-discretebar" transform="translate(0,0)">
<g>
<g class="nv-groups">
<g class="nv-group nv-series-0" style="stroke-opacity: 1; fill-opacity: 0.75;">
<g transform="translate(1.6846473217010498,0)" class="nv-bar positive" style="fill: #0088cc; stroke: #0088cc;">
<rect height="235" width="9.41078838174274" class="discreteBar">
</rect>
</g>
<g transform="translate(13.30290412902832,166.00723266601562)" class="nv-bar positive" style="fill: #0088cc; stroke: #0088cc;">
<rect height="68.99277326106593" width="9.41078838174274" class="discreteBar">
</rect>
</g>
<g transform="translate(24.921161651611328,175.98464965820312)" class="nv-bar positive" style="fill: #0088cc; stroke: #0088cc;">
<rect height="59.01535682023487" width="9.41078838174274" class="discreteBar">
</rect>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
</div>
It is most likely because the container does not have enough room to contain the graph. Add height=100% and width=100% or some arbitrary large number of pixels to test it out (to the div containing the chart).