如何在 SVG 中设置变换原点

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

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

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

This is how I did it:

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

它似乎没有将关键点设置为我指定的点,尽管我可以在 Firefox 中看到属性设置是正确的。我尝试了像 center bottom50% 100%这样带括号和不带括号的东西。目前为止都没用。

有人能帮忙吗?

118519 次浏览

旋转使用 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 轴的比例因子,y 轴是 sy。

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

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

如果你可以使用一个固定的值(不是“居中”或“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 来处理 变形过渡期。这是我的原始代码,我在 Chrome65中得到的:

//...
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 中设置 cxcytransform-origin值。

但是这在 Firefox 中不起作用!我所要做的就是将 circle包裹在 g标签中,然后使用上面相同的定位公式将 translate包裹起来。然后,我在 g标记中附加了 circle,并将它的 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,将目标从 .dot改为 circle,以便添加 transform: scale(2)。我甚至不需要使用 transform-origin

NOTES:

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

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

For scaling without having to use the matrix transformation:

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

这里是 CSS:

transform: translate(cxpx, cypx) scale(sx, sy) translate(-cxpx, -cypx)
svg * {
transform-box: fill-box;
}

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

没错 transform-box: fill-box现在不需要什么复杂的矩阵了

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

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

可以很好地使用 css 转换

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