By trying to rotate a square shaped element #sample
about its center using SVGTransform.setRotate
its shape gets distorted.
//REM: inserts return of getCurrentRotationOfSVGElementInDegrees(#sample) before the end of </body>
function addCurrentDegreesToBody(){
const
tElement = document.getElementById('sample'),
tDegrees = getCurrentRotationOfSVGElementInDegrees(tElement).toString();
document.body.insertAdjacentHTML('beforeEnd', `${tDegrees}<br />`)
};
//https://stackoverflow.com/questions/27557040/svg-find-rotation-angle-of-a-path
//REM: returns the angle of passed element in degrees
function getCurrentRotationOfSVGElementInDegrees(element){
const
tMatrix = element.transform.baseVal.getItem(0).matrix,
tDegrees = (180 / Math.PI) * Math.atan2(tMatrix.d, tMatrix.c) - 90;
return tDegrees < 0 ? tDegrees + 360 : tDegrees
};
//REM: Rotates #sample by +15° about its center
function rotateBy15Degrees(){
const
tElement = document.getElementById('sample'),
tAngle = getCurrentRotationOfSVGElementInDegrees(tElement),
tMatrix = tElement.transform.baseVal.getItem(0).matrix,
tBBox = tElement.getBBox();
setRotationSVG(
tElement,
tAngle + 15,
tBBox.x + tBBox.width / 2,
tBBox.y + tBBox.height / 2
)
};
//REM: sets the rotation of passed element to the passed angle about point (cx,cy)
//REM: and outputs the degrees in the <body>
function setRotationSVG(element, angle, cx, cy){
const
tTransform = element.ownerSVGElement.createSVGTransform(),
tAngle = getCurrentRotationOfSVGElementInDegrees(element);
//https://developer.mozilla.org/en-US/docs/Web/API/SVGTransform
//https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#rotate
//REM: Rotate to passed angle (opposite of current angle plus passed angle)
tTransform.setRotate(tAngle * -1 + angle, cx, cy);
element.transform.baseVal.appendItem(tTransform);
element.transform.baseVal.consolidate();
addCurrentDegreesToBody();
return element
};
<svg xmlns="http://www.w3.org/2000/svg" viewBox="1322 122 45 45" width="200px">
<!--REM: Expected result -->
<g id="sample" transform="matrix(0.208522,0.0256033,-0.0546508,0.445095,1023.54,-358.288)">
<g stroke-width="0.1" transform="matrix(1 0 0 1 0 0)">
<path d="m1902.15 1045.16v-46.74h-99.72v46.74z" fill="#1e90ff" fill-rule="evenodd"></path>
<path d="m1902.15 998.42v46.74h-99.72v-46.74z" fill="none" stroke="#fff"></path>
</g>
</g>
</svg>
<!--REM: Inline events for sample case-->
<button onclick="addCurrentDegreesToBody()">show degrees</button>
<button onclick="rotateBy15Degrees()">rotate by 15°</button>
<br /><br />
show degrees
By clicking on "show degrees" the script does the following steps:
- Calculate the current angle of
#sample
using its matrix - Output the angle before the end of
body
rotate by 15°
By clicking on "rotate by 15°" the script does the following steps:
- Calculate the current angle of
#sample
using its matrix - Rotate
#sample
by +15° about its center - Output the new angle before the end of
body
By doing that the shape of #sample
distorts => is not a square anymore. The outputed angle does not show an increase of +15° which I assume is due to the distorting issue.
How am I to use SVGTransform.setRotate
correctly, so that the shape of #sample
remains a square?
Update 26/08/2022
The issue seems to be the shape.
- If I use another shape like the one from enxaneta it works fine
- If I wrap the whole
#sample
in anotherg
and rotate that it works fine
I can showcase this in another fiddle here.