TL; dr我如何使用返回的CTM:
var ctm = canvas.rawNode.getScreenCTM();
修改屏幕坐标中的dx, dy
矢量,使其处于世界坐标中?在qzxswpoi应该成为{ dx: 1, dy: 0}
,给出上面的SVG示例,其中viewBox { dx: 3.6, dy: 0}
在500px宽的窗口中。
我认为以下内容可行:
0 0 1800 1800
但 var ctm = canvas.rawNode.getScreenCTM();
// Turn this into a dojox/gfx/matrix Matrix2D
var ctmm = new matrix.Matrix2D({xx: ctm.a, xy: ctm.b, dx: ctm.c,
yx: ctm.d, yy: ctm.e, dy: ctm.f});
// Invert this
var itm = matrix.invert(ctmm);
// Multiply screen coords by transform matrix
var worldshift = matrix.multiplyPoint(itm, shift.dx, shift.dy);
console.log('ctm ', ctm, ', shift ', shift, ' became worldshift ', worldshift);
shift.dx = worldshift.x;
shift.dy = worldshift.y;
充满了NaN和Infinity。
CodePen示例后面会出现长版本的问题
我知道这背后的基本数学,但发现自己难以尝试用矩阵变换来做。文档似乎避免了这个主题。情况是:
itm
函数在屏幕坐标中传递它移动的量:
this.host.onMove(this,{dx:x - this.lastX,dy:y - this.lastY});最后一个论点作为onMouseMove
论证传递给dojox/gfx/Moveable.onMoving
,可能是例如{dx:1,dy:0}如果鼠标向右移动一个像素。
如果我们愚蠢地允许框架将其应用于被拖动的形状的平移变换,则其位置与鼠标坐标不完全匹配:shift
(这在dojox演示中工作正常,因为它们的SVG坐标系与屏幕坐标系1匹配: 1)。
我在https://codepen.io/neekfenwick/pen/RxpoMq找到了一些灵感,其中Eugene说“覆盖onMoving你的对象并修改”shift“对象,所以它永远不会移动到指定边界之外的形状。”,这似乎是修改http://grokbase.com/t/dojo/dojo-interest/08anymq4t9/gfx-constrainedmoveable对象的好点,所以我的下一个尝试声明一种新类型的shift
并覆盖dojox/gfx/Moveable
。
我已经尝试使用矩阵变换来获得SVG的屏幕CTM(它出现在onMoving
的一个对象中)并使用直接矩阵运算将其用作{ a, b, c, d, e, f }
dojox/gfx
(Matrix2D
)。目的是修改{ xx, xy, dx, yx, yy, dy }
对象,在将屏幕单位用于形状的变换矩阵之前将其转换为世界单位,但发现自己非常困惑。首先,CTM似乎有一个大约50的大dy,它立即使形状从屏幕底部射出。这是我最近非常混乱和破碎的尝试:shift
我可以手动获取CTM的x和y比例值并将它们应用到shift对象:https://codepen.io/neekfenwick/pen/EoWNOb
如何使用https://codepen.io/neekfenwick/pen/KZWapa和Matrix2D.invert()
等矩阵运算来获取SVG的坐标系,产生一个转换矩阵,从屏幕坐标转换为世界坐标,并将其应用于鼠标移动的dx,dy?
我得到了一个工作的例子,只从Matrix2D.multiplyPoint()
中获取a
和d
,只填充DOMMatrix
的xx
和yy
元素:Matrix2D
https://codepen.io/neekfenwick/pen/mpWgrO
这样,红色圆圈与鼠标光标同步移动。
看起来我在使用 var MyMoveable = declare(Moveable, {
onMoving: function(/* dojox/gfx/Mover */ mover, /* Object */ shift){
// console.log('mover ', mover, ' shift ', shift);
// shift comes in screen coordinates
// Get the Screen Coordinate Transform Matrix
var ctm = canvas.rawNode.getScreenCTM();
// Turn this into a dojox/gfx/matrix Matrix2D
var ctmm = new matrix.Matrix2D({xx: ctm.a, yy: ctm.d});
// Invert this
var itm = matrix.invert(ctmm);
// Multiply screen coords by transform matrix
var worldshift = matrix.multiplyPoint(itm, shift.dx, shift.dy);
console.log('ctm ', ctm, ', shift ', shift, ' became worldshift ', worldshift);
// Replace the shift dx,dy vector with the transformed coordinates
shift.dx = worldshift.x;
shift.dy = worldshift.y;
}
});
属性时过于热心,试图使用所有元素来填充我的DOMMatrix
的xy
,yx
等元素,以用作在鼠标移动向量上使用的变换矩阵的基础。我发现文档Matrix2D
相当难以遵循,因为它没有在网格中布置矩阵元素所以我认为a,b,c,d,e,f只是简单地布置在3x3网格中:
https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrix
然而,文档的“3D Equivalent”部分表明它实际上是某种4x4矩阵(这里我使用?对于未指定的元素,我不确定默认值是什么):
{ a, b, c,
d, e, f,
0, 0, 1 }
所以我仍然很困惑,但至少有一个使用{ a, b, ?, ?,
c, d, ?, ?,
?, ?, ?, ?,
e, f, ?, ? }
操作的解决方案。
我还尝试过使用纯SVG操作来创建SVGPoint并使用DOMMatrix操作对其进行转换,但转换矩阵的偏移量为100或200,我放弃了它:Matrix2D