简体   繁体   English

带条件的 RxJs mousemove 事件

[英]RxJs mousemove event with condition

I'm struggling with this and I have no idea how to proceed.我正在为此苦苦挣扎,我不知道如何继续。 I want to capture mouse event only when the user stops with mousemove for certain time and it's inside specific element.我只想在用户停止使用mousemove一段时间并且它在特定元素内时捕获鼠标事件。

 const { fromEvent } = rxjs; const { debounceTime, tap, filter } = rxjs.operators; const square = document.querySelectorAll("#square"); let isCursorOverSquare = true; const move$ = fromEvent(square, "mousemove"); const enter$ = fromEvent(square, "mouseenter"); const leave$ = fromEvent(square, "mouseleave"); enter$.pipe( tap(() => isCursorOverSquare = true) ).subscribe(); leave$.pipe( tap(() => isCursorOverSquare = false) ).subscribe(); move$ .pipe( debounceTime(2000), filter(() => isCursorOverSquare) ) .subscribe( (e) => { console.log(e.target); });
 #square { width: 200px; height: 200px; display: block; border: 1px solid black; }
 <script src="https://unpkg.com/rxjs@6.3.2/bundles/rxjs.umd.min.js"></script> <div id="square"></div>

The thing I can't figure out is, how to skip the console.log , if the user moves from square to outside (ie handle the logic only, when user is with cursor inside the square).我无法弄清楚的是,如何跳过console.log ,如果用户从正方形移动到外部(即仅处理逻辑,当用户在正方形内使用光标时)。

EDIT: I managed to work it, but it's not the "RxJs" way.编辑:我设法解决了它,但这不是“RxJs”方式。 Now I'm setting the isCursorOverSquare variable to true and false and then I use filter operator.现在我将isCursorOverSquare变量设置为truefalse ,然后使用filter运算符。 Is there a "nicer" more reactive way, to handle this?有没有一种“更好”的反应性更强的方法来处理这个问题?

So if i understand your question correctly you want to:因此,如果我正确理解您的问题,您想:

  • Track all mouse movements ( mousemove event stream - fromevent )跟踪所有鼠标移动( mousemove事件流 - fromevent
  • After movement stops for a certain time ( debounce )运动停止一段时间后( debounce
  • Verify it is within a bounding box ( filter )验证它在边界框内( filter

So depending on performance you can either always event the mousemoves or only start mousemove eventing after entering the square using the .switchMap() operator:因此,根据性能,您可以始终事件 mousemove 或仅在使用.switchMap()运算符进入方块后才启动 mousemove 事件:

enter$
  .switchMap(_ => $moves
    .debounceTime(2000)
    .takeUntil(leave$)
  )
  .subscribe(finalMouseMoveEventInSquare => {});

The issue that you have is the last mousemove event is triggered when the cursor is still in the square, but the debounce delays the observable until after the cursor has left the square.您遇到的问题是最后一个mousemove事件在光标仍在方块中时被触发,但是去抖动将可观察对象延迟到光标离开方块之后。 You can solve this issue by only taking the observable until the mouse has left the square.您可以通过仅获取可观察对象直到鼠标离开正方形来解决此问题。 Here is the complete code for this answer:这是此答案的完整 代码

<head>
    <style>
        #square {
            width: 200px;
            height: 200px;
            display: block;
            border: 1px solid black;
        }
    </style>
</head>

<body>
    <div id="square"></div>
    <script src="https://unpkg.com/rxjs@6.3.2/bundles/rxjs.umd.min.js"></script>
    <script>
        const { fromEvent } = rxjs;
        const { debounceTime, repeat , takeUntil } = rxjs.operators;

        const square = document.getElementById("square");

        const move$ = fromEvent(square, "mousemove").pipe(debounceTime(2000));
        const enter$ = fromEvent(square, "mouseenter");
        const leave$ = fromEvent(square, "mouseleave");

        move$.pipe(takeUntil(leave$), repeat()).subscribe((e) => console.log(e.target));
    </script>
</body>

The repeat operator is necessary as otherwise once the mouse has left the square the first time, the observable will not be repeated when the mouse next enters the square. repeat操作符是必要的,否则一旦鼠标第一次离开方块,当鼠标下一次进入方块时,observable 将不会重复。 If your intended behaviour is for the observable to stop emitting after the mouse has left the square for the first time, feel free to remove the repeat operator.如果您的预期行为是让 observable 在鼠标第一次离开方块后停止发射,请随意删除重复操作符。 Hope this helps you, let me know if you have any questions!希望能帮到你,有什么问题可以私信我!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM