I have the following (simplified) SVG:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 120 100" preserveAspectRatio="none" >
<script type="text/ecmascript">
<![CDATA[
function getPathLength(path)
{
alert(path.getTotalLength());
}
]]>
</script>
<rect x="0" y="0" width="100%" height="100%" fill="black"/>
<path id="word" onclick="getPathLength(this);" fill="none" stroke="red" stroke-dasharray="83,83"
d="M 8.90625 3.78125 C 8.5377448 3.8134782 8.1622587 3.965423 7.8125 4.21875 C 6.5568946 6.0743722 5.8966744 8.1275786 5.125 10.15625 C 5.2012388 11.683341 4.3280721 13.093169 4.34375 14.59375 C 3.5435523 17.003468 4.9013748 18.393271 4.125 20.90625 C 3.8249969 23.220653 3.3490969 25.389271 2.96875 27.71875 C 2.775721 29.626027 1.7870007 33.314518 4.6875 33.4375 C 6.6892564 33.267533 8.9446263 33.620664 10.6875 32.53125 C 12.308551 32.345986 13.845824 31.488491 14.96875 30.4375 C 15.336184 29.709947 14.506173 29.249547 15.09375 28.53125 C 15.464699 26.390933 13.333175 28.42555 12.53125 28.4375 C 10.625482 29.096293 8.8511553 29.69647 6.875 29.65625 C 5.6218253 29.22028 6.5435685 27.168764 6.34375 26.03125 C 6.6314225 24.872659 6.8389714 23.78868 7.0625 22.53125 C 7.4982943 20.310119 8.0925706 18.009049 8.5 15.84375 C 9.2688601 14.209069 9.0995411 12.312299 9.71875 10.5625 C 10.027547 9.1134942 10.141384 7.3374588 10.5 5.90625 C 10.999008 4.514099 10.011766 3.6845653 8.90625 3.78125 z ">
<animate attributeName="stroke-dashoffset" begin="0s" from="100%" to="0%" dur="5s" fill="freeze" />
</path>
</svg>
When I click on the path to get the length Firefox v16 reports 82.4... which is what I use for the dasharray. But it starts out with part of the path already drawn, erases it then draws the full path again!? I tinkered witht he dasharay values and it works when I use 110 but I don't know why!
I have not tried other browsers or newer versions of Firefox yet...
NOTE The full problem is a word converted to a path. The path is discontinuous - it has 5 parts (there is a loop in the script forms of 'e', 'z' and 'h' and the first letter 'L' is not joined with the rest). What I want to do is make it look like a laser is drawing the letters. In a previous questions I learned that animating the dashoffset will acheive that effect. I was finally able to convert text to path using Inkscape. Now I am having trouble animating.
I tried animating the dasharray. That works for the correct length, but with the larger full word example (which is 7 letters long and 822 units long) it looks like several paths are in play - not just the 5 discontinuous parts but 9 different paths. When I try to animate the dashoffset on the full word I see NO animation at all - the word just appears fully formed.
Did you think 100% would be 100% of the length of the path? If so that's where you're going wrong as it's 100% of the viewport width. I don't think Opera and Firefox have a bug here, particularly as they happen to be displaying things identically.
Figured it out. I was trying to be cute by using a percentage so that I did not have to put the length in each animate command - all my animates were 100% to 0%. When I replaced the percentages with the actual lengths it worked as expected.
So looks like a bug in the SVG implementations of at least Firefox and Opera as the documentation clearly says you can use percentages...
Related
I have a javascript app (CAD like) build in SVG that have tools (objects build in SVG with Inkscape) that are inserted with the use tag. Everything works fine on Chrome and Safari (never tested in IE), but in Firefox, all objects that fill with gradients did not render. Like image below:
Firefox
Chrome
The tools are loaded like this (using external files)
<use
id="SvgjsUse1448"
xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="assets/images/neomap/tools/armchair.svg#armchair">
</use>
The gradients are defined in a separate svg inside the html page
...
<linearGradient xmlns="http://www.w3.org/2000/svg" id="armchair_SVGID_1_" y2="1911.6" gradientUnits="userSpaceOnUse" x2="1201.2" gradientTransform="matrix(1.0799475,0,0,1.2039969,15.269894,2.997636)" y1="467.91" x1="1201.7">
and apply like this
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" height="100%" width="100%" version="1.1" >
<defs>
<symbol id="armchair" viewBox="0 0 72000 54000">
<path style="stroke:#000000;stroke-width:6.84171867;stroke-miterlimit:10;fill:url(#armchair_SVGID_1_);" d="m2234.8,743.7s168.9,1406.4,0,1487.4c-188.77,90.42-1655.6,92.708-1844.3-0.4817-168.8-83.316,0-1488.9,0-1488.9v-182.09h1841l3.2398,184.09z"/>
...
</symbol>
</defs>
</svg>
It's a bug on Firefox? How can I workaround?
I had a similar problem and it turned out that mine was a real edge case, so I'm posting my solution here for the benefit of others.
My goal was to define a set of icons for later reuse in the document. I had defined the icons as nested svg documents inside a defs element:
<svg id="icons">
<defs>
<g id="atom-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256">
<defs>
<linearGradient id="atom-41-a" x1="50%" x2="50%" y1="3.961%" y2="100%">
<stop offset="0%" stop-color="#FDFDFD"/>
<stop offset="100%" stop-color="#CBCBCB"/>
</linearGradient>
<linearGradient id="atom-41-b" x1="50%" x2="50%" y1="3.961%" y2="100%">
<stop offset="0%" stop-color="#B2E198"/>
<stop offset="100%" stop-color="#04A171"/>
</linearGradient>
</defs>
<g fill="none">
<circle cx="128" cy="128" r="127.858" fill="url(#atom-41-a)"/>
<circle cx="127.858" cy="128.142" r="116.907" fill="url(#atom-41-b)"/>
<path fill="#F2F8F6" d="M100.453 110.097a221.783 221.783 0 0 0-3.988 6.382 164.44 164.44 0 0 1-3.684-11.377c3.73-.535 7.695-.957 11.874-1.249a224.886 224.886 0 0 0-4.202 6.244zm103.138 7.475c-4.132-3.967-10.04-7.602-17.558-10.804-14.926-6.356-34.918-10.474-56.295-11.595a234.82 234.82 0 0 0-7.529-.277C138.53 75.415 154.292 65.05 163.472 64.7c1.944-.074 3.576.31 4.854 1.141 4.296 2.792 5.488 11.453 3.189 23.166a4.267 4.267 0 0 0 8.373 1.644c3.953-20.137-1.576-28.497-6.911-31.965-2.785-1.81-6.093-2.655-9.83-2.513-14.12.536-33.904 15.592-51.956 38.803-7.148.247-14.038.864-20.483 1.827a106.106 106.106 0 0 1-1.625-9.522c-1.619-13.344.367-22.816 5.312-25.337.794-.405 1.662-.639 2.654-.713 4.418-.332 10.652 2.637 17.542 8.359a4.267 4.267 0 0 0 5.452-6.565c-8.85-7.35-16.8-10.817-23.633-10.303-2.112.158-4.095.703-5.892 1.62-4.593 2.342-7.732 6.828-9.33 13.331-1.368 5.57-1.562 12.513-.576 20.636.39 3.213.96 6.556 1.695 9.998-5.04 1.062-9.71 2.356-13.897 3.869-18.316 6.616-22.544 15.337-22.866 21.488-.308 5.876 2.7 14.62 18.775 22.91a4.267 4.267 0 0 0 3.911-7.583c-9.247-4.77-14.41-10.193-14.165-14.88.346-6.605 11.417-13.596 30.274-17.535 1.747 6.309 3.99 12.861 6.68 19.505-6.777 12.723-11.722 25.262-14.286 36.416-1.833 7.97-2.369 14.89-1.592 20.567.906 6.63 3.558 11.418 7.881 14.228 2.205 1.433 5.176 2.553 9.079 2.553 5.658 0 13.275-2.357 23.343-9.538a4.267 4.267 0 1 0-4.955-6.948c-9.925 7.08-18.454 9.613-22.816 6.778-4.652-3.023-5.633-12.642-2.624-25.728 1.995-8.678 5.555-18.296 10.383-28.21a220.995 220.995 0 0 0 3.283 6.731c9.717 19.087 21.612 35.694 33.494 46.762 5.984 5.573 11.708 9.497 17.011 11.663 3.218 1.314 6.24 1.971 9.045 1.971 2.596 0 5.008-.563 7.216-1.69 4.43-2.259 7.511-6.52 9.157-12.665 1.41-5.263 1.726-11.827.942-19.512-1.543-15.11-7.253-33.539-16.077-51.891a4.267 4.267 0 0 0-7.69 3.697c8.407 17.485 13.833 34.908 15.278 49.06 1.27 12.447-.78 21.31-5.486 23.71-4.942 2.52-13.756-1.438-23.58-10.588-11.17-10.404-22.43-26.168-31.706-44.388a210.555 210.555 0 0 1-5.851-12.483 210.936 210.936 0 0 1 7.143-11.836 213.301 213.301 0 0 1 7.877-11.333c.7-.01 1.405-.017 2.115-.019 3.664-.012 7.592.09 11.688.305 20.404 1.07 39.368 4.95 53.399 10.925 12.34 5.256 19.534 11.704 19.244 17.25-.246 4.708-5.967 9.575-15.696 13.352a4.267 4.267 0 0 0 3.088 7.955c16.905-6.563 20.821-14.967 21.13-20.861.27-5.151-2.04-10.111-6.865-14.743v.001z"/>
<path fill="#F1F8F3" d="M119.194 129.133c0 5.153 4.174 9.33 9.323 9.33s9.323-4.177 9.323-9.33c0-5.154-4.174-9.331-9.323-9.331s-9.323 4.177-9.323 9.33"/>
</g>
</svg>
</g>
</defs>
</svg>
Which I used elsewhere in the document like so:
<li title="Atom">
<svg><use xlink:href="#atom-icon"/></svg>
</li>
In order to prevent the big list of icons references from rendering on screen, I had applied the following styles:
#icons {
display: none;
}
This caused, of all things, the url references to linearGradients to stop working. Probably the browsers removed them from the DOM tree because of display: none or some such effect.
The solution was the change the styles:
#icons {
height: 0;
}
That's a Chrome/Safari bug you're relying on.
url(#armchair_SVGID_1_);
is actually shorthand for
url(<this file>#armchair_SVGID_1_);
but there's no gradient in the armchair.svg file.
The definition of what a base URI is is in RFC3986 section 5 which says
Within certain media types, a base URI for relative references can be
embedded within the content itself so that it can be readily obtained
by a parser.
There's a note in the CSS specification referring to this which I think makes a clearer statement (at least for CSS since this is the CSS specification):
For CSS style sheets, the base URI is that of the style sheet, not that of the source document.
The file armchair.svg defines a base URI the same as any SVG document or CSS stylesheet does, it's the absolute URL used to access it.
Webkit browsers get this wrong. There's this bug for the CSS stylesheets case of this issue.
Use an absolute url or put the gradient in the use file (but not in the symbol part).
It's really a Chrome/Safari bug.
I figured out, that the problem goes away if you remove all the hyphens from the linearGradient elements' IDs. Simple as that. SVG then works with groups too ().
I would be glad, if that helps somebody...
Firefox is behaving correctly according to the spec for the SVG <symbol> element. With SVG any element that are nested inside a <symbol> element or <defs> element are not directly rendered with CSS, even with a <use> element. Only their attributes are. You are using the style attribute, which is CSS inside the <symbol> element.
You must use the SVG fill attribute directly to have it work inside a <symbol> element. Even though you are using a SVG <use> element. It is referencing SVG graphical elements inside a SVG <symbol> element with the CSS style attribute, which will not be rendered according to the spec, since the CSS display property does not even apply to the SVG <symbol> element.
This is not a bug in Firefox, Firefox honors the spec whereas Chrome and Safari which use webkit, do not follow the spec and allow it for now. But they will soon follow the SVG spec.
See these references and the spec:
W3C <symbol> spec: http://www.w3.org/TR/SVG11/struct.html#SymbolElement
‘symbol’ elements are never rendered directly; their only usage is as something that can be referenced using the ‘use’ element. The ‘display’ property does not apply to the ‘symbol’ element; thus, ‘symbol’ elements are not directly rendered even if the ‘display’ property is set to a value other than none, and ‘symbol’ elements are available for referencing even when the ‘display’ property on the ‘symbol’ element or any of its ancestors is set to none.
MDN Firefox <symbol> element reference: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/symbol
The symbol element is used to define graphical template objects which can be instantiated by a element. The use of symbol elements for graphics that are used multiple times in the same document adds structure and semantics. Documents that are rich in structure may be rendered graphically, as speech, or as braille, and thus promote accessibility. note that a symbol element itself is not rendered. Only instances of a symbol element (i.e., a reference to a symbol by a element) are rendered.
The spec states that SVG elements inside the <symbol> element are not directly rendered. In that case you need to change the actually attributes of those elements inside a <symbol> element or <defs> elements. So just change the SVG fill attribute instead on those elements inside the <symbol> element.
Ok, this is a bug, but also an interpretation from the W3 Spec. In this section is specified two types of IRI local, and non-local.
local IRI references, where the IRI reference does not contain an or and thus only contains a fragment identifier
non-local IRI references, where the IRI reference does contain an <absoluteIRI> or <relativeIRI> and thus represents a reference to an element within the current document.
What I see, is that Chrome/Safari are more flexible when dealing with the specification, allowing the local IRI to reference an external document, if it not exist in the current document.
The point is, Chrome/Safari doesn't render the gradients of an external SVG file (loaded by reference, in a use tag) that are at the same external file, only if the gradients are loaded in the current main html/xml document.
So, I create two files for each SVG tool, one for Firefox, and one for other browsers. And now another problem as came up, for low values of transform: scale() in a g element, or small SVG elements, the gradient disappear (transparent), and this I believe is a bug.
I'm facing a problem that I thought would have been easier to solve than it actually is.
I want to create a puzzle with 4860 pieces for a game. The mesh of the puzzle is made with SVG. Below I'm reporting part of the code, just to give you an idea. The code is working as you can see in the last link I gave you.
I created in defs a list of paths (18 in total), then a long list of 4860 so that I can make my puzzle.
When the mouse moves over one piece, I want this piece to be highlighted.
That's the code (first part), followed by a series of tags like the one in the example.
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" width="1200" height="1200" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" xml:space="preserve">
<defs>
<style type="text/css">
.use1 {
stroke: #000000;
fill: #ffffff;
fill-opacity: 0.1;
stroke-linecap: butt;
}
.use1:hover {
fill: #ffffff;
fill-opacity: 0.8;
stroke: #3273BE;
stroke-width: 10;
}
.base {
}
</style>
<path id="a0" d="m152.199493 121.414993c-0.349991 2.4 -0.3 4.8 0 7.169998c1.200012 8.3 6.6 15.9 16.3 17.419998c12.858994 2 14 -5.5 23.2 . (...) "/>
.... the other 17 paths .....
</defs>
<image x="0" y="0" width="1200" height="720" xlink:href="lana-del-rey-ultraviolence-recensione.jpg" />
<use xlink:href="#C5" x="-50" y="-50" transform="scale(0.088) rotate(0)" class="use1" id="1"/>
....
... x 4860 ....
....
</svg>
You can see the result here:
http://www.ridiesorridi.it/puzzle/17.svg
If you open it in Safari or IE it works PERFECTLY with no lag. If you open in Chrome or Firefox to highlight a piece it's extremely slow. You can imagine when I put this SVG inside an HTML page ... !! Instead in IE and Safari it keeps working great.
My question is: how can I solve this problem with Chrome and Firefox?
I've already tried to remove extra decimals (to "optimize svg") but it didn't work.
Edit I noticed that in Chrome and Firefox, if I zoom in (like 400%) it works PERFECTLY. Once it has all the elements together, it keeps having problems (compared to IE and Safari)
Reducing accuracy would only help parsing speed. Once the SVG was parsed, it shouldn't make a difference.
I am not sure what, if any, optimisations FF and Chrome use when testing hover for SVG elements. But I would certainly try reducing the complexity of the pieces. For instance, the piece "g1" has 89 path commands in its definition. You should be able to reduce that by 4x, at least, and still get an accurate jigsaw piece shape.
I am trying to use non-linear animation rate on an SVG <animateMotion> by using the keyTimes="…" and keyPoints="…" attributes. It does not appear to be working: the animation motion is as linear as can be.
Here's the test file try it!
<svg xmlns="http://www.w3.org/2000/svg" xmlns:x="http://www.w3.org/1999/xlink"
viewBox="0 0 300 200">
<style>
path { stroke:#999 }
circle { fill-opacity:0.5; stroke:black }
</style>
<path id="p" d="M30,160 L270,40" />
<circle id="c" r="5" />
<animateMotion x:href="#c" fill="freeze"
dur="10s"
keyTimes="0;0.1;1"
keyPoints="0;0.9;1">
<mpath x:href="#p" />
</animateMotion>
</svg>
When working the ball should move 90% along the path in the first second, and move the final 10% in the remaining 9 seconds. What do I need to change to get this to work?
I've found another example online that is working correctly, so that I know it's not my OS/browser/version at fault.
(FWIW: Win7x64, Chrome30)
I found my mistake. Even though the default value for calcMode is linear—which is what I want—I didn't read far enough into the spec to see that it's a different default value for <animateMotion> elements.
Adding an explicit calcMode="linear" fixes the problem.
The default calcmode Value for animate Motion is paced not linear;
http://www.w3.org/TR/SVG/animate.html#AnimateMotionElement
And, if calcmode = "paced" is specified, any ‘keyTimes’ or ‘keySplines’ will be ignored.
http://www.w3.org/TR/SVG/animate.html#CalcModeAttribute;
That is why you have not got the the desired output...
There are a number of JavaScript snippets that will make text or graphics travel along a circular path with the letters or words always upright.
Example: http://www.dseffects.com/f_scripts.html
I want to have text (or graphics) orbit a point the way the moon orbits the Earth, with one face always toward the center. The following example shows this, but very crudely and not using web fonts.
Example: http://javaboutique.internet.com/text/Manipulation/TextRotor/
I am sure there is a way to modify orbiting code like the first example (only not around the cursor) so that each letter/image keeps one side toward the center (axis).
SVG really is the way to go for this kind of thing. I just whipped this up really quick but at least it works as an example. The HTML part can vary a lot but this is one way.
Put this into an html page:
<iframe src="orbitingText.svg" width="100%" height="100%"></iframe>
Then, create the orbitingText.svg file (it's just a text file with a .svg extension):
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 300 300">
<defs>
<path id="textPath" d="M 150 75 a 75 75 0 1 0 0.00001 0"/>
</defs>
<circle cx="150" cy="150" r="40" stroke="blue" stroke-width="1"></circle>
<text fill="red">
<textPath xlink:href="#textPath" startOffset="0">
<animate attributeName="startOffset" dur="7s" from="0" to="500" repeatCount="indefinite" />
Orbiting Text
</textPath>
</text>
Oh, and if you are worried about cross-browser compatibility, check out this site:
http://code.google.com/p/svgweb/
I made a logo in Inkscape. For learning I wanted to make a wheel shape in the logo rotate by the animation support in SVG.
It was easy to implement the rotation, but it was difficult for me to be able to specify the correct axis of rotation. The shape was a cog wheel and I wanted it to rotate around its center. Trial and error gave that the xy-coordinate (47.1275, 1004.17) (whose components are strangely asymmetric, but I guess that has to do with the transformation matrices Inkscape applies) was a good approximation (see animateTransform tag below), but how would I get that from first principles?
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 321.281 150.799" xmlns:dc="http://purl.org/dc/elements/1.1/">
<g transform="translate(-9.9178912,-891.57237)">
<g transform="matrix(1.9522781,0,0,1.9522781,4.6434311,-1008.1558)">
<animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 47.1275 1004.17" to="45 47.1275 1004.17" dur="2s" fill="freeze" additive="sum" repeatCount="indefinite" />
<g transform="matrix(0.65043772,0,0,0.65043772,-143.67477,980.4256)" stroke="#666" stroke-miterlimit="4" stroke-dasharray="none" stroke-width="7.68713093" fill="none">
<path stroke-linejoin="miter" d="m293.404-3.51576c-2.73916,0-5.41514,0.287192-8,0.8125v6.1875c-3.47484,0.838872-6.7198,2.18462-9.6875,4l-4.375-4.375c-2.24264,1.48612-4.29226,3.22977-6.1875,5.125s-3.63888,3.94486-5.125,6.1875l4.375,4.375c-1.81538,2.9677-3.16112,6.21265-4,9.6875h-6.1875c-0.5253,2.58486-0.8125,5.26083-0.8125,8s0.2872,5.41515,0.8125,8h6.1875c0.83888,3.47485,2.18462,6.7198,4,9.6875l-4.375,4.375c1.48612,2.24264,3.22976,4.29227,5.125,6.1875s3.94486,3.63888,6.1875,5.125l4.375-4.375c2.9677,1.81538,6.21266,3.16113,9.6875,4v6.1875c2.58486,0.525308,5.26082,0.8125,8,0.8125,2.73916,0,5.41514-0.287192,8-0.8125v-6.1875c3.47484-0.838872,6.7198-2.18462,9.6875-4l4.375,4.375c2.24264-1.48612,4.29226-3.22977,6.1875-5.125s3.63888-3.94486,5.125-6.1875l-4.375-4.375c1.81538-2.9677,3.16112-6.21266,4-9.6875h6.1875c0.5253-2.58485,0.8125-5.26083,0.8125-8s-0.2872-5.41515-0.8125-8h-6.1875c-0.83888-3.47485-2.18462-6.7198-4-9.6875l4.375-4.375c-1.48612-2.24264-3.22976-4.29227-5.125-6.1875s-3.94486-3.63888-6.1875-5.125l-4.375,4.375c-2.9677-1.81538-6.21266-3.16113-9.6875-4v-6.1875c-2.58486-0.525308-5.26084-0.8125-8-0.8125z" stroke-dashoffset="162" stroke="#666" stroke-linecap="butt" stroke-miterlimit="4" stroke-dasharray="none" stroke-width="7.68713093" fill="none"/>
</g>
</g>
</g>
</svg>
From what I've read in the specification I would say the transformation matrices applied are
1.9522781 0 4.6434311
0 1.9522781 -1008.1558
0 0 1
and
0.65043772 0 -143.67477
0 0.65043772 980.4256
0 0 1
Are they applied on the xyz-coordinate (-9.9178912,-891.57237,0) after the translation transformation?
I guess a correct analysis above would get me the top left point of the path described, or maybe the coordinate for the first handle. After that, does one have to parse the path to decide the bounding-box and thereby the center (since it concerns a somewhat circular object) of the path?
Is it all a lesson in not trying to manually do animation on freely created shapes?
I think the transformations will be applied from the innermost outward, so transform="translate(-9.9178912,-891.57237)" will be done last. But you can ignore the other transformations if you put your animation in the innermost region, i.e. within the path itself:
<g transform1>
<g transform2>
<g transform3>
<path d="coordinates">
<animateTransform your transformation here>
</path>
</g>
</g>
</g>
Then you just need to find the centre of your path, which is easy to do in Inkscape, but tricky to do on-the-fly (related question here: programmatically How to get shape width in SVG document using java).
Personally, I'd use a script within the svg so you can use getBBox to find the bounding box of your shape. If you add the following element into your SVG you can make any element with the id="cog" turn about its centre:
<script type="text/ecmascript"><![CDATA[
var svgNS = "http://www.w3.org/2000/svg";
function init(evt)
{
if ( window.svgDocument == null )
{
svgDocument = evt.target.ownerDocument;
}
addRotateTransform('cog');
}
function addRotateTransform(target_id)
{
var element_to_rotate = svgDocument.getElementById(target_id);
var my_transform = svgDocument.createElementNS(svgNS, "animateTransform");
var bb = element_to_rotate.getBBox();
var cx = bb.x + bb.width/2;
var cy = bb.y + bb.height/2;
my_transform.setAttributeNS(null, "attributeName", "transform");
my_transform.setAttributeNS(null, "attributeType", "XML");
my_transform.setAttributeNS(null, "type", "rotate");
my_transform.setAttributeNS(null, "dur", "4s");
my_transform.setAttributeNS(null, "repeatCount", "indefinite");
my_transform.setAttributeNS(null, "from", "0 "+cx+" "+cy);
my_transform.setAttributeNS(null, "to", "360 "+cx+" "+cy);
element_to_rotate.appendChild(my_transform);
my_transform.beginElement();
}
]]></script>
You also need to add onload="init(evt)" as an attribute to the SVG tag. e.g.
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 321.281 150.799"
xmlns:dc="http://purl.org/dc/elements/1.1/"
onload="init(evt)">
This will call the init() function when the SVG is first loaded. The init() function calls addRotateTransform() which find the element with a given id. It then finds the centre of that object using getBBox() and adds an animateTransform method with the relevant centres. You can change the dur attribute which determines the speed of a full rotation.
It might seem like a lot of code, but I think it's the easiest way to determine the centre of a path. It also means to can easily add other rotating elements by add addRotateTransform('whatever-id'); to the init() function.