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

我使用 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>

    );

  }

}

最终结果是组件显示画布和线条,但动画仅在其中之一中发生。其余的在初始状态下是静态的。请告诉我为什么会发生这种情况以及我可以采取哪些措施来修复它,以便所有组件都可以动画化。需要注意的是,当我刷新代码并且浏览器通过热重载刷新时,另一个组件会在每次刷新时启动动画,依此类推。



慕桂英3389331
浏览 70回答 1
1回答

慕容708150

问题是某些变量是在函数外部定义的,initCanvas因此在所有组件(line1、和)之间共享。因此,每次您调用时,它们都会被覆盖。line2ctxcanvasEleminitCanvas一个快速的解决方案是将其包装在一个类中:export class WaveCanvas {&nbsp; constructor(canvas) {&nbsp; &nbsp; this.canvasElem = canvas;&nbsp; &nbsp; this.ctx = canvas.getContext("2d");&nbsp; &nbsp; const parent = canvas.parentElement;&nbsp; &nbsp; canvas.width = parent.clientWidth;&nbsp; &nbsp; canvas.height = parent.scrollHeight;&nbsp; }&nbsp; init() {&nbsp; &nbsp; // ...&nbsp; &nbsp; this.line1 = new Line(...);&nbsp; }&nbsp; animate() {&nbsp; &nbsp; requestAnimationFrame(() => this.animate());&nbsp; &nbsp; this.ctx.clearRect(0, 0, this.canvasElem.width, this.canvasElem.height);&nbsp; &nbsp; this.line1.update();&nbsp; &nbsp; this.line2.update();&nbsp; }}然后在组件中实例化它:&nbsp; componentDidLoad() {&nbsp; &nbsp; let canvas = this.el.querySelector('canvas');&nbsp; &nbsp; const waveCanvas = new WaveCanvas(canvas);&nbsp; &nbsp; waveCanvas.init();&nbsp; &nbsp; waveCanvas.animate();&nbsp; }这样, 的每个实例都WaveCanvas将拥有自己对正确<canvas>元素的引用。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript