SVG Scale 组从他的中心

SVG Scale group from his center

我正在尝试将名为 #RectangleScaled<g></g> 从组中心缩放 1.4 倍。 我正在使用这个公式

translate(-centerX*(factor-1), -centerY*(factor-1)) scale(factor)

但是红色矩形似乎没有正确的翻译

这是我的实现

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>

这里是fiddle

仅适用于 Chrome(将其视为错误): 对于缩放并将缩放元素保持在中心位置,您可以使用纯 CSS,通过将 transform-origin: center; 样式添加到 #RectangleScaled 选择器。

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>

你好像搞错了中心。您围绕错误的中心点进行缩放。

您将 canvasBBox widthheight 除以二,但您没有考虑 bbox 的 xy 值.

#Canvas元素的中心在

var cx = canvasBbox.x + canvasBbox.width/2;
var cy = canvasBbox.y + canvasBbox.height/2;

如果您使用这些值更新计算,您将得到预期的结果。

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>