首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RxJS6:完成后重置流

RxJS6:完成后重置流
EN

Stack Overflow用户
提问于 2018-05-02 11:03:50
回答 2查看 455关注 0票数 2

我一直在玩RxJS 6。我正在尝试实现dragstart, dragmove and dragend。这是我到目前为止掌握的密码。

代码语言:javascript
复制
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'));

问题是运算符takeUntilfirst将流标记为已完成。这意味着dragstartdragend只会触发一次。在此事件发生后,是否有办法以某种方式重置流?例如,当dragstart流接收到事件时,通过重置mouseup流。

附加解释

在当前实现中,dragstartdragend将在加载页面(&拖动)后准确地记录到控制台一次。在此之后,流就完成了,并且不会通过它发送更多的事件。我想要重置流,每次拖动操作,以便dragstart & dragend将工作的每一个拖动操作,而不是仅仅是在加载页面后的第一次。

当前行为([]表示发生的鼠标操作,斜体文本是控制台输出):

首次拖动操作

  • 滑鼠
  • 拖起
  • 摩丝
  • 拖曳
  • 鼠嘴
  • 拖尾

二次拖动操作

  • 滑鼠
  • (无论拖放启动记录到控制台,什么都不会发生)
  • 摩丝
  • 拖曳
  • 鼠嘴
  • (任何事情都不会发生,但是应该将拖尾记录到控制台)
EN

回答 2

Stack Overflow用户

发布于 2018-05-02 11:33:16

请参阅这里的工作示例https://codepen.io/anon/pen/bMWjEV在这里输入链接描述

代码语言:javascript
复制
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';
});
代码语言:javascript
复制
.box {
  position: relative;
  width: 100px;
  height: 100px;
  background: red;
  cursor: pointer;
  border:solid 10px green;
}
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/2.5.2/rx.all.js"></script>
<div class="box"></div>

票数 0
EN

Stack Overflow用户

发布于 2019-07-17 12:25:36

但你告诉我这样做:)

如果您从dragstart流中移除管道和"first“运算符

代码语言:javascript
复制
const dragstart = mousedown

这条小溪不会流完。拖移不会完成,因为它是从鼠标向下映射的,而不是dragstart流。

如果您告诉结果流只选择第一个流,则该流将在发出一次后完成。

这一守则应适用于:

代码语言:javascript
复制
const mousedown = fromEvent<MouseEvent>(window, 'mousedown');
const mousemove = fromEvent<MouseEvent>(window, 'mousemove');
const mouseup = fromEvent<MouseEvent>(window, 'mouseup');

// I dont think it's necessary to duplicate
const dragstart = mousedown

// No need to map to something else
const dragend = mouseup

const dragmove = dragstart.pipe(
  concatMapTo( 
    mousemove.pipe(
        takeUntil( dragend )
    )
  )
);



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'));
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50133103

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档