我一直在玩RXJS6。我正在尝试实现dragstart, dragmove and dragend
。这是我目前掌握的密码。
import { fromEvent } from 'rxjs';
import { concatMap } from 'rxjs/internal/operators/concatMap';
import { map } from 'rxjs/internal/operators/map';
import { takeUntil } from 'rxjs/internal/operators/takeUntil';
import { repeat } from 'rxjs/internal/operators/repeat';
import { first } from 'rxjs/internal/operators/first';
const mousedown = fromEvent<MouseEvent>(window, 'mousedown');
const mousemove = fromEvent<MouseEvent>(window, 'mousemove');
const mouseup = fromEvent<MouseEvent>(window, 'mouseup');
const dragstart = mousedown.pipe(
first()
);
const dragmove = mousedown.pipe(
concatMap((dragStartEvent) => mousemove.pipe(
takeUntil(mouseup))
)
);
const dragend = mousedown.pipe(
(dragEvent) => mouseup.pipe(first())
);
const log = (prefix: string) => (data: MouseEvent) => console.log(`${prefix}: x: ${data.clientX}, y:${data.clientY}`);
dragstart.subscribe(log('dragstart'));
dragmove.subscribe(log('dragmove'));
dragend.subscribe(log('dragend'));
问题是运算符
takeUntil
和first
将流标记为已完成。这意味着
dragstart
和dragend
只会发射一次。有没有办法在事件发生后重置流?例如,当
dragstart
流接收到事件时重置mouseup
流。附加说明
在当前实现中,
dragstart
和dragend
将在加载页面(和拖动)后准确地记录到控制台。在此之后,流完成,不再通过它发送事件。我想重置每个拖动操作的流,这样dragstart&dragend将处理每个拖动操作,而不仅仅是加载页面后的第一个操作。当前行为([]表示发生的鼠标操作,斜体文本是控制台输出):
第一次拖动操作
[老鼠镇]
dragstart公司
[鼠标移动]
德拉格莫夫
[鼠标]
德拉根德
第二次拖动操作
[老鼠镇]
(没有发生任何事情,但是dragstart应该被记录到控制台)
[鼠标移动]
德拉格莫夫
[鼠标]
(没有发生任何事情,但是dragend应该记录到控制台)
最佳答案
请看这里的工作示例
https://codepen.io/anon/pen/bMWjEVenter link description here
const { fromEvent } = Rx.Observable;
const target = document.querySelector('.box');
const mouseup = fromEvent(target, 'mouseup');
const mousemove = fromEvent(document, 'mousemove');
const mousedown = fromEvent(target, 'mousedown');
let log = (prefix: string, x:number, y:number) => console.log(`${prefix}: x: ${x}, y:${y}`);
const mousedrag = mousedown.selectMany((md) => {
const startX = md.clientX + window.scrollX,
startY = md.clientY + window.scrollY,
startLeft = parseInt(md.target.style.left, 10) || 0,
startTop = parseInt(md.target.style.top, 10) || 0;
return mousemove.map((mm) => {
mm.preventDefault();
log('mousemove',mm.clientX, mm.clientY);
return {
left: startLeft + mm.clientX - startX,
top: startTop + mm.clientY - startY
};
}).takeUntil(mouseup);
});
subscription = mousedrag.subscribe((pos) => {
log('dragstart',pos.top, pos.left)
target.style.top = pos.top + 'px';
target.style.left = pos.left + 'px';
});
.box {
position: relative;
width: 100px;
height: 100px;
background: red;
cursor: pointer;
border:solid 10px green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/2.5.2/rx.all.js"></script>
<div class="box"></div>
关于typescript - RxJS6:完成后重置流,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50133103/