RxJs:拖放示例:添加 mousedragstart

plo*_*ne1 3 javascript system.reactive rxjs

如何mousedragstart使用拖放 RxJs 的示例实现Observable 。

mousedragstart应该在第一个mousedrag之后的第一个mousedown之前发出,直到mouseup.

我认为我们必须玩flatMap/ take(1)/takeUntil(mouseup)但我每次都失败了..


更新

这里的困难不是避免mousedrag被发射之前mousedragstart

Mat*_*ell 5

基于我之前的未解决根本问题的答案以及您提供的信息,我们在概念上定义了如下内容:

var dragTarget = document.getElementById('dragTarget');

var mouseup   = Rx.Observable.fromEvent(document,   'mouseup');
var mousemove = Rx.Observable.fromEvent(document,   'mousemove');
var mousedown = Rx.Observable.fromEvent(dragTarget, 'mousedown');

var dragstart = mousedown.flatMap(() =>
  mousemove
   .where(x => x.movementX !== 0 || x.movementY !== 0)
   .takeUntil(mouseup)
   .take(1)
);

var dragmove = mousedown.flatMap(() =>
  mousemove
    .where(x => x.movementX !== 0 || x.movementY !== 0)
    .takeUntil(mouseup)
);
Run Code Online (Sandbox Code Playgroud)

这里的问题是事件之间的重叠;就与底层事件的关系而言,dragstart 是由与第一个 dragmove 完全相同的事情触发的。在这种情况下,订阅顺序将决定执行顺序,正如您所说,这不是您想要依赖的。为了解决这个问题,我们必须控制潜在的事件。

这是一个简单的函数,它接受一个 observable 并返回一个包含两个 observable 的数组,该数组将发出与原始 observable 相同的值,但其中事件将始终在第二个 observable 之前传递给第一个 observable,无论订阅了哪个第一的:

function prioritize(s$) {
  var first = new Rx.Subject();
  var second = s$.do(x => first.onNext(x)).share();

  return [
    Rx.Observable.using(
      () => second.subscribe(() => {}),
      () => first
    ),
    second
  ];
}
Run Code Online (Sandbox Code Playgroud)

从那里,我们可以用这样的东西替换上面的适当部分:

var mousedowns = prioritize(mousedown);

var dragstart = mousedowns[0].flatMap(() =>
 mousemove
   .where(x => x.movementX !== 0 || x.movementY !== 0)
   .takeUntil(mouseup)
   .take(1)
);

var dragmove = mousedowns[1].flatMap(() =>
  mousemove
    .where(x => x.movementX !== 0 || x.movementY !== 0)
    .takeUntil(mouseup)
);

dragmove.subscribe(() => console.log('dragmove'));
dragstart.subscribe(() => console.log('dragstart'));
Run Code Online (Sandbox Code Playgroud)

这是整个工作:

https://jsbin.com/qodilerofe/edit?js,console,output