如何在SVG中设置变换原点

如何在SVG中设置变换原点,svg,coordinate-transformation,Svg,Coordinate Transformation,我需要使用javascript调整SVG文档中某些元素的大小和旋转。问题是,默认情况下,它总是在左上角(0,0)处围绕原点应用变换 如何重新定义此变换定位点 我尝试使用transform origin属性,但它不影响任何东西 我就是这样做的: svg.getDocumentById('someId').setAttribute('transform-origin', '75 240'); 它似乎没有将关键点设置为我指定的点,尽管我可以在Firefox中看到该属性设置正确。我试过像中底和50%1

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

如何重新定义此变换定位点

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

我就是这样做的:

svg.getDocumentById('someId').setAttribute('transform-origin', '75 240');
它似乎没有将关键点设置为我指定的点,尽管我可以在Firefox中看到该属性设置正确。我试过像
中底
50%100%
这样的方法,有括号也有括号。到目前为止,一切都没起作用


有人能帮忙吗?

要旋转,请使用
transform=“rotate(deg,cx,cy)”
,其中deg是要旋转的度数,而(cx,cy)定义旋转中心

对于缩放/调整大小,必须按(-cx,-cy)转换,然后缩放,然后再转换回(cx,cy)。您可以通过以下方式执行此操作:


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

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

// <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);
};
//
var view=document.getElementById(“视图”);
变量状态={
x:0,,
y:0,
比例:1
};
//变换原点,设置为鼠标位置或夹点中心
var oX=window.innerWidth/2;
var oY=窗内高度/2;
var changeScale=功能(比例){
//如果需要,请限制此处的比例
//缩放和平移变换原点等效
var scaleD=比例/状态.scale;
var currentX=state.x;
var currentY=状态y;
//魔法
var x=标度*(电流x-oX)+oX;
var y=标度*(当前y-oY)+oY;
state.scale=比例;
状态x=x;
状态y=y;
var transform=“矩阵(“+scale+”,0,0,“+scale+”,“+x+”,“+y+”);
//var transform=“translate(“+x+”,“+y+”)比例(“+scale+”);//相同
view.setAttributeNS(null,“transform”,transform);
};

它在这里工作:

如果可以使用固定值(不是“中心”或“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)无法正确处理相对值。

我也遇到了类似的问题。但是我使用了D3来定位我的元素,并且希望转换和转换由CSS处理。这是我的原始代码,我在Chrome 65中使用:

//...
this.layerGroups.selectAll('.dot')
  .data(data)
  .enter()
  .append('circle')
  .attr('transform-origin', (d,i)=> `${valueScale(d.value) * Math.sin( sliceSize * i)} 
                                     ${valueScale(d.value) * Math.cos( sliceSize * i + Math.PI)}`)
//... etc (set the cx, cy and r below) ...
这允许我使用相同的数据在javascript中设置
cx
cy
transform origin

但这在Firefox中不起作用我要做的是将
圆圈
包裹在
g
标记中,然后使用上面相同的定位公式对其进行
translate
。然后我在
g
标记中添加
圆圈
,并将其
cx
cy
值设置为
0
。从那里,
transform:scale(2)
将按预期从中心进行缩放。最后的代码是这样的

this.layerGroups.selectAll('.dot')
  .data(data)
  .enter()
  .append('g')
  .attrs({
    class: d => `dot ${d.metric}`,
    transform: (d,i) => `translate(${valueScale(d.value) * Math.sin( sliceSize * i)} ${valueScale(d.value) * Math.cos( sliceSize * i + Math.PI)})`
  })
  .append('circle')
  .attrs({
    r: this.opts.dotRadius,
    cx: 0,
    cy: 0,
  })
进行此更改后,我将CSS更改为以
圆圈为目标,而不是
.dot
,以添加
变换:缩放(2)
。我甚至不需要使用
变换原点

注意事项:

  • 在第二个示例中,我使用的是
    d3 selection multi
    。这允许我将对象传递给
    .attrs
    ,而不是对每个属性重复
    .attr

  • 使用字符串模板文字时,请注意第一个示例中所示的换行符。这将在输出中包含一个换行符,可能会中断代码


  • 无需使用
    矩阵
    变换即可进行缩放:

    transform="translate(cx, cy) scale(sx sy) translate(-cx, -cy)"
    
    这里是CSS:

    transform: translate(cxpx, cypx) scale(sx, sy) translate(-cxpx, -cypx)
    
    应用
    transformbox:fill-box
    将使SVG中的元素表现为普通HTML元素。然后,您可以像通常一样应用
    变换原点:中心
    (或其他内容)

    没错,
    变换框:填充框
    。现在,不需要任何复杂的矩阵元素了,只需在DOM中设置嵌入元素的属性(
    transform origin=“center”
    )就可以了

              <circle
              fill="#FFFFFF"
              cx="82"
              cy="81.625"
              r="81.5"
              transform-origin="center"
            ></circle>
    
    
    

    可以很好地使用css转换

    非常感谢。我认为旋转工作得很完美,但缩放/调整大小总是以一些随机量结束。我试着使用矩阵,并像“translate(cxsx,cysy)scale(sx,sy)”那样分别进行。同样的结果。它不是transform=“matrix(sx,0,0,sy,cx-sxcx,cy-sycy)”吗?因为你只想通过差异来翻译。我认为这个逻辑是正确的,但它仍然让我失去了位置…现在它起作用了!我只是使用了错误的cx和cy值!非常感谢@是的,矩阵变换适用于任何系统,它只是数学。唯一的区别可能是符号。据我所知,CSS矩阵变换使用与SVG相同的表示法,因此按该顺序使用相同的六个数字应该可以。只是为了澄清一下,cx和cy需要是缩放框中心的偏移量。正如我在CSS框模型中思考的那样,这让我有点困惑@forresto在下面的回答中提到了这一点。FWIW应该在Firefox 19 beta 3中修复,尽管我在Firefox 22中仍然有问题。Mozilla bugzilla清单:@CTheDark,你能重新考虑一下这个问题的公认答案吗?我们现在有了一个更现代的解决方案:哇。如果可以,我会+10。这救了我一天!谢谢。如何在JavaScript中做到这一点?比如
    element.setAttribute('transform-origin','25px 25px')
    ?您的github链接404sHello@NuclearPeon,这太棒了,但我似乎无法在代码中实现它。我希望应用的SVG元素已经是一个名为“mainGrid”的变量。我尝试用“mainGrid”替换“view”的实例,但没有效果。我错过了什么?谢谢@sakeferret最明显要检查的是
    idsvg { 
      transform-box: fill-box;
    }
    
              <circle
              fill="#FFFFFF"
              cx="82"
              cy="81.625"
              r="81.5"
              transform-origin="center"
            ></circle>