TL;医生 我如何使用返回的CTM:
var ctm = canvas.rawNode.getScreenCTM();
修改屏幕坐标中的dx, dy
向量,使其处于世界坐标中?如果在500px宽的窗口中使用viewBox { dx: 1, dy: 0}
的上述SVG示例,则{ dx: 3.6, dy: 0}
应该变为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;
但是itm
充满了NaN和Infinity。
CodePen示例的长版问题
我知道这背后的基本数学,但发现自己难以尝试用矩阵变换来做。文档似乎避免了这个主题。情况是:
dojox / gfx / Moveable使用dojox / gfx / Mover
onMouseMove
函数传递它在屏幕中移动的数量
坐标:
this.host.onMove(this,{dx:x - this.lastX,dy:y - this.lastY});
最后一个参数作为dojox/gfx/Moveable.onMoving
参数传递给shift
,可能是例如{dx:1,dy:0}如果鼠标向右移动一个像素。
如果我们愚蠢地允许框架将此应用于被拖动形状的平移变换,其位置与鼠标坐标不完全匹配:https://codepen.io/neekfenwick/pen/RxpoMq(这在dojox演示中工作正常,因为它们的SVG坐标系匹配屏幕坐标系1:1)。
我在http://grokbase.com/t/dojo/dojo-interest/08anymq4t9/gfx-constrainedmoveable找到了一些灵感,其中Eugene说"覆盖onMoving你的对象并修改" shift"对象所以它永远不会移动指定边界之外的形状。",这似乎是修改shift
对象的好点,因此我的下一次尝试声明了一种新类型dojox/gfx/Moveable
并覆盖{ {1}}。
我尝试使用矩阵变换来获取SVG的屏幕CTM(来自onMoving
的对象)并将其用作{ a, b, c, d, e, f }
dojox/gfx
({{1} })使用直矩阵运算。目的是修改Matrix2D
对象,将屏幕单位转换为世界单位,然后再将其用于形状的变换矩阵,但发现自己非常困惑。首先,CTM似乎有一个大约50的大dy,它立即使形状从屏幕底部射出。这是我最近非常混乱和破碎的尝试:https://codepen.io/neekfenwick/pen/EoWNOb
我可以手动拍摄CTM的x和y比例值并将它们应用到移位对象:https://codepen.io/neekfenwick/pen/KZWapa
如何使用{ xx, xy, dx, yx, yy, dy }
和shift
之类的矩阵运算来获取SVG的坐标系,产生转换矩阵以从屏幕坐标转换为世界坐标,并将其应用于dx ,dy,鼠标移动了吗?
答案 0 :(得分:0)
我得到了一个有效的示例,仅从d
中仅DOMMatrix
和xx
填充yy
和Matrix2D
元素{{1} }: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
的{{1}},yx
等元素以用作用于鼠标移动矢量的变换矩阵的基础。我发现文档https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrix相当难以理解,因为它没有在网格中布置矩阵元素,所以我认为a,b,c,d,e,f只是在3x3中布局格:
Matrix2D
然而,文档中的“3D Equivalent”部分表明它实际上是某种4x4矩阵(这里我使用?对于未指定的元素,我不确定默认值是什么):
{ a, b, c,
d, e, f,
0, 0, 1 }
所以我仍然很困惑,但至少要使用{ a, b, ?, ?,
c, d, ?, ?,
?, ?, ?, ?,
e, f, ?, ? }
操作来解决问题。
我还尝试过使用纯SVG操作来创建SVGPoint并使用DOMMatrix操作对其进行转换,但转换矩阵的偏移量为100或200,我放弃了它:https://codepen.io/neekfenwick/pen/BJWEZw < / p>