为了账号安全,请及时绑定邮箱和手机立即绑定

Stencil js - requestAnimationFrame 并未出现在所有组件中

Stencil js - requestAnimationFrame 并未出现在所有组件中

慕桂英3389331 2023-08-18 17:08:44
我使用 stencil.js 创建了一个简单的目录项组件。在组件中有一个画布标签,我在其上绘制了动画曲线。在 componentDidLoad 函数中,我定义了画布,对其进行初始化并调用 animate 函数。这是组件本身的代码:import { Component, Host, h, Prop, Element  } from "@stencil/core";import { Item } from "../hotb-catalog-container/data";import { initCanvas, init, animate } from "./wave.js";import axios from "axios";@Component({  tag: "hotb-catalog-item",  styleUrl: "hotb-catalog-item.scss",  shadow: false,})export class HotbCatalogItem {  @Prop() item: Item;  @Element() el: HTMLElement;  // @Event({ bubbles: true, composed: true }) itemSelect: EventEmitter<Item>;  itemSelected(event: Event) {    event.preventDefault();    //sessionStorage.setItem("item", JSON.stringify(this.item));    axios.post("/item", { item: this.item }).then(() => {      window.location.href = "http://localhost:3000/item";    });  }  componentDidLoad() {    let canvas = this.el.querySelector('canvas');    initCanvas(canvas);    init();    animate();  }  render() {    return (      <Host>        <div class="heading">          <h1>{this.item.name}</h1>          <span> מ{this.item.origin} &#183; {this.item.taste}</span>        </div>        <div class="center-part">          <div class="center-part__img"></div>          <div class="center-part__icon center-part__icon--temp">            {this.item.temp}&deg;C          </div>          <div class="center-part__icon center-part__icon--time">            {this.item.time}          </div>        </div>        <a          href="/item"          onClick={this.itemSelected.bind(this)}          class="primary-btn homepage__tea"        >          לצפיה        </a>        <canvas></canvas>      </Host>    );  }}最终结果是组件显示画布和线条,但动画仅在其中之一中发生。其余的在初始状态下是静态的。请告诉我为什么会发生这种情况以及我可以采取哪些措施来修复它,以便所有组件都可以动画化。需要注意的是,当我刷新代码并且浏览器通过热重载刷新时,另一个组件会在每次刷新时启动动画,依此类推。
查看完整描述

1 回答

?
慕容708150

TA贡献1831条经验 获得超4个赞

问题是某些变量是在函数外部定义的,initCanvas因此在所有组件(line1、和)之间共享。因此,每次您调用时,它们都会被覆盖。line2ctxcanvasEleminitCanvas


一个快速的解决方案是将其包装在一个类中:


export class WaveCanvas {

  constructor(canvas) {

    this.canvasElem = canvas;

    this.ctx = canvas.getContext("2d");

    const parent = canvas.parentElement;

    canvas.width = parent.clientWidth;

    canvas.height = parent.scrollHeight;

  }


  init() {

    // ...

    this.line1 = new Line(...);

  }


  animate() {

    requestAnimationFrame(() => this.animate());

    this.ctx.clearRect(0, 0, this.canvasElem.width, this.canvasElem.height);


    this.line1.update();

    this.line2.update();

  }

}

然后在组件中实例化它:


  componentDidLoad() {

    let canvas = this.el.querySelector('canvas');

    const waveCanvas = new WaveCanvas(canvas);

    waveCanvas.init();

    waveCanvas.animate();

  }

这样, 的每个实例都WaveCanvas将拥有自己对正确<canvas>元素的引用。


查看完整回答
反对 回复 2023-08-18
  • 1 回答
  • 0 关注
  • 94 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信