dojox.gfx.Moveable将屏幕坐标转换为世界坐标以进行拖动

时间:2017-12-28 08:27:10

标签: svg matrix draggable coordinate-transformation dojox.gfx

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示例的长版问题

我知道这背后的基本数学,但发现自己难以尝试用矩阵变换来做。文档似乎避免了这个主题。情况是:

  • SVG节点有viewBox定义世界坐标,比如0,0到 1800,1800
  • SVG节点位于将其缩放到窗口的文档中 尺寸,宽约500px所以SVG中的世界坐标(1800 x 1800单位) 不要将1:1映射到屏幕坐标。每个像素跨度为1800/500 = 3.6 世界单位
  • 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,鼠标移动了吗?

1 个答案:

答案 0 :(得分:0)

我得到了一个有效的示例,仅从d中仅DOMMatrixxx填充yyMatrix2D元素{{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>

相关问题