gpt4 book ai didi

javascript - SVG 旋转和缩放转换问题

转载 作者:太空狗 更新时间:2023-10-29 13:52:50 24 4
gpt4 key购买 nike

我正在尝试使用变换来调整、旋转和拖动 SVG 元素。如果我旋转一个对象,然后重新调整大小并再次旋转,在最后一次旋转时元素会移位。

用于调整大小的代码

var matrix = SVG.createSVGMatrix()
.translate(x,y)
.scaleNonUniform(sx,sy)
.translate(-x,-y);
var newMatrix = SVG.createSVGTransformFromMatrix(ctm.multiply(matrix));
element.transform.baseVal.initialize(newMatrix);

用于旋转的代码

var matrix = SVG.createSVGMatrix()
.translate(cx,cy)
.rotate(angle)
.translate(-cx,-cy);
var newMatrix = SVG.createSVGTransformFromMatrix(ctm.multiply(matrix));
element.transform.baseVal.initialize(newMatrix);

有解决这个问题的办法吗?

最佳答案

无论应用哪种变换,我都对元素使用 getBBox 的组合来识别其中心。此外,为了跟踪元素的转换中心,我将它封装在一个 svg 包装器中,并获取它的边界框。我在每个变换上使用矩阵变换和 consolidate()。

以下是如何使用它来将元素移动到所需点的示例:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Native Center Transforms with Wrapper</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body style='padding:10px;font-family:arial'>
<center>
<h4>Native Center Transforms with Wrapper</h4>
<div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:6px;'>
The <b>Native Center</b> is the center of an element's bounding box. This remains constant no matter which transforms has been applied to an element.
Therefore this center point there can be used as the <b>reference point</b> for stable rotation, scale, and skew transforms. By use of an svg <b>wrapper</b>, the element can be translated so its
center point moves to a target point.
</div>
<table><tr>
<td>
<div style="padding:10px;width:400px;text-align:justify">
<b>Scenerio:</b><br />
The rect element has been translated from its original location (dashed rect).
Further scale, rotate, and skew transforms can use the rect's
original bounding box center (black circle): <b>NativeCenterX, NativeCenterY</b>.<br /><br />
Also, folowing scale. rotate, skew..<br />
The center of the element can be <b>moved to</b> a specific target point (maroon circle) by using the center point of it's svg <b>wrapper</b>
<br /><br />
<i>Click the buttons one or more times to transform the rect.</i>
</div>
</td>
<td>
<div id="svgDiv" style='background-color:lightgreen;width:400px;height:400px;'>
<svg id="mySVG" width="400" height="400">
<rect id="myRect" fill=red stroke="none" x="10" y="60" width=150 height=80 transform="translate(110,50)" />
<rect id="bbRect" fill=none stroke="black" stroke-width="1" stroke-dasharray="10 10" />
<circle id=nativeCenter r=5 fill="black" stroke="none" />
<circle id=moveToTarget r=5 fill="maroon" cx=240 cy=330 stroke="none" />
</svg>
</div>
<center>
<button onClick=rotateRect()>rotate</button>
<button onClick=scaleRect()>scale</button>
<button onClick=skewXRect()>skewX</button>
<button onClick=skewYRect()>skewY</button>
then...<button onClick=moveToRect()>Move To</button>
</center>
</td>
</tr></table>
<br />SVG Source:<br />
<textarea id=svgSourceValue style='font-size:110%;font-family:lucida console;width:90%;height:200px'></textarea>
<br />Javascript:<br />
<textarea id=jsValue style='border-radius:26px;font-size:110%;font-weight:bold;color:midnightblue;padding:16px;background-color:beige;border-width:0px;font-size:100%;font-family:lucida console;width:90%;height:400px'></textarea>
</center>
<div id='browserDiv' style='padding:5px;position:absolute;top:5px;left:5px;background-color:gainsboro;'>OK in:IE11/CH32/FF23<br /></div>
<script id=myScript>
var NativeCenterX
var NativeCenterY
var TransformRequestObj
var TransformList
//---translate target---
var TargetX
var TargetY
//---onload---
function initBBox()
{
var bb=myRect.getBBox()
var bbx=bb.x
var bby=bb.y
var bbw=bb.width
var bbh=bb.height
NativeCenterX=bbx+.5*bbw
NativeCenterY=bby+.5*bbh
bbRect.x.baseVal.value=bbx
bbRect.y.baseVal.value=bby
bbRect.width.baseVal.value=bbw
bbRect.height.baseVal.value=bbh
nativeCenter.cx.baseVal.value=NativeCenterX
nativeCenter.cy.baseVal.value=NativeCenterY

TargetX=moveToTarget.cx.baseVal.value
TargetY=moveToTarget.cy.baseVal.value

//--- transform myRect Objs---
TransformRequestObj=mySVG.createSVGTransform()
var animTransformList=myRect.transform
TransformList=animTransformList.baseVal
}
//---button---
function rotateRect() //---15 degrees
{
TransformRequestObj.setRotate(15,NativeCenterX,NativeCenterY)
TransformList.appendItem(TransformRequestObj)
TransformList.consolidate()
svgSourceValue.value=svgDiv.innerHTML
}
function scaleRect() //---.8---
{
TransformRequestObj.setTranslate(NativeCenterX,NativeCenterY )
TransformList.appendItem(TransformRequestObj)
TransformList.consolidate()

TransformRequestObj.setScale(.8,.8)
TransformList.appendItem(TransformRequestObj)
TransformList.consolidate()
TransformRequestObj.setTranslate(-NativeCenterX,-NativeCenterY )
TransformList.appendItem(TransformRequestObj)
TransformList.consolidate()

svgSourceValue.value=svgDiv.innerHTML
}
function skewXRect()
{
TransformRequestObj.setTranslate(NativeCenterX,NativeCenterY )
TransformList.appendItem(TransformRequestObj)
TransformList.consolidate()

TransformRequestObj.setSkewX(10)
TransformList.appendItem(TransformRequestObj)
TransformList.consolidate()

TransformRequestObj.setTranslate(-NativeCenterX,-NativeCenterY )
TransformList.appendItem(TransformRequestObj)
TransformList.consolidate()

svgSourceValue.value=svgDiv.innerHTML
}
function skewYRect()
{
TransformRequestObj.setTranslate(NativeCenterX,NativeCenterY )
TransformList.appendItem(TransformRequestObj)
TransformList.consolidate()

TransformRequestObj.setSkewY(10)
TransformList.appendItem(TransformRequestObj)
TransformList.consolidate()

TransformRequestObj.setTranslate(-NativeCenterX,-NativeCenterY )
TransformList.appendItem(TransformRequestObj)
TransformList.consolidate()

svgSourceValue.value=svgDiv.innerHTML
}
var NS="http://www.w3.org/2000/svg"
//---move transformed rect to a specific point(TargetX,TargetY)--
function moveToRect()
{
//---build temp wrapper---
var wrapper=document.createElementNS(NS,"svg")
mySVG.appendChild(wrapper)
//---temp place rect in wrapper---
wrapper.appendChild(myRect)
var bb=wrapper.getBBox()
//---return myRect to previous location---
mySVG.insertBefore(myRect,bbRect)
//---remove temp wrapper---
mySVG.removeChild(wrapper)

var bbx=bb.x
var bby=bb.y
var bbw=bb.width
var bbh=bb.height
//---center of svg srapper---
var Wcx=bbx+.5*bbw
var Wcy=bby+.5*bbh

//---bind target point to current matrix---
var pnt = myRect.nearestViewportElement.createSVGPoint();
pnt.x = TargetX;
pnt.y = TargetY;
var sCTM = myRect.getCTM();
PNT1 = pnt.matrixTransform(sCTM.inverse());
//---bind wrapper center to current matrix--
var pnt = myRect.nearestViewportElement.createSVGPoint();
pnt.x = Wcx;
pnt.y = Wcy ;
var sCTM = myRect.getCTM();
PNT2 = pnt.matrixTransform(sCTM.inverse());
//---translate rect's center to target---
var transX=PNT1.x-PNT2.x
var transY=PNT1.y-PNT2.y

TransformRequestObj.setTranslate(transX,transY)
TransformList.appendItem(TransformRequestObj)
TransformList.consolidate()

svgSourceValue.value=svgDiv.innerHTML
}

</script>
<script>
document.addEventListener("onload",init(),false)
function init()
{
initBBox()
svgSourceValue.value=svgDiv.innerHTML
jsValue.value=myScript.text
}
</script>

</body>

</html>

关于javascript - SVG 旋转和缩放转换问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22604912/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com