我有点头疼......我正在使用jsbox2d.js进行2D游戏,基于SVG图形。我想»将一个b2d-body连接到一个svg元素,这对于调试绘图已有效,但不适用于场景中的图形。
设置:
有一个SVG,包括任意深度嵌套的组和形状结构。每一个我都有一些变换,所以每个元素都驻留在自己的坐标空间中。
除了有一个box2d模拟,一些实体代表svg中的一个元素。
我想将b2body的变换应用于它所代表的svg-element,以便动画看起来正确。它已经在调试绘图中工作,我正在使用这段代码:
// links is an array like [[b2body, svgelement],…]
for (var i = 0; i < links.length; i++) {
var t = links[i][0].GetTransform();
//tiny helper function just taking the values and
//setting it to the element
// transform(element, a,b,c,d,e,f)
//|a c e|
//|b d f|
svghelper.transform(links[i][1],
t.q.c, t.q.s, -t.q.s,
t.q.c, t.p.x, t.p.y);
}
主要区别在于,使用b2dShapes顶点的世界坐标,即时生成用于调试绘图的元素,无需任何变换。
但场景的图形取自使用inkscape和f.i创建的SVG图形。使用小组作为手臂或charackter的头部。
如何在元素上应用正文的变换?我想我需要改变变换矩阵的基础,但我不知道怎么做不起作用。
我试过这个:
var t = body.GetTransform(),
mtr = svg,createSVGMatrix(
t.q.c, t.q.s, -t.q.s,
t.q.c, t.p.x, t.p.y),
toElement = element.getTransformToElement(element.ownerSVGDocument),
toElement_inv = toElement.invert();
mtr = mtr.multiply(toElement);
mtr = toElement_inv.multiply(mtr);
//applying the result
但是通过反转矩阵导致了错误的结果和错误。
提前致谢!
答案 0 :(得分:0)
我在下面有一个示例可能会有所帮助,希望不会增加您的头痛;)它解决了将元素放在不同的viewPorts中的问题
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Find X,Y in Transforms & ViewPorts</title>
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
</head>
<body style='padding:10px;font-family:arial'>
<center>
<h4>Find X,Y in Transforms & ViewPorts</h4>
<div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:6px;'>
Elements are transformed and reside it different viewPorts. This example uses <b>getScreenCTM</b> and <b>inverse</b> to access x,y values.
</div>
<table>
<tr><td align=left>
<b>Click on an element target.<br />
This will place the black circle<br />so it matches the target's transformations</b><br />
Scenerio:<br />
1.) SVG image is inline, contained in a DIV.<br />
2.) The blue rect element is contained in a <g>.<br />
3.) The <g> element has been transformed.<br />
4.) The maroon rect resides in a different viewPort.<br />
5.) The orange circle has been transformed.<br />
6.) Move cursor over elements to get their x,y values<br />
6.) Click over element place black circle in its viewport or target's transform.<br />
</td>
<td align=left>
<div id="svgDiv" style='background-color:lightgreen;width:400px;height:400px;'>
<svg id="mySVG" width="400" height="400" onmousemove="svgCursor(evt)" onclick="placeBlackCircle(evt)" >
<circle pointer-events="none" id="blackCircle" r="10" fill="black" />
<circle onmousemove=getXY(evt) onmouseout=clearXY() id="redCircle" cx="120" cy="180" r="40" fill="red" stroke="black" stroke-width="2" />
<circle onmousemove=getXY(evt) onmouseout=clearXY() id="orangeCircle" cx="200" cy="200" r="40" fill="orange" stroke="black" stroke-width="2" />
<svg viewBox="0 100 800 800">
<rect onmousemove=getXY(evt) onmouseout=clearXY() id="maroonRect" x="220" y="250" width="60" height="60" fill="maroon" stroke="black" stroke-width="2" />
</svg>
<g id="myG" >
<rect onmousemove=getXY(evt) onmouseout=clearXY() id="blueRect" x="220" y="250" width="60" height="60" fill="blue" stroke="black" stroke-width="2" />
</g>
</svg>
</div>
</td>
<td align=left>
<table style='font-family:lucida console'>
<tr><td colspan=4><b>HTML Page Values:</b></td></tr>
<tr style='font-size:110%'>
<td align=right>mouse X:</td><td><input style='font-size:120%' type=text id=htmlMouseXValue size=1 /></td>
<td><input style='font-size:120%' type=text id=htmlMouseYValue size=1 /></td><td align=left>:mouse Y</td>
</tr>
<tr><td colspan=4><b>SVG Image Values:</b></td></tr>
<tr style='font-size:110%'>
<td align=right>svg X:</td> <td><input style='font-size:120%' type=text id=svgXValue size=1 /></td>
<td><input style='font-size:120%' type=text id=svgYValue size=1 /></td><td align=left>:svg Y</td>
</tr>
<tr><td colspan=4><b>Target:<input id=elemIdValue size=10 /></b></td></tr>
<tr style='font-size:110%'>
<td align=right>client X:</td> <td><input style='font-size:120%' type=text id=clientXValue size=1 /></td>
<td><input style='font-size:120%' type=text id=clientYValue size=1 /></td><td align=left>:client Y</td>
</tr>
<tr style='font-size:110%'>
<td align=right>screen X:</td> <td><input style='font-size:120%' type=text id=screenXValue size=1 /></td>
<td><input style='font-size:120%' type=text id=screenYValue size=1 /></td><td align=left>:screen Y</td>
</tr>
</table>
</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>
<script id=myScript>
//---mouse move---
function getXY(evt)
{
var target=evt.target
elemIdValue.value=target.id
var pnt = target.ownerSVGElement.createSVGPoint();
pnt.x = evt.clientX;
pnt.y = evt.clientY;
clientXValue.value=pnt.x
clientYValue.value=pnt.y
//---element's x,y screen transformed/inversevalues---
var sCTM = target.getScreenCTM();
var PNT = pnt.matrixTransform(sCTM.inverse());
screenXValue.value=PNT.x
screenYValue.value=PNT.y
}
function placeBlackCircle(evt)
{
var target=evt.target;
//---initialize a point in its respective viewport--
if(target.nearestViewportElement) //--must click on an element not svg root--
{
var pnt = target.nearestViewportElement.createSVGPoint();
//---client area click point---
pnt.x = evt.clientX;
pnt.y = evt.clientY;
var sCTM = target.getScreenCTM();
//---return viewport's Pnt.x, Pnt.y---
PNT = pnt.matrixTransform(sCTM.inverse());
//----place blackDot on top in viewport and locate it---
target.nearestViewportElement.appendChild(blackCircle)
blackCircle.setAttribute("cx",PNT.x)
blackCircle.setAttribute("cy",PNT.y)
if(target.parentNode.nodeName=="g")
{
target.parentNode.appendChild(blackCircle)
}
if(target.getAttribute("transform"))
{
var transform=target.getAttribute("transform")
blackCircle.setAttribute("transform",transform)
}
else
blackCircle.removeAttribute("transform")
}
}
function clearXY()
{
elemIdValue.value=""
clientXValue.value=""
clientYValue.value=""
screenXValue.value=""
screenYValue.value=""
}
//---onload---
function initTransforms()
{
//---place some transforms on the elements---
//--- transform orange circle---
var transformRequestObj=mySVG.createSVGTransform()
var animTransformList=orangeCircle.transform
var transformList=animTransformList.baseVal
//---translate---
transformRequestObj.setTranslate(180,-260)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//----scale---
transformRequestObj.setScale(.5,.9)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//----skewY---
transformRequestObj.setSkewY(52)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//--init Transform on myG---
var transformRequestObj=mySVG.createSVGTransform()
var animTransformList=myG.transform
var transformList=animTransformList.baseVal
//---translate---
transformRequestObj.setTranslate(-50,-80)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//----skewX---
transformRequestObj.setSkewX(15)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//----skewY---
transformRequestObj.setSkewY(20)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//---rotate---
transformRequestObj.setRotate(30,200,200)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
}
document.onmousemove = htmCursor
//---'event' is the html event object---
function htmCursor(event)
{
var event = event || window.event;
myMouseX=event.clientX;
myMouseY=event.clientY;
myMouseX = myMouseX + document.documentElement.scrollLeft;
myMouseY = myMouseY + document.documentElement.scrollTop;
htmlMouseXValue.value=myMouseX
htmlMouseYValue.value=myMouseY
}
//---'evt' is the svg event object--
function svgCursor(evt)
{
var rect = svgDiv.getBoundingClientRect();
svgXValue.value=evt.clientX-rect.left
svgYValue.value=evt.clientY-rect.top
}
</script>
<script>
document.addEventListener("onload",init(),false)
function init()
{
initTransforms()
svgSourceValue.value=svgDiv.innerHTML
jsValue.value=myScript.text
}
</script>
</body>
</html>