简体   繁体   中英

SVG Scale group from his center

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.org/2000/svg" xmlns:xlink="http://www.w3.org/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

You 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.org/2000/svg" xmlns:xlink="http://www.w3.org/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.org/2000/svg" xmlns:xlink="http://www.w3.org/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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM