如何在SVG中设置变换原点



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

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

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

我是这样做的:

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

它似乎没有将枢纽点设置为我指定的点,尽管我可以在Firefox中看到该属性是正确设置的。我尝试了center bottom50% 100%这样的东西,有或没有括号。

有人能帮忙吗?

使用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轴的比例因子

2020年新方案

svg * { 
  transform-box: fill-box;
}

应用transform-box: fill-box将使SVG中的元素表现为普通的HTML元素。然后你可以应用transform-origin: center(或其他东西),因为你通常会

没错,transform-box: fill-box。现在,不需要任何复杂的矩阵

如果你可以使用一个固定的值(不是"center"或"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)不能正确处理相对值

无需使用matrix转换即可缩放:

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

这里是CSS:

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

如果你像我一样,想要用transform-origin平移然后缩放,你需要更多的东西

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

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

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

您可以在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

我也遇到过类似的问题。但是我使用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, cytransform-origin值。

但是这在Firefox中不起作用!我要做的是将circle包装在g标签和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. 当使用字符串模板文字时,要注意第一个示例中所示的换行。这将在输出中包含一个换行符,并可能破坏您的代码。

最新更新