2013-12-08 94 views
2

我嘗試使用SVG在Dart中創建拖放行爲。我有BasicUnit s基本上是GElement<g>)s。現在它有一個body,這是一個RectElement。我正在使用該元素來移動單位。這裏是定義:Dart SVG Drag and Drop滑動鼠標

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對象。對於給定的id,它得到svg元素。這裏的定義是:

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<g>元素。當您選擇靠近其邊緣的元素並嘗試拖動時,突然元素會被刪除。如果您嘗試快速拖放,那也是如此。我試圖按照this webpage上的示例進行操作,但無法弄清楚問題所在。

UPDATE 完整源代碼可用here

UPDATE II Here是一個演示。

回答

1

瀏覽器嘗試拖動雙擊該頁面後選定的文本。這可以很容易地通過防止默認行爲的onmousedown事件事件(你的選擇方法)是固定的:

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事件,或者光標移動到查看區域之外。這可以通過固定只聽的畫布,而不是身體上onMouseUp事件:

canvas.onMouseUp.listen(moveCompleted); 

this example

此外,在點擊元素(在您的select方法中)時打開onMouseMove,onMouseUp和onMouseLeave偵聽器,然後禁用onMouseUp和onMouseLeave(moveCompleted方法)上的偵聽器可能會更好。我在上面的例子中已經完成了這個。

+0

我很欣賞你的努力,但滑動問題仍然存在。實際上,監聽'canvas' onMouseMove'和'onMouseLeave'最終會被一個單元卡住,除非你將鼠標光標移出'canvas'。請參閱問題中的示例鏈接,該鏈接正常工作。 – mert

+0

它工作正常,我沒有遇到你遇到的問題。試試[這個例子](https://rawgithub.com/ringstaff/dart-drag-and-drop-svg/master/dart_drag_and_drop_svg_JS.html),讓我知道你是否仍然看到相同的問題。 – ringstaff

+0

我想我找到了你所指的問題。我會更新我的答案以反映我發現的內容。 – ringstaff