I want to programmatically rotate the hands of a clock designed in Inkscape as an SVG to make a custom designed Date/Time picker in the browser using Javascript/Jquery.
SVG:
<svg
width="2200"
height="1700"
viewBox="0 0 582.08332 449.79166"
sodipodi:docname="DateTimePicker.svg">
...
<g
inkscape:label="DateTimePicker"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,152.79168)">
<g
id="g4802"
inkscape:label="SecondsHand"
inkscape:transform-center-x="0.23194686"
inkscape:transform-center-y="-22.707409"
transform="translate(10.583327,-42.333328)">
.... (There are some paths in here to draw the shape)
</g>
<g
id="g4798"
inkscape:label="MinutesHand"
inkscape:transform-center-x="0.050484234"
inkscape:transform-center-y="-20.583753"
transform="translate(10.583352,-42.333325)">
.... (There are some paths in here to draw the shape)
</g>
<g
id="g4789"
inkscape:label="HoursHand"
inkscape:transform-center-x="-0.29101068"
inkscape:transform-center-y="-12.194587"
transform="translate(10.583295,-42.333339)">
<path
inkscape:transform-center-y="-12.335484"
sodipodi:nodetypes="ccccccccc"
inkscape:transform-center-x="-0.43053568"
inkscape:connector-curvature="0"
id="path3199"
d="m 424.77397,-31.058733 -2.7993,21.043385 c 0,0 -0.41499,2.6995795 0.88985,4.0317895 -0.089,0.23193 -0.1351,0.47814 -0.13589,0.72657 -1.3e-4,1.12967 0.91567,2.04548 2.04534,2.04536 1.12947,-1.6e-4 2.04496,-0.91589 2.04483,-2.04536 -1.8e-4,-0.24869 -0.0457,-0.49525 -0.13436,-0.7276 1.3035,-1.33258 0.88834,-4.0307595 0.88834,-4.0307595 z"
style="opacity:0.778;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.30000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter2507)"
inkscape:label="ShadowHourHand" />
<g
inkscape:transform-center-x="5.3889177e-06"
transform="translate(47.709026,-125.85737)"
inkscape:transform-center-y="-10.8713"
id="g3193"
inkscape:label="HourHand">
<path
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0"
id="path3183"
d="m 1423.707,324.97033 -10.58,72.17225 c 0,0 -1.5685,10.20314 3.3632,15.23828 -0.3366,0.87657 -0.5106,1.80713 -0.5136,2.74609 -5e-4,4.26959 3.4608,7.73091 7.7304,7.73047 4.2688,-6.1e-4 7.729,-3.46162 7.7285,-7.73047 -7e-4,-0.93992 -0.1727,-1.87183 -0.5078,-2.75 4.9266,-5.03651 3.3575,-15.23437 3.3575,-15.23437 z"
style="opacity:1;fill:url(#linearGradient4836);fill-opacity:1;stroke:none;stroke-width:1.13385832;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(0.26458333,0,0,0.26458333,0,11.249983)" />
<path
sodipodi:nodetypes="ccccccccccc"
inkscape:connector-curvature="0"
id="path3185"
transform="matrix(0.26458333,0,0,0.26458333,0,11.249983)"
d="m 1423.8672,338.32229 -6.9727,63.97654 0.2422,0.002 v 0.0215 c 8e-4,4.63516 3.1214,8.3923 6.9707,8.39257 3.8145,-0.002 6.919,-3.6962 6.9668,-8.28906 h 0.033 l -0.047,-0.67969 v -0.0176 -0.0215 z"
style="opacity:0.7;fill:#ffe25d;fill-opacity:1;stroke:none;stroke-width:1.13385832;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3111)" />
<path
inkscape:connector-curvature="0"
id="circle3187"
d="m 378.15497,121.08581 a 1.4660022,1.4660022 0 0 1 -1.46601,1.466 1.4660022,1.4660022 0 0 1 -1.466,-1.466 1.4660022,1.4660022 0 0 1 1.466,-1.466 1.4660022,1.4660022 0 0 1 1.46601,1.466 z"
style="opacity:1;fill:#ffe56a;fill-opacity:1;stroke:none;stroke-width:0.30000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter2836)" />
<path
sodipodi:nodetypes="scscs"
inkscape:connector-curvature="0"
id="path3189"
d="m 377.65184,117.39486 c 0,0.83592 -0.41881,1.51358 -0.93544,1.51358 -0.51663,0 -0.93544,-0.67766 -0.93544,-1.51358 0,-0.83592 0.35199,-2.54925 0.86862,-2.54925 0.51663,0 1.00226,1.71333 1.00226,2.54925 z"
style="opacity:0.70899999;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.30000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3146)" />
<path
inkscape:connector-curvature="0"
id="circle3191"
d="m 377.173,121.08581 a 0.48403955,0.48403955 0 0 1 -0.48404,0.48404 0.48403955,0.48403955 0 0 1 -0.48403,-0.48404 0.48403955,0.48403955 0 0 1 0.48403,-0.48404 0.48403955,0.48403955 0 0 1 0.48404,0.48404 z"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.30000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3168)" />
</g>
</g>
</g>'s as needed
This is what Inkscape calculates on the HoursHand for rotation increments of 15 degrees.
{
// 0 degrees
transform-center: (-0.29101049, -12.194589),
transform: translate(10.583294,-42.333341)
},
{
transform-center: (-2.679194, -11.668645),
transform: rotate(15,590.36335,14.32942)
},
{
transform-center: (-5.8379232, -10.278138),
transform: rotate(30,508.58162,-6.1159341)
},
{
transform-center: (-8.5291975, -8.1175788),
transform: rotate(45,480.68739,-13.089463)
},
{
transform-center: (-10.569195, -5.2923862),
transform: rotate(60,466.24828,-16.699228)
},
{
transform-center: (-11.819306, -1.9982106),
transform: rotate(75,457.17147,-18.968421)
},
{
transform-center: (-12.194588, 0.29100973),
transform: rotate(90,450.7532,-20.572983)
},
{
transform-center: (-11.668649, 2.679191),
transform: rotate(105,445.82829,-21.804206)
},
{
transform-center: (-10.278149, 5.8379174),
transform: rotate(120,441.80712,-22.809495)
},
{
transform-center: (-8.1175958, 8.5291943),
transform: rotate(135,438.35406,-23.672756)
},
{
transform-center: (-5.292401, 10.569196),
transform: rotate(150,435.25813,-24.446734)
},
{
transform-center: (-1.9982232, 11.819314),
transform: rotate(165,432.37318,-25.167967)
},
{
transform-center: (0.2910098, 12.194597),
transform: rotate(180,429.58653,-25.864625)
},
{
transform-center: (2.6792046, 11.668654)
transform: rotate(-165,426.79988,-26.561283)
},
{
transform-center: (5.837939, 10.278141),
transform: rotate(-150,423.91493,-27.282518)
},
{
transform-center: (8.1175808, 8.5292134),
transform: rotate(-135,420.819,-28.056498)
},
{
transform-center: (10.569206, 5.293819),
transform: rotate(-120,417.36594,-28.919761)
},
{
transform-center: (11.819324, 1.9982024),
transform: rotate(-105,413.34476,-29.925051)
},
{
transform-center: (12.194597, -0.29101935),
transform: rotate(-90,408.41985,-31.156276)
},
{
transform-center: (11.668649, -2.6792024),
transform: rotate(-75,402.00158,-32.760839)
},
{
transform-center: (10.278139, -5.8379339),
transform: rotate(-60,392.92477,-35.030033)
},
{
transform-center: (8.1175801, -8.5292112),
transform: rotate(-45,378.48565,-38.6398)
},
{
transform-center: (5.2923805, -10.569206),
transform: rotate(-30,350.59142,-45.613334)
},
{
transform-center: (1.9982049, -11.819318),
transform: rotate(-15,268.80967,-66.058702)
}
Here is some Javascript I ran on the HoursHand at 0 degrees:
CTM: SVGMatrix
a: 0.6871868371963501
b: 0
c: 0
d: 0.6871868371963501
e: 7.272700786590576
f: 76.36006927490234
boundingBox: SVGRect
height: 28.33203125
width: 6.1015625
x: 421.53515625
y: -31.05859375
boundingClientRect: DOMRect
bottom: 74.5
height: 19.5
left: 296.933349609375
right: 301.15000915527344
top: 55
width: 4.2166595458984375
x: 296.933349609375
y: 55
0: <g id="g4789" inkscape:label="HoursHand" inkscape:transform-center-x="-0.29101068" inkscape:transform-center-y="-12.194587" transform="translate(10.583295,-42.333339)">
screenCTM: SVGMatrix
a: 0.6871868371963501
b: 0
c: 0
d: 0.6871868371963501
e: 7.272700786590576
f: 76.36006927490234
transform: "translate(10.583295,-42.333339)"
transform_center_x: "-0.29101068"
transform_center_y: "-12.194587"
Inverse CTM = (a,d = 1.45522, b,c = 0, e = -10.58339, f = -111.12089)
What I want to know is for some arbitrary object, starting with HoursHand, and any degree or rotation, how to calculate the transform-center x and y, as well as the x and y of the center of rotation, for that degree as Inkscape calculates it.
Note: The transform-center here is off center, and I want to use Javascript rather than rely on CSS since SVG transforms are handled differently than CSS transforms, so the method explained here will not work: SVG Animation rotate group around its center
Update 1: I've read what I can understand of the relevant chapter mentioned in this answer: Why am I failing to rotate a path around a given point in SVG pointing to this text: https://www.w3.org/TR/SVG/coords.html#TransformProperty which helped some.
The issue here though is that my paths coming out of Inkscape have coordinates like m 424.77397,-31.058733 in their user coordinate space. If you notice, at 15 degree rotation on the HoursHand I have rotate(15,590.36335,14.32942) and at 30 degrees I have rotate(30,508.58162,-6.1159341), the center of rotation on the transform has changed drastically on the x-axis.
So some angle-finding code needs to be applied to pre-determine where the center of rotation needs to be when rotating instead of the translate(~10,~-42) in the current user coordinate space, which is where I need help.
The sane way to do this in Inkscape is to select a group node that has a "transform: translate(x, y)" attribute, and remove the transform. Then select the group's child nodes and position where the group node needed. On the Javascript side I needed to remember the center point positions for transformations before rotating. The Hours, Minutes, and Seconds hand all share the same center point for rotation, which needs to be absolute positioned relative to the bounding box coordinates obtained with getBBox().
Knowing how to do rotations in an SVG user coordinate system with a group that is translated and has a transformation center that is off-center could still be advantageous in some situations though.