座標変換を理解するために、次のようなDOM構造を考えます。
(複雑さを排除するため、x と y(または width と height)は同じ値にしています)
export function Component() {
return (
<div style={{ margin: 100 }}>
<svg width={200} height={200} viewBox="0 0 400 400">
<g transform="translate(100, 100)"></g>
</svg>
</div>
);
}
このDOM構造には、いくつかの座標系が存在します。
これら座標系間の変換にはどの行列を使えば良いかについては、次の図を見ることでわかります。
(図の数値は x 座標を表します)
例
たとえば、座標系 D の点 (150, 150) を座標系 B の点に変換するときは、次のように実装します。
const p = new DOMPoint(150, 150);
const m = g.getCTM()!;
const q = p.matrixTransform(m);
console.log(q.x); //=> 125
g.getCTM()
や svg.getScreenCTM()
の評価値は DOMMatrix
オブジェクト(または null
)です。
DOMMatrix
オブジェクトは .inverse()
メソッドを持ちます。
これは逆行列を返すメソッドです。これを利用することで、座標系 B から座標系 D への変換などが可能になります。
次のように実装します。
const p = new DOMPoint(125, 125);
const m = g.getCTM()!.inverse();
const q = p.matrixTransform(m);
console.log(q.x); //=> 150
座標系 D から座標系 C に変換するときは次のように実装します。
const p = new DOMPoint(300, 300);
const m1 = g.getCTM()!;
const q = p.matrixTransform(m1);
const m2 = svg.getCTM()!.inverse();
const r = q.matrixTransform(m2);
console.log(r.x); //=> 400
次のように、変換行列同士の積を取り、その行列を適用することもできます。
const p = new DOMPoint(300, 300);
const m = (() => {
const m1 = g.getCTM()!;
const m2 = svg.getCTM()!.inverse();
return m2.multiply(m1);
})();
const q = p.matrixTransform(m);
console.log(q.x); //=> 400