RxJS:区分拖单一的点击RxJS、拖单一

2023-09-14 23:07:47 作者:瞄准你的心

我有一个AngularJS组件,应该到一个单一的点击或拖拽(调整的区域)。反应

I have an AngularJS component that should react to either a single click or a drag (resizing an area).

我开始在我的应用程序中使用RxJS(ReactiveX),所以我试图用它来找到一个解决方案。请求的角侧是次要...

I started to use RxJS (ReactiveX) in my application, so I try to find a solution using it. The Angular side of the request is minor...

要简化问题(和训练自己),我做了一个滑块指令的基础上,rx.angular.js拖放例如:的 http://plnkr.co/edit/UqdyB2 见Slide.js文件(另code是其他实验)。这种逻辑的code是:

To simplify the problem (and to train myself), I made a slider directive, based on the rx.angular.js drag'n'drop example: http://plnkr.co/edit/UqdyB2 See the Slide.js file (the other code is for other experiments). The code of this logic is:

    function(scope, element, attributes)
    {
      var thumb = element.children(0);
      var sliderPosition = element[0].getBoundingClientRect().left;
      var sliderWidth = element[0].getBoundingClientRect().width;
      var thumbPosition = thumb[0].getBoundingClientRect().left;
      var thumbWidth = thumb[0].getBoundingClientRect().width;

      // Based on drag'n'drop example of rx-angular.js
      // Get the three major events
      var mousedown = rx.Observable.fromEvent(thumb,     'mousedown');
      var mousemove = rx.Observable.fromEvent(element,   'mousemove');
      var mouseup   = rx.Observable.fromEvent($document, 'mouseup');

      // I would like to be able to detect a single click vs. click and drag.
      // I would say if we get mouseup shortly after mousedown, it is a single click;
      // mousedown.delay(200).takeUntil(mouseup)
      //   .subscribe(function() { console.log('Simple click'); }, undefined, function() { console.log('Simple click completed'); });

      var locatedMouseDown = mousedown.map(function (event) 
      {
        event.preventDefault();
        // console.log('Click', event.clientX - sliderPosition);
        // calculate offsets when mouse down
        var initialThumbPosition = thumb[0].getBoundingClientRect().left - sliderPosition;
        return { from: initialThumbPosition, offset: event.clientX - sliderPosition };
      });

      // Combine mouse down with mouse move until mouse up
      var mousedrag = locatedMouseDown.flatMap(function (clickInfo) 
      {
        return mousemove.map(function (event)
        {
          var move = event.clientX - sliderPosition - clickInfo.offset;
          // console.log('Move', clickInfo);
          // calculate offsets from mouse down to mouse moves
          return clickInfo.from + move;
        }).takeUntil(mouseup);
      });

      mousedrag 
        .map(function (position)
        {
          if (position < 0)
            return 0;
          if (position > sliderWidth - thumbWidth)
            return sliderWidth - thumbWidth;
          return position;
        })
        .subscribe(function (position) 
        {
          // console.log('Drag', position);
          // Update position
          thumb.css({ left: position + 'px' });
        });
    }

这主要是D'n'D水平的限制和给定的范围内。

That's mostly D'n'D constrained horizontally and to a given range.

现在,我也喜欢听的mousedown,如果鼠标了一小会儿内发生(比如200毫秒,调整),我认为这是一个点击我做了具体的处理(如重置位置零)。

Now, I would like to listen to mousedown, and if mouse up happens within a short while (say 200 ms, to adjust), I see it as a click and I do a specific treatment (eg. resetting the position to zero).

我试着用延迟()。takeUntil(mouseup事件),如在另一个SO回答,但没有成功。也许,可能需要一个开关(),太(避免去拖动路线)。

I tried with delay().takeUntil(mouseup), as seen in another SO answer, without success. Perhaps a switch() might be needed, too (to avoid going the drag route).

你知道吗?先谢谢了。

推荐答案

您可以使用暂停 timeoutWith 如果您正在使用ReactiveX / RxJS)

You can use timeout (timeoutWith if you are using ReactiveX/RxJS)

var click$ = mousedown.flatMap(function (md) {
  return mouseup.timeoutWith(200, Observable.empty());
});

如果鼠标松开不超时发生之前它只是传播一个空观测来代替。如果是的话那么下游的观察者会收到一个事件。

If the mouseup doesn't occur before the timeout it will just propagate an empty Observable instead. If it does then the downstream observer will receive an event.