开发者

How can I prevent mousemove events while mouse button is pressed?

I got a grid that I want to move mouse over. While I am just hovering and moving mouse I want events to fire, but when I press mousedown they sh开发者_JS百科ould pause firing. Once I fire mouseup they should continue.

If that sounds super easy, it probably isn't. After some time we came up with a not very elegant solution, but I wonder whether something better exists. I won't influence your approach with our hack.

So initial code that doesn't work

mouseMove.TakeUntil(mouseDown).Repeat()

Adding .SkipUntil(mouseUp) left or right to TakeUntil basicly stop above code from working at all.


How about this:

bool mouseIsDown = false;
Observable.Merge(
    mouseDown.Select(_ => true),
    mouseUp.Select(_ => false)
).Subscribe(x => mouseIsDown = x);

mouseMove.Where(_ => !mouseIsDown);

The technically correct answer involves the Window operator, but this is just as good and easier to grok (and easier for me to write)


this could be a posible solution

// create the observables
IObservable<Point> mouseMove = Observable.FromEventPattern<MouseEventArgs>(this, "MouseDown")
    .Select(e=>e.EventArgs.GetPosition(this));

IObservable<bool> mouseDown = Observable.FromEventPattern(this, "MouseDown").Select(_ => false);
IObservable<bool> mouseUp = Observable.FromEventPattern(this, "MouseUp").Select(_ => true);

var merged = mouseUp.Merge(mouseDown).StartWith(true);

// sends the moves with the current state of the mouse button
var all = mouseMove.CombineLatest(merged, (move, take) => new {Take = take, Move = move});

// the result is all the points from mouse move where the mouse button isn't pressed
var result = all.Where(t => t.Take).Select(t => t.Move);


Below are 2 possible solutions

var beh = new BehaviorSubject<bool>(true);
mousedown.Select(_ => false).Subscribe(beh);
mouseup.Select(_ => true).Subscribe(beh);
mousemove.SelectMany(e =>
{
     return mousemove.TakeUntil(beh.Where(b => !b));
}).Subscribe( .... );

OR

var du = mousedown.Select(_ => false).Merge(mouseup.Select(_ => true)).Merge(Observable.Return(true));
mousemove.CombineLatest(du, (ev, b) => new Tuple<MouseEventArgs, bool>(ev.EventArgs, b))
 .Where(t => t.Item2)
 .Select(t => t.Item1)
 .Subscribe(....);


This works:

        var mouseMoveWhileUpOnly =
            mouseUp
                .Select(mu =>
                    mouseMove
                        .TakeUntil(mouseDown))
                .Switch();

The only trick you need to do to get the observable started without actually needing to manually do a mouse up is this:

        var mouseUp = Observable
            .FromEventPattern<MouseButtonEventHandler, MouseButtonEventArgs>(
                h => this.MouseLeftButtonUp += h,
                h => this.MouseLeftButtonUp -= h)
            .Select(ep => Unit.Default)
            .StartWith(Unit.Default);

Note the StartWith.

Otherwise the mouseDown & mouseMove observables are defined normally.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜