RxJs 如何处理文档事件

RxJs How do deal with document events

开始使用 RxJs。找不到解决此问题的方法。我有一个可拖动的控件:

startDrag = rx.Observable.fromEvent(myElem,'mousedown')

现在,因为控件太小 mousemovemouseup 事件应该在文档级别(否则它不会停止拖动,除非光标正好在元素上)

endDrag = rx.Observable.fromEvent document,'mouseup'

position = startDrag.flatMap ->
   rx.Observable.fromEvent document,'mousemove'
   .map (x)-> x.clientX
   .takeUntil endDrag

现在如何 "catch" 不再被拖拽的正确时刻 (mouseup)。 您看到订阅 endDrag 的问题了吗?每次点击任何地方都会触发,而不仅仅是 myElem 如何一次检查所有 3 个属性?它应该只取恰好在 startDragposition

之后发生的那些 document.mouseups

Upd:我的意思是问题不在于移动元素。那部分很简单 - 订阅 position,更改元素的 css。 我的问题是 - 我需要检测 mouseup 的时刻并知道被拖动的确切元素(页面上有多个元素)。我不知道该怎么做。

我已经调整了 RxJS 存储库中提供的 drag and drop example 以根据您的需要运行。

显着变化:

  • mouseUpdocument 收听。

  • 目标元素从 select 添加到 return。

  • 拖动动作在 mapmap 内部处理 return 是 mouseDown 事件中的目标元素。

  • takeUntil(mouseUp) 之后调用 last 所以 subscribe 只会在拖动过程结束时到达(每次拖动一次)。

工作示例:

function main() {
  var dragTarget = document.getElementById('dragTarget');

  // Get the three major events
  var mouseup = Rx.Observable.fromEvent(document, 'mouseup');
  var mousemove = Rx.Observable.fromEvent(document, 'mousemove');
  var mousedown = Rx.Observable.fromEvent(dragTarget, 'mousedown');


  var mousedrag = mousedown.selectMany(function(md) {

    // calculate offsets when mouse down
    var startX = md.offsetX;
    var startY = md.offsetY;

    // Calculate delta with mousemove until mouseup
    return mousemove.select(function(mm) {
      if (mm.preventDefault) mm.preventDefault();
      else event.returnValue = false;

      return {
        // Include the targeted element
        elem: mm.target,
        pos: {
          left: mm.clientX - startX,
          top: mm.clientY - startY
        }
      };
    })
    .map(function(data) {
      // Update position
      dragTarget.style.top = data.pos.top + 'px';
      dragTarget.style.left = data.pos.left + 'px';

      // Just return the element
      return data.elem;
    })
    .takeUntil(mouseup)
    .last();
  });


  // Here we receive the element when the drag is finished
  subscription = mousedrag.subscribe(function(elem) {
    alert('Drag ended on #' + elem.id);
  });
}
main();
#dragTarget {
  position: absolute;
  width: 20px;
  height: 20px;
  background: #0f0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.7/rx.all.min.js"></script>
<div id="dragTarget"></div>