飞镖SVG拖放滑动鼠标

时间:2013-12-08 09:14:39

标签: html5 svg dart

我尝试使用SVG在Dart中创建拖放行为。我的BasicUnit基本上是GElement<g>)s。现在它有一个body,即RectElement。我正在使用该元素移动单位。这是定义:

class BasicUnit {

  SvgSvgElement canvas;
  GElement group;
  RectElement body;
  bool dragging;
  num dragOffsetX, dragOffsetY, width, height;

  BasicUnit(SvgSvgElement this.canvas, num x, num y, num this.width, num this.height) {
    this.body = new RectElement();
    this.body.setAttribute('x', '$x');
    this.body.setAttribute('y', '$y');
    this.body.setAttribute('width', '$width');
    this.body.setAttribute('height', '$height');
    this.body.classes.add('processing_body');

    this.body.onMouseDown.listen(select);
    this.body.onMouseMove.listen(moveStarted);
    this.body.onMouseUp.listen(moveCompleted);
    this.body.onMouseLeave.listen(moveCompleted);

    this.group = new GElement();
    this.group.append(this.body);

    this.dragging = false;
  }

  void select(MouseEvent e) {
    e.preventDefault();
    this.dragging = true;

    var mouseCoordinates = getMouseCoordinates(e);
    this.dragOffsetX = mouseCoordinates['x'] - body.getCtm().e; //double.parse(body.attributes['x']);
    this.dragOffsetY = mouseCoordinates['y'] - body.getCtm().f;
  }

  void moveStarted(MouseEvent e) {
    e.preventDefault();

    if (dragging) {
      var mouseCoordinates = getMouseCoordinates(e);
      num newX = mouseCoordinates['x'] - dragOffsetX;
      num newY = mouseCoordinates['y'] - dragOffsetY;
      this.body.setAttribute('transform', 'translate($newX, $newY)');
    }
  }

  void moveCompleted(MouseEvent e) {
    e.preventDefault();
    this.dragging = false;
  }

  dynamic getMouseCoordinates(e) {
    return {'x': (e.offset.x - this.canvas.currentTranslate.x)/this.canvas.currentScale, 
            'y': (e.offset.y - this.canvas.currentTranslate.y)/this.canvas.currentScale};
  }
}

我有一个Application个对象。它获取给定svg的{​​{1}}元素。这是定义:

id

我的问题是我的鼠标滑过class Application { int WIDTH = 80, HEIGHT = 60; SvgSvgElement canvas; Application(canvas_id) { this.canvas = document.querySelector(canvas_id); this.canvas.onDoubleClick.listen((MouseEvent e) => addUnit(e)); } void addUnit(MouseEvent e) { num x = e.offset.x - WIDTH/2; num y = e.offset.y - HEIGHT/2; BasicUnit newUnit = new BasicUnit(this.canvas, x, y, WIDTH, HEIGHT); this.canvas.append(newUnit.group); } } BasicUnit元素。当您选择靠近其边缘的元素并尝试拖动时,突然元素会被删除。如果你试图快速拖放,那也是如此。我试图按照this webpage上的示例,但无法弄清问题是什么。

更新 完整源代码here

更新II Here是一个演示。

1 个答案:

答案 0 :(得分:1)

双击页面后,浏览器正在尝试拖动选中的文本。这可以通过阻止onMouseDown事件(您的select方法)的默认行为来轻松修复:

void select(MouseEvent e) {
  e.preventDefault();
  this.dragging = true;
  this.group.parentNode.append(this.group);

  var mouseCoordinates = this.getMouseCoordinates(e);
  this.dragOffsetX = mouseCoordinates['x'] - this.body.getCtm().e;        
  this.dragOffsetY = mouseCoordinates['y'] - this.body.getCtm().f; 
}

另一个问题是由于svg绘制速度不够快,无法跟上鼠标坐标。因此,当移动得足够快时,鼠标坐标移动到SVG元素的主体之外,因此该元素将不再获得鼠标移动事件。这可以通过在后台SVG元素(示例中的画布)上侦听onMouseMove和onMouseLeave事件而不是移动的元素来解决:

body.onMouseDown.listen(select);
canvas.onMouseMove.listen(moveStarted);
body.onMouseUp.listen(moveCompleted);
canvas.onMouseLeave.listen(moveCompleted);

编辑:

除非在被拖动的元素位于另一个元素下方时发生onMouseUp,否则使用上述方法是有效的,在这种情况下,元素仍然被拖动,直到该元素上发生另一个onMouseUp事件,或者光标移动到查看区域之外。这可以通过在画布上而不是body上监听onMouseUp事件来解决:

canvas.onMouseUp.listen(moveCompleted);

请参阅this example

另外,在单击元素时(在select方法中)打开onMouseMove,onMouseUp和onMouseLeave侦听器可能会更好,然后在onMouseUp和onMouseLeave(moveCompleted方法)上禁用侦听器。我在上面的例子中做过这个。