如何使用RxJS编写拖动锁代码?

如何使用RxJS编写拖动锁代码?,rxjs,reactive-programming,Rxjs,Reactive Programming,拖动锁定交互从第一次双击开始,然后是一些鼠标移动,最后是第二次双击。它是拖放的一种变体 我想用RxJS编写这个交互,但我面临的一个大问题是相同的事件(双击)开始和结束交互(编写拖放代码时没有这个问题) 如何使用RxJS实现拖动锁? 我想订阅第一次单击、所有移动和最后的双击。plunker: 让我们定义一个事件-DragLockEvent,它由类型“DragLockEventType”组成,可以是“initialClick”、“move”或“finalClick”,如果是“move”类型,则定义鼠

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

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

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

plunker:

让我们定义一个事件-DragLockEvent,它由类型“DragLockEventType”组成,可以是“initialClick”、“move”或“finalClick”,如果是“move”类型,则定义鼠标移动事件

现在,让我们创建一个可观察对象,它将发出这些事件: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 }))
});
type DragLockEventType='initialClick'|'move'|'finalClick';
接口拖缆孔{
类型:DragLockEventType;
moveEvent?:MouseEvent;
}
const dragLock$:Observable=Observable.create((观察者:观察者)=>{
设拖动=假;
常量双击$=fromEvent(document.documentElement“dblclick”)
.pipe(takeWhile(()=>!observer.closed));
const mouseMove$=fromEvent(document.documentElement,“mouseMove”)
.pipe(takeWhile(()=>!observer.closed));
双击$
.烟斗(
点击(()=>{
拖动=!拖动;
if(拖动)observer.next({type:'initialClick'});
else observer.next({type:'finalClick'});
}),
过滤器(()=>拖动),
switchMap(()=>mouseMove$.pipe(takeUntil(双击$))
)
.subscribe((e:MouseEvent)=>observer.next({type:'move',moveEvent:e}))
});

太棒了!两个问题:1/使用
管道
是否有任何技术原因,或者您只想处理纯函数?2/我将代码移植到RxJava(它不提供任何
管道
),我必须在语句
末尾添加
.share()
。为什么代码中不需要
share()
?可能与管道的使用有关。管道在rxjs中是一个相当新的概念。不是通过调用“import'rxjs/add/operator/…”将运算符添加到Observable.prototype,而是通过使用.pipe()来使用运算符,这样就不会污染Observable.prototype。这里有一些关于这个概念的链接:2。共享操作符所做的是使所有订阅方订阅同一个可观察对象的“实例”,这意味着所有订阅都共享同一个可观察对象,而不是为每个订阅创建新的可观察对象。如果doubleClick$observable有多个订阅服务器,则需要一个share()操作符来同步所有订阅服务器。