如何使用Drag and Drop RxJs's example实现mousedragstart
Observable。
mousedragstart
应在mousedrag
之后的mousedown
之前发出,直到mouseup
。
我认为我们必须使用flatMap
/ take(1)
/ takeUntil(mouseup)
但我每次都会失败..
更新
此处的难度不能避免在mousedrag
mousedragstart
答案 0 :(得分:4)
基于我之前的,未解决根本问题的答案以及您提供的信息,我们在概念上定义如下:
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)
);
这里的问题是事件之间的重叠;在与基础事件的关系方面,dragstart与第一个dragmove完全相同。在这种情况下,订阅顺序将决定执行的顺序,正如您所说,这不是您想要依赖的。为了解决这个问题,我们必须控制基础事件。
这是一个简单的函数,它接受一个observable并返回一个包含两个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
];
}
从那里,我们可以用以下内容替换上面的相应部分:
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'));
这是完整的工作:
答案 1 :(得分:0)
它应该像
一样简单fminsearch
但事实并非如此。 Chrome在mousedown之后立即引发mousemove事件,这将导致上述逻辑在用户实际开始拖动之前错误地产生一个元素。所以你实际上需要这样的东西:
var mousedragstart = mousedown.flatMap(() => mousemove.takeUntil(mouseup).take(1));
答案 2 :(得分:0)
拖放的另一种解决方案:
let dragDiv = document.getElementById('drag');
let mouseisdown = false;
let startPos;
Observable.fromEvent(dragDiv, "mousedown").subscribe((e) => {
mouseisdown = true;
startPos = { x: e.offsetX, y: e.offsetY}
});
Observable.fromEvent(document, "mouseup").subscribe(e => mouseisdown = false);
Observable
.fromEvent(document, "mousemove")
.filter(e => mouseisdown)
.map((e) => {
return {
left: e.clientX - startPos.x,
top: e.clientY - startPos.y
}
})
.subscribe( p => {
dragDiv.style.top = p.top + "px";
dragDiv.style.left = p.left + "px";
});
打字稿版本:
let dragDiv = document.getElementById('drag');
let mouseisdown = false;
let startPos;
Observable.fromEvent(dragDiv, "mousedown").subscribe((e:MouseEvent) => {
mouseisdown = true;
startPos = { x: e.offsetX, y: e.offsetY}
});
Observable.fromEvent(document, "mouseup").subscribe(e => mouseisdown = false);
Observable
.fromEvent(document, "mousemove")
.filter(e => mouseisdown)
.map((e:MouseEvent) => {
return {
left: e.clientX - startPos.x,
top: e.clientY - startPos.y
}
})
.subscribe( p => {
dragDiv.style.top = p.top + "px";
dragDiv.style.left = p.left + "px";
});