
或[1 0 0 1 tx ty],其中tx和ty分別是在x和y中平移坐標的距離。
例子
下面提供兩個小例子svg。每個都包含一個path都被旋轉的15°。我試圖用石灰標記點p(x1,y1)circle。
;window.onload = () => {
//REM: Query the first element in svg => [path, path]
document.querySelectorAll('svg > *[transform]').forEach((element) => {
let tSVG = element.ownerSVGElement;
let tBBox = element.getBBox();
let tMatrix = element.transform.baseVal.getItem(0).matrix;
//REM: Draw a circle at p(x1,y1) - before rotation
let tOldX = tBBox.x * tMatrix.a tMatrix.e;
let tOldY = tBBox.y * tMatrix.d tMatrix.f
let tCircle1 = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
tCircle1.setAttributeNS(null, 'r', '5');
tCircle1.setAttributeNS(null, 'fill', 'orange');
tCircle1.setAttributeNS(null, 'fill-opacity', '0.5');
tCircle1.setAttributeNS(null, 'cx', tOldX);
tCircle1.setAttributeNS(null, 'cy', tOldY);
tSVG.appendChild(tCircle1);
//REM: Rotate by 15° around center of itself
let tTransform = tSVG.createSVGTransform();
tTransform.setRotate(15, tBBox.x tBBox.width / 2, tBBox.y tBBox.height / 2);
element.transform.baseVal.appendItem(tTransform);
element.transform.baseVal.initialize(element.transform.baseVal.consolidate());
//REM: Fetch new matrix
tMatrix = element.transform.baseVal.getItem(0).matrix;
//REM: Pure scale
let tScaleX = Math.sqrt(tMatrix.a * tMatrix.a tMatrix.b * tMatrix.b);
let tScaleY = Math.sqrt(tMatrix.c * tMatrix.c tMatrix.d * tMatrix.d);
//REM: Draw a circle at p(x1,y1) - after rotation
let tNewX = tBBox.x * tScaleX tMatrix.e;
let tNewY = tBBox.y * tScaleY tMatrix.f;
let tCircle2 = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
tCircle2.setAttributeNS(null, 'r', '5');
tCircle2.setAttributeNS(null, 'fill', 'lime');
tCircle2.setAttributeNS(null, 'fill-opacity', '0.9');
tCircle2.setAttributeNS(null, 'cx', tNewX);
tCircle2.setAttributeNS(null, 'cy', tNewY);
tSVG.appendChild(tCircle2);
//REM: Connection
let tLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
tLine.setAttributeNS(null, 'stroke', 'green');
tLine.setAttributeNS(null, 'x1', tOldX);
tLine.setAttributeNS(null, 'y1', tOldY);
tLine.setAttributeNS(null, 'x2', tNewX);
tLine.setAttributeNS(null, 'y2', tNewY);
tSVG.appendChild(tLine);
console.log(
'e: ' tMatrix.e,
'f: ' tMatrix.f
)
})
}
<svg xmlns = 'http://www.w3.org/2000/svg' viewBox = '950,-250,100,400' height='800' width='300'>
<path d = 'm1029.31 112.6h97.40v57.01h-97.40z' fill = 'red' transform = 'matrix(0.9, 0, 0, 0.9, 15, -15)' />
</svg>
<svg xmlns = 'http://www.w3.org/2000/svg' viewBox = '-40,-40,150,100' height='200' width='300'>
<path d = 'M0 0L100 0L100 60L0 60z' fill = 'blue' transform = 'matrix(0.9, 0, 0, 0.9, 15, -15)'></path>
</svg>
問題
據我了解,我應該能夠通過使用以下計算得到點p(x1,y1) aka top-left:
- x1: (bbox.x * scale) matrix.e //原始位置 x 縮放 物體移動 x
- y1: (bbox.y * scale) matrix.f //原始位置 y 縮放 被 y 移動的物件
然而,它僅適用于第二個/藍色 svg,而不是第一個/紅色。第一個/紅色 svg 的f對我來說似乎很遙遠:
- e: 80.92766714917656 f: -261.78134648854723 //first/red svg
- e: 23.52145237337207 f: -25.726854765665173 //第二/藍色 svg
我哪里錯了?
評論
雖然我為語法添加了 Javascript 標記,但重點不在于 Javascript。Javascript 提供了正確放置石灰的其他可能性circle。
uj5u.com熱心網友回復:
我沒有研究為什么它失敗了。我有幾個想法。但是,如果您應用正確的矩陣乘法公式,它就可以正常作業。
let tNewX = tBBox.x * tMatrix.a tBBox.y * tMatrix.c tMatrix.e;
let tNewY = tBBox.x * tMatrix.b tBBox.y * tMatrix.d tMatrix.f;
;window.onload = () => {
//REM: Query the first element in svg => [path, path]
document.querySelectorAll('svg > *[transform]').forEach((element) => {
let tSVG = element.ownerSVGElement;
let tBBox = element.getBBox();
let tMatrix = element.transform.baseVal.getItem(0).matrix;
//REM: Draw a circle at p(x1,y1) - before rotation
let tOldX = tBBox.x * tMatrix.a tMatrix.e;
let tOldY = tBBox.y * tMatrix.d tMatrix.f
let tCircle1 = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
tCircle1.setAttributeNS(null, 'r', '5');
tCircle1.setAttributeNS(null, 'fill', 'orange');
tCircle1.setAttributeNS(null, 'fill-opacity', '0.5');
tCircle1.setAttributeNS(null, 'cx', tOldX);
tCircle1.setAttributeNS(null, 'cy', tOldY);
tSVG.appendChild(tCircle1);
//REM: Rotate by 15° around center of itself
let tTransform = tSVG.createSVGTransform();
tTransform.setRotate(15, tBBox.x tBBox.width / 2, tBBox.y tBBox.height / 2);
element.transform.baseVal.appendItem(tTransform);
element.transform.baseVal.initialize(element.transform.baseVal.consolidate());
//REM: Fetch new matrix
tMatrix = element.transform.baseVal.getItem(0).matrix;
//REM: Draw a circle at p(x1,y1) - after rotation
let tNewX = tBBox.x * tMatrix.a tBBox.y * tMatrix.c tMatrix.e;
let tNewY = tBBox.x * tMatrix.b tBBox.y * tMatrix.d tMatrix.f;
let tCircle2 = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
tCircle2.setAttributeNS(null, 'r', '5');
tCircle2.setAttributeNS(null, 'fill', 'lime');
tCircle2.setAttributeNS(null, 'fill-opacity', '0.9');
tCircle2.setAttributeNS(null, 'cx', tNewX);
tCircle2.setAttributeNS(null, 'cy', tNewY);
tSVG.appendChild(tCircle2);
//REM: Connection
let tLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
tLine.setAttributeNS(null, 'stroke', 'green');
tLine.setAttributeNS(null, 'x1', tOldX);
tLine.setAttributeNS(null, 'y1', tOldY);
tLine.setAttributeNS(null, 'x2', tNewX);
tLine.setAttributeNS(null, 'y2', tNewY);
tSVG.appendChild(tLine);
console.log(
'e: ' tMatrix.e,
'f: ' tMatrix.f
)
})
}
<svg xmlns = 'http://www.w3.org/2000/svg' viewBox = '950,-250,100,400' height='800' width='300'>
<path d = 'm1029.31 112.6h97.40v57.01h-97.40z' fill = 'red' transform = 'matrix(0.9, 0, 0, 0.9, 15, -15)' />
</svg>
<svg xmlns = 'http://www.w3.org/2000/svg' viewBox = '-40,-40,150,100' height='200' width='300'>
<path d = 'M0 0L100 0L100 60L0 60z' fill = 'blue' transform = 'matrix(0.9, 0, 0, 0.9, 15, -15)'></path>
</svg>
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/475348.html
標籤:javascript svg 矩阵
