如何使用RxJS编写拖动锁?

时间:2018-04-15 17:05:07

标签: rxjs reactive-programming

拖动锁定交互从首次双击开始,然后是一些鼠标移动,然后以第二次双击结束。它是拖放的一种变体。

我想在RxJS中编写这种交互,但我面临的一个大问题是同一事件(双击)开始和结束交互(编码拖放时我们没有的问题)。

如何使用RxJS实现拖锁? 我想订阅第一次点击,所有移动和最后双击。

1 个答案:

答案 0 :(得分:1)

plunker:https://plnkr.co/edit/MXUtPzH9iD40VjVxLBwB?p=preview

让我们定义一个事件 - DragLockEvent,它包含" DragLockEventType"这可能是' initialClick',' move'或者' finalClick'以及鼠标移动事件,以防它类型为'移动'。

现在让我们创建一个可以发出这些事件的observable:dragLock $。

在观察者的内部,有一个标志 - "拖动",表明我们是否正在拖动。

现在我们需要听双击事件,对于每个这样的事件,我们需要切换拖动标志,并发出匹配事件。

然后,如果我们处于拖动模式,我们开始收听鼠标移动事件并报告它们,直到我们再次双击。

type DragLockEventType = 'initialClick' | 'move' | 'finalClick';

interface DragLockEvent {
    type: DragLockEventType;
    moveEvent?: MouseEvent;
}

const dragLock$: Observable<DragLockEvent> = Observable.create((observer: Observer<DragLockEvent>) => {
    let dragging = false;

    const doubleClick$ = fromEvent(document.documentElement, 'dblclick')
        .pipe(takeWhile(() => !observer.closed));
    const mouseMove$ = fromEvent(document.documentElement, 'mousemove')
        .pipe(takeWhile(() => !observer.closed));

    doubleClick$
        .pipe(
            tap(() => {
                dragging = !dragging;
                if (dragging) observer.next({ type: 'initialClick' });
                else observer.next({ type: 'finalClick' });
            }),
            filter(() => dragging),
            switchMap(() => mouseMove$.pipe(takeUntil(doubleClick$)))
        )
        .subscribe((e: MouseEvent) => observer.next({ type: 'move', moveEvent: e }))
});