La relation entre x de coordonnées d'un élément et la coordonnée de la position droite du texte ne soit pas la même que celle de la y de coordonnées d'un élément et la position basse . En fait, c'est inversé. C'est parce que verticalement, le texte est placé au bas d'un élément et les coordonnées y vont de haut en bas, tandis que les coordonnées horizontales vont dans la même direction que le texte.
Ceci est facilement visible lors de l'utilisation de la méthode GetBBbox(), que vous utilisez. Par exemple, lorsque vous ajoutez un élément de texte aux coordonnées 0 pour x et y, vous verrez que getBBbox vous donnera un x = 0 mais un y négatif.
console.log(document.getElementById('testbbox').getBBox());
<svg id="testbbox"><text x=0 y=0>test</text></svg>
déjà, les calculs du centre de votre texte devront être différents. Ce que vous avez maintenant est:
outerRect.x - ((outerRect.width - innerRect.width)/2)
Cela fonctionne parce que vous supposez que le rectangle interne commence à 0, ce qui n'est pas le cas. Votre boîte englobante est verticalement dans le négatif. formule si complète devrait être quelque chose comme:
outerRect.x - innerRect.x - ((outerRect.width - innerRect.width)/2)
Ce qui dans votre exemple serait:
x - bboxx + ((width - boxWidth)/2)
Où bbox est x de getBBox()
Vous pouvez utiliser base, mais avec dy sur le tspan, cela rend les calculs un peu plus complexes, pas sûr que ce soit la bonne approche. Puisque de toute façon getBBox prend en compte la ligne de base dans le calcul, ce n'est pas vraiment nécessaire.
De plus, si vous regardez ici, la ligne de base pour le texte devrait être la ligne de base dominante, sans alignement-base: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/dominant-baseline
voir comment il affecte la zone de délimitation, en particulier y coordonnées:
console.log(document.getElementById('central').getBBox());
console.log(document.getElementById('top').getBBox());
<svg id="central">
<text y=10 dominant-baseline="central" >test</text>
</svg>
<svg id="top">
<text y=10 dominant-baseline="top" >test</text>
</svg>
Voir résultat final: https://codesandbox.io/s/52wl31l8zn
Dieu le simple fait que j'ai inversé 'textAlignV' et' textAlignH' se sent si mal! En tout cas, merci, ça fonctionne parfaitement. C'est un comportement si étrange, je ne comprends pas comment on s'attend à ce que les gens s'en aperçoivent! – Telokis