Как установить transform origin в SVG
мне нужно изменить размер и повернуть определенные элементы в SVG-документе с помощью javascript. Проблема в том, что по умолчанию он всегда применяет преобразование вокруг начала координат в (0, 0)
– верхний левый.
как я могу повторно определить эту точку привязки преобразования?
Я попытался с помощью transform-origin
атрибут, но он ни на что не влияет.
вот как я это сделал:
svg.getDocumentById('someId').setAttribute('transform-origin', '75 240');
он, похоже, не устанавливает центральную точку в точку, которую я указал, хотя я могу см. в Firefox, что атрибут правильно установлен. Я пробовал такие вещи, как center bottom
и 50% 100%
с круглыми скобками и без них. Пока ничего не получалось.
может кто-нибудь помочь?
5 ответов
для поворота используйте 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.
Если вы можете использовать фиксированное значение (не " центр "или" 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) не будут корректно обрабатывать относительные значения.
Если вы похожи на меня и хотите панорамировать, а затем масштабировать с помощью 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/
для масштабирования без использования matrix
преображение:
transform="translate(cx, cy) scale(sx sy) translate(-cx, -cy)"
и вот он в CSS:
transform: translate(cxpx, cypx) scale(sx, sy) translate(-cxpx, -cypx)
у меня была аналогичная проблема. Но я использовал 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) ...
это позволило мне установить cx
,cy
и transform-origin
значения в javascript с использованием тех же данных.
но это не сработало в Firefox! что мне нужно было сделать, так это завернуть circle
in the g
и тег translate
оно используя такую же располагая формулу сверху. Затем я добавил circle
на g
tag, и установить его 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 на целевой circle
вместо .dot
, чтобы добавить transform: scale(2)
. Я даже не нуждался в использовании. transform-origin
.
Примечания:
я использую
d3-selection-multi
во втором примере. Это позволяет мне передать объект.attrs
вместо того, чтобы повторять.attr
для каждого атрибута.при использовании литерала шаблона строки помните о разрывах строк, как показано в первом примере. Это будет включать новую строку в выводе и может нарушить ваш код.