ChatGPT解决这个技术问题 Extra ChatGPT

如何在 SVG 中设置变换原点

我需要使用 javascript 调整和旋转 SVG 文档中的某些元素。问题是,默认情况下,它总是在 (0, 0) - 左上角的原点周围应用变换。

如何重新定义这个变换锚点?

我尝试使用 transform-origin 属性,但它不影响任何东西。

我是这样做的:

svg.getDocumentById('someId').setAttribute('transform-origin', '75 240');

尽管我可以在 Firefox 中看到该属性已正确设置,但它似乎并未将关键点设置为我指定的点。我尝试了带括号和不带括号的 center bottom50% 100% 之类的东西。到目前为止没有任何效果。

任何人都可以帮忙吗?

FWIW,据说从 Firefox 19 beta 3 开始修复,尽管我在 Firefox 22 中仍然遇到问题。Mozilla bugzilla 列表:bugzilla.mozilla.org/show_bug.cgi?id=828286
@CTheDark,你能重新考虑一下这个接受的答案吗?我们现在有一个更现代的解决方案:stackoverflow.com/a/62720107/4375751

P
Persijn

要旋转使用 transform="rotate(deg, cx, cy)",其中 deg 是您要旋转的度数, (cx, cy) 定义旋转中心。

对于缩放/调整大小,您必须通过 (-cx, -cy) 进行转换,然后进行缩放,然后再转换回 (cx, cy)。您可以使用 matrix transform 执行此操作:

transform="matrix(sx, 0, 0, sy, cx-sx*cx, cy-sy*cy)"

其中 sx 是 x 轴的比例因子,sy 是 y 轴的比例因子。


太感谢了。我认为旋转效果很好,但缩放/调整大小总是会随机减少一些。我尝试使用矩阵并分别执行它们,例如“translate(cxsx,cysy)scale(sx,sy)”。同样的结果。
不会是 transform="matrix(sx, 0, 0, sy, cx-sxcx, cy-sycy)" 吗?因为您只想按差异进行翻译。我认为这个逻辑是正确的,但它仍然让我失去立场......
现在它起作用了!我只是使用了错误的 cx 和 cy 值!多谢!
@JayStevens 是的,矩阵变换适用于任何系统,它只是数学。唯一的区别可能是符号。据我所知,CSS 矩阵变换使用与 SVG 相同的符号,因此按该顺序排列的相同六个数字应该可以工作。
只是为了澄清一下,cx 和 cy 需要是你缩放的盒子中心的偏移量。这让我有点困惑,就像我在 CSS 盒子模型中思考的那样。 @forresto 在下面的回答中提到了这一点。
G
George
svg * { 
  transform-box: fill-box;
}

应用 transform-box: fill-box 将使 SVG 中的元素表现得像普通的 HTML 元素。然后你可以像往常一样应用 transform-origin: center (或其他东西)

没错,transform-box: fill-box。这些天来,不需要任何复杂的矩阵东西


非常有用的解决方案,这应该得到更高的评价。这正是我所需要的;谢谢你! svg 和 html 元素在转换和过渡时有细微的差别。我被动画错误困扰了好几个小时,直到我找到了这个答案......使用transform-box: fill-box;,你可以让 svg elementes 以一种理智的方式尊重 transform-origin/就像你期望的那样!
别担心,伙计!当我找到它时,我也有类似的解脱(谢谢@Robert Longson)!!它解决了我试图控制 svg 地图上的点时所面临的巨大头痛 :sweat: :sweat: :sweat:
请注意:transform-box 于 2017 年全面推出——在这个问题被提出并首次回答 6 年后。因此,您可能不得不原谅人们“错过了窍门”。
嘿 SimplSam,我已经更新了答案以对过去更加友好
这是最好的答案
H
Hafenkranich

如果您可以使用固定值(不是“中心”或“50%”),则可以使用 CSS 代替:

-moz-transform-origin: 25px 25px;
-ms-transform-origin:  25px 25px;
-o-transform-origin: 25px 25px;
-webkit-transform-origin:  25px 25px;
transform-origin: 25px 25px;

某些浏览器(如 Firefox)不能正确处理相对值。


哇。如果可以的话会+10。这拯救了我的一天!谢谢。
如何在 JavaScript 中做到这一点?
element.setAttribute('transform-origin', '25px 25px')
f
forresto

如果您像我一样想要平移然后使用变换原点进行缩放,则需要更多。

// <g id="view"></g>
var view = document.getElementById("view");

var state = {
  x: 0,
  y: 0,
  scale: 1
};

// Origin of transform, set to mouse position or pinch center
var oX = window.innerWidth/2;
var oY = window.innerHeight/2;

var changeScale = function (scale) {
  // Limit the scale here if you want
  // Zoom and pan transform-origin equivalent
  var scaleD = scale / state.scale;
  var currentX = state.x;
  var currentY = state.y;
  // The magic
  var x = scaleD * (currentX - oX) + oX;
  var y = scaleD * (currentY - oY) + oY;

  state.scale = scale;
  state.x = x;
  state.y = y;

  var transform = "matrix("+scale+",0,0,"+scale+","+x+","+y+")";
  //var transform = "translate("+x+","+y+") scale("+scale+")"; //same
  view.setAttributeNS(null, "transform", transform);
};

它在这里工作:http://forresto.github.io/dataflow-prototyping/react/


你的 github 链接 404s
你好@NuclearPeon,这太棒了,但我似乎无法在我的代码中实现它。我希望它应用的 SVG 元素已经是一个名为“mainGrid”的变量。我尝试用“mainGrid”替换“view”的实例,但没有任何效果。我错过了什么?谢谢!
@sakeferret 要检查的最明显的事情是 getElementById 和文档的 id="..." 属性中的 id 匹配。不看代码很难确定。如果您不想将其作为 SO 问题发布,您可以尝试使用属性名称创建最简单的示例,直到它起作用/您找到问题,然后将其余部分重新添加。
c
cmititiuc

对于无需使用 matrix 转换的缩放:

transform="translate(cx, cy) scale(sx sy) translate(-cx, -cy)"

它在 CSS 中:

transform: translate(cxpx, cypx) scale(sx, sy) translate(-cxpx, -cypx)

P
Paal

您可以在 0,0 原点附近构建任何您想要的东西,然后将其放入组 <g></g> 并矩阵转换整个组。像这样,对象将始终围绕 0,0 旋转,但整个组被移动(平移)到其他地方,并且在旋转后应用平移矩阵。

<样式> .arrow { 变换:旋转(60度); } /* OR */ #arrow-A { transform: rotate(60deg); } OR 脚本: