首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何重新启动循环requestAnimationFrame

如何重新启动循环requestAnimationFrame
EN

Stack Overflow用户
提问于 2021-10-31 15:26:02
回答 1查看 201关注 0票数 0

我正在尝试制作一个游戏,我想使用window.requestAnimationFrame()来让角色移动,这个动作一开始似乎是正确的。

但是问题是,当我在触发后立即重新触发 move()时,移动会越来越快,我有代码blow,move()pause()initListener()都是关于运动的函数。

代码语言:javascript
运行
复制
type state = "init" | "mount" | "moving" | "pause" | "end";

interface position {
  left: number;
  top: number;
}

interface elProps {
  id: string;
  text: string;
  avatar: string;
}

export default class Bullet {
  public el: HTMLElement;
  public targetEl: HTMLElement;
  public unit: string = "px";
  private id:string;
  private state: state;
  private position: position;
  private animationId: number | undefined;
  constructor(props: elProps) {
    if (!props) return;
    this.el = document.createElement("div");

    this.initEl(props);
  }
  initEl(props: elProps) {
    const defaultStyle = {};
    this.el.style["height"] = "40px";
    this.el.style["background"] = "lightblue";
    this.el.style["display"] = "inline-flex";
    this.el.style["position"] = "absolute";
    // 
    const { text, avatar, id } = props;
    this.el.setAttribute("id", id);
    this.id = id
    const textEl = document.createElement("div");
    textEl.innerText = text;
    const avatarEl = document.createElement("img");
    avatarEl.setAttribute("src", avatar);
    //
    this.el.appendChild(avatarEl);
    this.el.appendChild(textEl);
    //
    this.state = "init";
  }
  mount(targetEl: HTMLElement, position: position, unit: string) {
    //
    this.position = position;
    this.unit = unit;
    this.targetEl = targetEl;
    this.el.style["left"] = this.position.left + this.unit;
    //
    targetEl.appendChild(this.el);
    //
    this.state = "mount";
    const domEl = document.querySelector(`#${SPECIAL_ID}`);
    if (!domEl) {
      throw new Error("mount bullet error");
    }
    this.el = domEl as HTMLElement;
  }
  move(duration: number) {
    this.state = "moving";
    this.initListener();

    const animation = () => {
      if (this.state !== "moving") return;

      this.position.left -= 1.2;
      this.el.style["left"] = this.position.left + this.unit;
      this.animationId = requestAnimationFrame(animation);
    };
    animation();
  }
  pause() {
    if(this.animationId){
      cancelAnimationFrame(this.animationId)
      this.animationId = undefined
    }
  }
  initListener() {
    this.el.addEventListener("mouseenter", () => {
      this.state = "pause";
      this.pause()
    });
    this.el.addEventListener("mouseover", () => {
      this.state = "pause";
      this.pause()
    });
    this.el.addEventListener("mouseout", () => {
      this.state = "moving";
      this.move()
    });
  }
}

我想是因为当我重新触发move()时,javascript堆栈中仍然有一些requestAnimationFrame()在运行?

我怎么才能解决这个问题?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-31 18:58:30

您应该在执行暂停时取消事件侦听器的注册,或者在move()函数之外注册它们(例如,在mount()中)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69787986

复制
相关文章

相似问题

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