我正在努力应对RXJS的拖放行为。我想在250ms鼠标按下后开始拖动一个元素,因为没有劫持该元素上的点击事件。
到目前为止,开始拖动工作但停止拖动永远不会被调用。谁知道为什么?
let button = document.querySelector('.button');
let mouseDownStream = Rx.Observable.fromEvent(button, 'mousedown');
let mouseUpStream = Rx.Observable.fromEvent(button, 'mouseup');
let dragStream = mouseDownStream
.flatMap((event) => {
return Rx.Observable
.return(event)
.delay(250)
.takeUntil(mouseUpStream)
});
let dropStream = mouseUpStream
.flatMap((event) => {
return Rx.Observable
.return(event)
.skipUntil(dragStream)
});
dragStream.subscribe(event => console.log('start drag'));
dropStream.subscribe(event => console.log('stop drag'));
答案 0 :(得分:4)
我已经更新了您的代码示例以使其运行,我做了什么:
flatMap
s交换switchMap
s switchMap
是flatMapLatest
的别名)这将确保它只接收最新事件以及新事件发出后,它将取消任何旧的subevent =>在这种情况下,flatMap
可能会正常工作,但使用switchMap
更安全,这也是一条经验法则:如有疑问:请使用switchMap
dropStream
基于dragStream
现在skipUntil
,这是一个竞赛条件问题,因为它会在一些mouseUp(需要及时返回)后的下一个dragStream发射之后首先触发。button
交换到document
(更多的是一个方便的东西,而不是真正必不可少的工作)
let button = document.querySelector('.button');
let mouseDownStream = Rx.Observable.fromEvent(button, 'mousedown');
let mouseUpStream = Rx.Observable.fromEvent(document, 'mouseup');
let dragStream = mouseDownStream
.switchMap((event) => {
return Rx.Observable
.return(event)
.delay(250)
.takeUntil(mouseUpStream)
});
let dropStream = dragStream
.switchMap(() => mouseUpStream.take(1))
dragStream.subscribe(event => console.log('start drag'));
dropStream.subscribe(event => console.log('stop drag'));

<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.all.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<button class="button">Button</button>
</body>
</html>
&#13;
答案 1 :(得分:0)
具有TypeScript和更新的rxjs的通用拖动事件
export const DragEvent = (selector:string):Observable<boolean> => {
//element where the drag event should be recorded (make sure element is in the dom)
const elem = document.querySelector(selector);
// touch events to handle mobile devices
const touchStart$ = fromEvent<TouchEvent>(elem, 'touchstart');
const touchEnd$ = fromEvent<TouchEvent>(elem, 'touchend');
const touchMove$ = fromEvent<TouchEvent>(elem, 'touchmove');
// mouse events for desktop users
const mouseDown$ = fromEvent<MouseEvent>(elem, 'mousedown');
const mouseUp$ = fromEvent<MouseEvent>(elem, 'mouseup');
const mouseMove$ = fromEvent<MouseEvent>(elem, 'mousemove');
//Mouse drag event
const mouseDragging$ = mouseMove$.pipe(
skipUntil(mouseDown$),
takeUntil(mouseUp$)
);
//
const mapToBoolean = (bool) => map(() => bool);
//universal drag event will emit true on drag (desktop/mobile) optional:add touchStart$ to the merge.
const move$ = merge(mouseDragging$, touchMove$).pipe(mapToBoolean(true);
//universal end of drag event will emit false on drag end (desktop/mobile)
const end$ = merge(mouseUp$, touchEnd$).pipe(mapToBoolean(false);
//merged to return true or false depending on user dragg
return merge(move$, end$).pipe(distinctUntilChanged());
}