3

我正在尝试使用代理事件(on-mousedown、up、move、out)使用 RactiveJS 实现一个简单的可拖动 DIV

跟随JSFiddle工作得很好,但是当用户移动鼠标太快时,拖动停止。这仅仅是因为在我的例子中,mouseevent 处理程序位于 DIV 标记而不是正文或文档元素上。我的最终想法是创建一个滑块组件,但是我正在寻求提供最佳的用户体验并使这项工作更像 JQuery 的可拖动。

模板:

<div class="rect {{drag ? 'dragging' : ''}}" 
         on-mousedown="startDrag"
         on-mouseup="stopDrag" 
         on-mouseout="stopDrag" 
         on-mousemove="drag"
         style="top:{{top}}px; left:{{left}}px;">
</div>

活性实例:

var ractive = new Ractive({
    el: "#content",
    template: "#template",
    data: {left:20,top:80}
});
ractive.on({
    startDrag : function (event) {
        this.set({
            'drag': true,
            'mouseX': event.original.clientX - this.get('left'),
            'mouseY': event.original.clientY - this.get('top')
        });
    },
    stopDrag : function (event) {
        this.set('drag', false);
    },
    drag : function (event) {
        if(this.get('drag')) {
            var x = event.original.clientX, 
                y = event.original.clientY;
            this.set({
                top: y - this.get('mouseY') ,
                left: x - this.get('mouseX')
            });
            event.original.stopPropagation();
        }
    }
})

如何改进上述代码?

4

2 回答 2

5

通常mousemove并且mouseend需要在document. 我发现使用 Ractive 装饰器通常更适合拖动。这是一个让你开始的例子(http://jsfiddle.net/h9j2hdyj/1/):

<div class="rect noSelect {{ dragging ? 'dragging' : ''}}" 
     decorator='drag:"position"'
     style="{{#position}}top:{{top}}px;left:{{left}}px{{/}}">
</div>

装饰师:

Ractive.decorators.drag = function(node, keypath){

    var ractive = this, initial, begin, startPos;

    node.addEventListener('mousedown', start, false)

    function listenOnDocument(){
        document.addEventListener('mousemove', move, false)
        document.addEventListener('mouseup', unlistenOnDocument, false)
    }

    function unlistenOnDocument(){
        document.removeEventListener('mousemove', move, false)
        document.removeEventListener('mouseup', end, false)
    }

    function start(e){
        begin = { x: e.x, y: e.y }
        startPos = ractive.get(keypath)
        startPos = { x: startPos.left, y: startPos.top }
        ractive.set('dragging', true)
        listenOnDocument()
        e.preventDefault()
        e.stopPropagation()
    }

    function move(e){
        ractive.set(keypath, {
            left: startPos.x + (e.x - begin.x),
            top: startPos.y + (e.y - begin.y)
        })
        e.preventDefault()
        e.stopPropagation()
    }

    function end(){
        unlistenOnDocument()
        ractive.set('dragging', false)
    }

  return {
      update: function(pos){
          console.log(pos)
          position = pos
      },
    teardown: function(){
        node.removeEventListener('mousedown', start, false)
        end()
    }
  }

}
于 2014-09-25T19:25:38.193 回答
2

另一种选择是使用ractive-touch插件的pan事件 - 它们在引擎盖下使用 Hammer.js,因此它们对鼠标和触摸友好。

于 2014-09-25T21:38:56.940 回答