I'm trying to scale an <g></g>
called #RectangleScaled
by a 1.4 factor from the group center.
I'm using this formula
translate(-centerX*(factor-1), -centerY*(factor-1)) scale(factor)
But the red rectangle doesn't seem to have the right translation
Here is my implementation
var rectangle = document.querySelector("#Rectangle")
var rectangleScaled = document.querySelector("#RectangleScaled")
var canvasBbox = document.querySelector("#Canvas").getBBox()
var x = -canvasBbox.width/2*(1.4-1)
var y = -canvasBbox.height/2*(1.4-1)
rectangleScaled.style.transform = "translate("+x+"px, "+y+"px) scale(1.4)"
Svg
<svg width="411" height="731" viewBox="0 0 411 731" version="1.1" xmlns="" xmlns:xlink="">
<g id="Canvas" transform="translate(721 384)">
<clipPath id="clip-0" clip-rule="evenodd">
<path d="M -721 -384L -310 -384L -310 347L -721 347L -721 -384Z" fill="#FFFFFF"/>
</clipPath>
<g id="Google Pixel" clip-path="url(#clip-0)">
<path d="M -721 -384L -310 -384L -310 347L -721 347L -721 -384Z" fill="#FFFFFF"/>
<g id="RectangleScaled">
<use xlink:href="#path1_fill" transform="translate(-614 -152)" fill="red"/>
</g>
<g id="Rectangle">
<use xlink:href="#path0_fill" transform="translate(-614 -152)" fill="#C4C4C4"/>
</g>
</g>
</g>
<defs>
<path id="path0_fill" d="M 0 0L 196 0L 196 266L 0 266L 0 0Z"/>
<path id="path1_fill" d="M 0 0L 196 0L 196 266L 0 266L 0 0Z"/>
</defs>
</svg>
Here is the fiddle
I'm trying to scale an <g></g>
called #RectangleScaled
by a 1.4 factor from the group center.
I'm using this formula
translate(-centerX*(factor-1), -centerY*(factor-1)) scale(factor)
But the red rectangle doesn't seem to have the right translation
Here is my implementation
var rectangle = document.querySelector("#Rectangle")
var rectangleScaled = document.querySelector("#RectangleScaled")
var canvasBbox = document.querySelector("#Canvas").getBBox()
var x = -canvasBbox.width/2*(1.4-1)
var y = -canvasBbox.height/2*(1.4-1)
rectangleScaled.style.transform = "translate("+x+"px, "+y+"px) scale(1.4)"
Svg
<svg width="411" height="731" viewBox="0 0 411 731" version="1.1" xmlns="http://www.w3/2000/svg" xmlns:xlink="http://www.w3/1999/xlink">
<g id="Canvas" transform="translate(721 384)">
<clipPath id="clip-0" clip-rule="evenodd">
<path d="M -721 -384L -310 -384L -310 347L -721 347L -721 -384Z" fill="#FFFFFF"/>
</clipPath>
<g id="Google Pixel" clip-path="url(#clip-0)">
<path d="M -721 -384L -310 -384L -310 347L -721 347L -721 -384Z" fill="#FFFFFF"/>
<g id="RectangleScaled">
<use xlink:href="#path1_fill" transform="translate(-614 -152)" fill="red"/>
</g>
<g id="Rectangle">
<use xlink:href="#path0_fill" transform="translate(-614 -152)" fill="#C4C4C4"/>
</g>
</g>
</g>
<defs>
<path id="path0_fill" d="M 0 0L 196 0L 196 266L 0 266L 0 0Z"/>
<path id="path1_fill" d="M 0 0L 196 0L 196 266L 0 266L 0 0Z"/>
</defs>
</svg>
Here is the fiddle
Share Improve this question asked Feb 17, 2018 at 17:20 zaarr78zaarr78 47710 silver badges23 bronze badges 2- Could you clarify, what exactly would you like to do, because I don't get it? Just scale it but leave centered, or scale and move it? – mpro Commented Feb 17, 2018 at 18:30
- I want to scale the red rectangle to 1.4 but I dont want it to move I only want it to scale from his center position, if you only try to do scale(1.4) you will see that the rectangle is scaling but also moving which is not what I want – zaarr78 Commented Feb 17, 2018 at 18:44
3 Answers
Reset to default 4You appear to have got your centre wrong. You are scaling around the wrong centre point.
You are dividing canvasBBox
width
and height
by two, but you are not taking into account the x
and y
values of the bbox.
The centre of the #Canvas
element is at
var cx = canvasBbox.x + canvasBbox.width/2;
var cy = canvasBbox.y + canvasBbox.height/2;
If you update the calculation with these values, you get your expected result.
var rectangle = document.querySelector("#Rectangle")
var rectangleScaled = document.querySelector("#RectangleScaled")
var canvasBbox = document.querySelector("#Canvas").getBBox()
var cx = canvasBbox.x + canvasBbox.width/2;
var cy = canvasBbox.y + canvasBbox.height/2;
var x = -cx * (1.4 - 1)
var y = -cy * (1.4 - 1)
rectangleScaled.style.transform = "translate("+x+"px, "+y+"px) scale(1.4)"
<svg width="411" height="731" viewBox="0 0 411 731" version="1.1" xmlns="http://www.w3/2000/svg" xmlns:xlink="http://www.w3/1999/xlink">
<g id="Canvas" transform="translate(721 384)">
<clipPath id="clip-0" clip-rule="evenodd">
<path d="M -721 -384L -310 -384L -310 347L -721 347L -721 -384Z" fill="#FFFFFF"/>
</clipPath>
<g id="Google Pixel" clip-path="url(#clip-0)">
<path d="M -721 -384L -310 -384L -310 347L -721 347L -721 -384Z" fill="#FFFFFF"/>
<g id="RectangleScaled">
<use xlink:href="#path1_fill" transform="translate(-614 -152)" fill="red"/>
</g>
<g id="Rectangle">
<use xlink:href="#path0_fill" transform="translate(-614 -152)" fill="#C4C4C4"/>
</g>
</g>
</g>
<defs>
<path id="path0_fill" d="M 0 0L 196 0L 196 266L 0 266L 0 0Z"/>
<path id="path1_fill" d="M 0 0L 196 0L 196 266L 0 266L 0 0Z"/>
</defs>
</svg>
Only for Chrome (consider it as a bug):
For scale and keep the scaled element in the center position you can do it with pure CSS, by adding transform-origin: center;
style to #RectangleScaled
selector.
var rectangle = document.querySelector("#Rectangle")
var rectangleScaled = document.querySelector("#RectangleScaled")
var canvasBbox = document.querySelector("#Canvas").getBBox()
rectangleScaled.style.transform = "scale(1.4)"
svg {
border:solid;
}
#RectangleScaled {
transform-origin: center;
}
<svg width="411" height="731" viewBox="0 0 411 731" version="1.1" xmlns="http://www.w3/2000/svg" xmlns:xlink="http://www.w3/1999/xlink">
<g id="Canvas" transform="translate(721 384)">
<clipPath id="clip-0" clip-rule="evenodd">
<path d="M -721 -384L -310 -384L -310 347L -721 347L -721 -384Z" fill="#FFFFFF"/>
</clipPath>
<g id="Google Pixel" clip-path="url(#clip-0)">
<path d="M -721 -384L -310 -384L -310 347L -721 347L -721 -384Z" fill="#FFFFFF"/>
<g id="RectangleScaled">
<use xlink:href="#path1_fill" transform="translate(-614 -152)" fill="red"/>
</g>
<g id="Rectangle">
<use xlink:href="#path0_fill" transform="translate(-614 -152)" fill="#C4C4C4"/>
</g>
</g>
</g>
<defs>
<path id="path0_fill" d="M 0 0L 196 0L 196 266L 0 266L 0 0Z"/>
<path id="path1_fill" d="M 0 0L 196 0L 196 266L 0 266L 0 0Z"/>
</defs>
</svg>
var rectangle = document.querySelector("#Rectangle")
var rectangleScaled = document.querySelector("#RectangleScaled")
var canvasBbox = document.querySelector("#Canvas").getBBox()
var s = 1.4; // you can change this value to scale
var cx = canvasBbox.x + canvasBbox.width/2;
var cy = canvasBbox.y + canvasBbox.height/2;
var x = (cx * -(s - 1)) * 1;
var y = (cy * -(s - 1)) * (10 * s);
rectangleScaled.style.transform = "translate("+x+"px, "+y+"px) scale("+s+")"
svg {
border:solid;
}
<svg width="411" height="731" viewBox="0 0 411 731" version="1.1" xmlns="http://www.w3/2000/svg" xmlns:xlink="http://www.w3/1999/xlink">
<g id="Canvas" transform="translate(721 384)">
<clipPath id="clip-0" clip-rule="evenodd">
<path d="M -721 -384L -310 -384L -310 347L -721 347L -721 -384Z" fill="#FFFFFF"/>
</clipPath>
<g id="Google Pixel" clip-path="url(#clip-0)">
<path d="M -721 -384L -310 -384L -310 347L -721 347L -721 -384Z" fill="yellow"/>
<g id="RectangleScaled">
<use xlink:href="#path1_fill" transform="translate(-620 -360)" fill="red"/>
</g>
<g id="Rectangle">
<use xlink:href="#path0_fill" transform="translate(-620 -360)" fill="#C4C4C477"/>
</g>
</g>
</g>
<defs>
<path id="path0_fill" d="M 0 0L 196 0L 196 266L 0 266L 0 0Z"/>
<path id="path1_fill" d="M 0 0L 196 0L 196 266L 0 266L 0 0Z"/>
</defs>
</svg>