Как установить начало преобразования в SVG
мне нужно изменить размер и повернуть некоторые элементы в документе SVG с помощью javascript. Проблема в том, что по умолчанию он всегда применяет преобразование вокруг источника в (0, 0)
– верхний левый.
как я могу переопределить эту точку привязки преобразования?
Я пробовал использовать , но это ни на что не влияет.
вот как я это сделал:
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 чтобы расположить мои элементы, и хотел transform и переход для обработки с помощью 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 элементg
и тегtranslate
он использует ту же формулу позиционирования сверху. Затем я добавилcircle
на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 для таргетинга
circle
вместо.dot
, чтобы добавитьtransform: scale(2)
. Мне даже не нужно было использоватьtransform-origin
.Примечания:
я использую
d3-selection-multi
во втором примере. Это позволяет мне передать объект.attrs
вместо того, чтобы повторять.attr
для каждого атрибута.при использовании литерала шаблона строки следует учитывать разрывы строк, как показано в первом примере. Это будет включать новую строку в выводе и может нарушить ваш код.