120

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

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

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

我是这样做的:

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

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

任何人都可以帮忙吗?

4

8 回答 8

162

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

对于缩放/调整大小,您必须通过 (-cx, -cy) 进行转换,然后进行缩放,然后再转换回 (cx, cy)。您可以使用矩阵变换来做到这一点:

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

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

于 2011-07-15T23:16:58.267 回答
66
svg * { 
  transform-box: fill-box;
}

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

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

于 2020-07-03T17:23:45.230 回答
22

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

于 2015-09-01T17:53:48.650 回答
14

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

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

于 2014-01-08T12:47:33.267 回答
14

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

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

它在 CSS 中:

transform: translate(cxpx, cypx) scale(sx, sy) translate(-cxpx, -cypx)
于 2018-04-01T02:09:44.000 回答
0

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

<g transform="matrix(1 0 0 1 160 200)">
  <polygon id="arrow-A" class="arrow" points="0,4 -90,0 0,-4 "/>
</g>


<style>

.arrow {
  transform: rotate(60deg);
}

/* OR */

#arrow-A {
  transform: rotate(60deg);
}

</style>

OR scripting: 

<script> 
  document.getElementById("arrow-A").setAttribute("transform", "rotate(60)");
</script>

这将创建一个箭头(例如,用于仪表),较宽的一端位于 [0,0] 并将其移动到 [160, 200]。无论对“箭头”类应用哪种旋转,都会将其围绕 [160, 200] 旋转。

测试:Chrome、Firefox、Opera、MS Edge

于 2022-01-23T14:55:47.740 回答
-1

我有一个类似的问题。但我使用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 中设置cxcy和值。transform-origin

但这在 Firefox 中不起作用!我必须做的是将标签包装circleg标签中,translate并使用上面相同的定位公式。然后我将 附加到circle标签g中,并将其cxcy值设置为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 更改为针对 ,circle而不是.dot, 添加transform: scale(2). 我什至不需要使用transform-origin

笔记:

  1. d3-selection-multi在第二个例子中使用。这使我可以将对象传递给.attrs而不是对每个属性重复.attr

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

于 2018-03-21T17:51:02.040 回答
-1

transform-origin="center"在 DOM 中设置嵌入元素的属性 ( ) 对我有用

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

使用 css 转换效果很好

于 2020-10-30T15:04:20.423 回答