最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - SVG Scale group from his center - Stack Overflow

programmeradmin2浏览0评论

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
Add a ment  | 

3 Answers 3

Reset to default 4

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/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>

发布评论

评论列表(0)

  1. 暂无评论