Comment définir transform origin en SVG
je dois redimensionner et faire tourner certains éléments dans SVG document en utilisant javascript. Le problème est, par défaut, qu'il applique toujours la transformation autour de l'origine à (0, 0)
– en haut à gauche.
Comment puis-je redéfinir ce point d'ancrage transform?
j'ai essayé d'utiliser l'attribut transform-origin
, mais il n'affecte rien.
C'est comme ça que je l'ai fait:
svg.getDocumentById('someId').setAttribute('transform-origin', '75 240');
Il ne semble pas mettre le point pivot au point que j'ai spécifié bien que je puisse voir dans Firefox que l'attribut est correctement défini. J'ai essayé des choses comme center bottom
et 50% 100%
avec et sans parenthèses. Rien n'a fonctionné jusqu'à présent.
est-ce que quelqu'un peut aider?
5 réponses
pour tourner utilisez transform="rotate(deg, cx, cy)"
, où deg est le degré que vous voulez tourner et (cx, cy) définir le centre de rotation.
pour mettre à l'échelle/redimensionner, vous devez traduire par (-cx, -cy), puis mettre à l'échelle et ensuite traduire en (CX, cy). Vous pouvez le faire avec un transformation de matrice :
transform="matrix(sx, 0, 0, sy, cx-sx*cx, cy-sy*cy)"
où sx est le facteur d'échelle dans l'axe des abscisses, sy dans l'axe des ordonnées.
si vous pouvez utiliser une valeur fixe (Pas "centre" ou " 50%"), Vous pouvez utiliser CSS à la place:
-moz-transform-origin: 25px 25px;
-ms-transform-origin: 25px 25px;
-o-transform-origin: 25px 25px;
-webkit-transform-origin: 25px 25px;
transform-origin: 25px 25px;
certains navigateurs (comme Firefox) ne gèrent pas correctement les valeurs relatives.
si vous êtes comme moi et que vous voulez faire un panoramique et ensuite zoomer avec transform-origin, vous aurez besoin d'un peu plus.
// <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);
};
ici ça marche: http://forresto.github.io/dataflow-prototyping/react /
pour la mise à l'échelle sans avoir à utiliser la transformation matrix
:
transform="translate(cx, cy) scale(sx sy) translate(-cx, -cy)"
Et voici dans CSS:
transform: translate(cxpx, cypx) scale(sx, sy) translate(-cxpx, -cypx)
j'ai eu un problème similaire. Mais j'utilisais D3 pour positionner mes éléments, et je voulais que les transform et transition soient manipulés par CSS. C'était mon code d'origine, que J'ai obtenu en travaillant dans 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) ...
cela m'a permis de définir les valeurs cx
, cy
, et transform-origin
en javascript en utilisant les mêmes données.
BUT ça n'a pas marché avec Firefox! ce que j'ai eu à faire était d'envelopper le circle
dans le g
étiquette et translate
il en utilisant la même formule de positionnement d'en haut. J'ai ensuite ajouté le circle
dans la balise g
, et j'ai placé ses valeurs cx
et cy
à 0
. À partir de là, transform: scale(2)
serait échelle du centre comme prévu. Le code final ressemblait à ça.
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,
})
après avoir fait ce changement, j'ai changé mon CSS pour cibler le circle
au lieu du .dot
, ajouter le transform: scale(2)
. Je n'avais même pas besoin d'utiliser transform-origin
.
NOTES:
-
j'utilise
d3-selection-multi
dans le deuxième exemple. Cela me permet de passer un objet à.attrs
au lieu de répéter.attr
pour chaque attribut. -
Lorsqu'on utilise un modèle de chaîne de caractères littéral, soyez conscient des sauts de ligne comme illustré dans le premier exemple. Cela inclura une nouvelle ligne dans la sortie et peut casser votre code.