Stencil js - some components do not utilize requestAnimationFrame

Using stencil.js, I have developed a unique catalog item component featuring an animating curved lines painted on a canvas tag within the component. In the componentDidLoad function, the canvas is defined, initialized, and the animate function is called. Here's the code snippet of the component:

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>
    );
  }
}

The imported canvas code looks like this:

let line1;
let line2;
var ctx;
var canvasElem;

function initCanvas(canvas) {
  canvasElem = canvas;
  ctx = canvas.getContext("2d");
  const parent = canvas.parentElement;
  canvas.width = parent.clientWidth;
  canvas.height = parent.scrollHeight;
}

class LineGen {
...

The catalog item component is nested inside a container component as shown below:

    let items;
    if (this.newItemsArr.length == 0) {
      items = <div class="no-items">אין משקאות שתואמים לחיפוש שלך</div>;
    } else {
      items = this.newItemsArr.map((item) => (
        <hotb-catalog-item item={item}></hotb-catalog-item>
      ));
    }
    return (
      <Host>
        {items}
      </Host>
    );

However, only one of the components animates while the others remain static in their initial state. Refreshing the code triggers animation in another component with each refresh cycle. Please advise me on how to resolve this issue and ensure that all components animate properly.

Thank you for your assistance.

Answer №1

The issue at hand lies in the fact that certain variables are declared outside of the initCanvas function, leading to them being shared amongst all components (line1, line2, ctx, and canvasElem). This results in them getting overwritten every time initCanvas is called.

A simple solution would involve encapsulating everything within a class:

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();
  }
}

Then, you can instantiate it within the component like so:

  componentDidLoad() {
    let canvas = this.el.querySelector('canvas');
    const waveCanvas = new WaveCanvas(canvas);
    waveCanvas.init();
    waveCanvas.animate();
  }

This approach ensures that each instance of WaveCanvas maintains its own reference to the appropriate <canvas> element.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Persistent NW.js Local Storage Cache Remains Present even After Deleting Application

I have been encountering an issue in my NW.js app where I store data in the Local Storage. Even after deleting the app and cleaning up cache information, the Local Storage data seems to persist. When I reinstall the app, the stored data reappears as if it ...

Tips for preserving the state of the Material-UI AutoComplete during component re-renders?

Currently, I am utilizing the Material-UI v4 AutoComplete component along with the renderOption prop in order to display a checkbox item option. The issue arises when the onChange event occurs and updates a hook in the parent component causing a re-rende ...

Tips for retrieving the most recent number dynamically in a separate component without needing to refresh the page

Utilizing both the Helloworld and New components, we aim to store a value in localStorage using the former and display it using the latter. Despite attempts to retrieve this data via computed properties, the need for manual refreshing persists. To explore ...

How can I retrieve the data property within the setup function in Vue 3?

Trying to access a data property inside setup() in Vue 3 is resulting in the following error: TypeError: Cannot read property '$localStorage' of undefined data() data() { return { $localStorage: {}, } setup setup() { this.$loca ...

The function getComputedStyle(elem).getPropertyValue('fontSize') returns incorrect values when the font size of the element is specified in em units

My current issue involves trying to obtain the font size of an element in the following manner: getComputedStyle(MyTargetElement , "").getPropertyValue('font-size') The result is coming back as 16px, when it should actually be 14px. W ...

"Concealing a div in one CSS file while revealing it in a separate CSS file: a step-by

When my basic front end auth login react component page loads for the first time, I have an issue where a form appears on the login side of things that I only want to show once the app side has rendered upon successful login. Once logged in, it should ren ...

Modify div content based on user selection

I have a question about updating the content of a div based on certain conditions in my code. Here is what I'm trying to achieve: <div class="form-control" ns-show="runningImport" disabled="disabled"> {{input[row.header_safe]}}{{select[row. ...

Transferring Data to EJS Template

I have been facing a challenge in passing a value from a POST route to an EJS file for display. Despite trying various methods like redirecting, sending, and rendering the results, the data won't make its way to the EJS file. Below is the POST route ...

Attempting to implement CSS styles tailored specifically for a webpage that is dynamically loaded using AJAX

I'm experimenting with loading CSS for AJAX pages so that the styles are contained within each individual page instead of one large CSS file. My current approach is something like the following: $("#content").load(pageid+".html #content > *", func ...

Creating a blueprint for my AJAX setup to effectively incorporate a callback function

I'm currently working with AJAX to fetch timezone information in a function, but I need it to return the result. I've come to realize that AJAX is asynchronous, so I require a callback function. Although I have seen examples, I am struggling to u ...

Effortless jQuery Parallax

Seeking assistance with debugging this jQuery code that manipulates the top margin of an element within a container. The container has a fixed size and overflow set to hidden to create a parallax effect. The parallax effect is functioning properly, but it ...

Encountering a problem with AngularJS when attempting to access an array and display an alert message

While working with Angular, I encountered an issue in trying to access content stored within an array. Upon reviewing the code, console.log(JSON.stringify($scope.lineItems)) was returning [[]]. However, when inspecting or setting a breakpoint on this line ...

Configuring the port number of the socketio connection in Heroku

I attempted to create a chat application using JavaScript and npm. After completing it to some extent, I deployed it to Heroku and encountered the error net :: ERR_CONNECTION_REFUSED in Chrome's developer tools. I suspect that Socket.io, Express, and ...

Exploring Objects with the Prototype Chain in JavaScript

When exploring an object using a tree structure in the browser console, you can inspect it like this: console.log(document); You can navigate through the object, including its prototype and subsequent prototypes. I attempted to replicate this feature but ...

Insert a hyperlink button using InnerHtml

I am facing an issue with displaying a list item that contains a tab and a link button: <li runat="server" id="liActivityInvoices"><a href="#tabActivityInvoices">Invoices</a><asp:LinkButton runat="server" ID="btnLoadInvoice" OnClick=" ...

Ways to shorten the anchor tag when there are more than two tags

I currently have the following code implemented on my webpage: var menuBreadcrumb = document.getElementById('menu-breadcrumb'); var counta = $("#menu-breadcrumb a").length; //alert(counta); if (counta >= 2) { let mbcElement = '&l ...

What is the method for a JavaScript program to determine if a global property name has been defined according to the ECMA-262 standard

Imagine creating a function called checkIfEcmaGlobal which would return true for recognized names of ECMA-262 globals. $ node > checkIfEcmaGlobal('Array') true > checkIfEcmaGlobal('process') false What approach could be taken to ...

The React Draft WYSIWYG editor's value is triggering a content security policy problem due to the presence of inline styles

What steps can be taken to resolve the content-security-policy problem stemming from inline styles in a react-draft-wysiwyg editor after deployment? The styles are not being applied, leading to this issue. How can it be rectified? ...

Clicking on an object will trigger the threejs to traverse through

I need to implement a wireframe for an object when a button is clicked. I am using the traverse function to achieve this, and it works perfectly fine in the OBJMTLLoader. However, when I try to use it in a separate function as shown below and then click th ...

Struggling with UI-Grid's single filter feature when dealing with intricate data structures?

I'm currently working with UI-Grid and facing a challenge while applying a filter to some complex data using their single filter example. Initially, everything runs smoothly when I use simple selectors. However, as soon as I attempt to delve one level ...