Javascript 并非所有组件中都出现Stencil js-requestAnimationFrame
我使用stencil.js创建了一个简单的目录项组件。在组件中有一个画布标签,我在上面画了动画曲线。 在componentDidLoad函数中,我定义画布,初始化它并调用animate函数。这是组件本身的代码:Javascript 并非所有组件中都出现Stencil js-requestAnimationFrame,javascript,canvas,components,requestanimationframe,stenciljs,Javascript,Canvas,Components,Requestanimationframe,Stenciljs,我使用stencil.js创建了一个简单的目录项组件。在组件中有一个画布标签,我在上面画了动画曲线。 在componentDidLoad函数中,我定义画布,初始化它并调用animate函数。这是组件本身的代码: import { Component, Host, h, Prop, Element } from "@stencil/core"; import { Item } from "../hotb-catalog-container/data"; i
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} · {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}°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>
);
}
}
从“@stencil/core”导入{Component,Host,h,Prop,Element}”;
从“./hotb目录容器/数据”导入{Item};
从“/wave.js”导入{initCanvas,init,animate};
从“axios”导入axios;
@组成部分({
标签:“hotb目录项”,
styleUrl:“hotb目录项.scss”,
影子:错,
})
导出类HotbCatalogItem{
@Prop()项目:项目;
@Element()el:HTMLElement;
//@Event({bubbles:true,composited:true})itemSelect:EventEmitter;
已选择项(事件:事件){
event.preventDefault();
//setItem(“item”,JSON.stringify(this.item));
post(“/item”,{item:this.item})。然后(()=>{
window.location.href=”http://localhost:3000/item";
});
}
componentDidLoad(){
让canvas=this.el.querySelector('canvas');
初始画布(画布);
init();
制作动画();
}
render(){
返回(
{this.item.name}
{this.item.origin}&{this.item.taste}
{this.item.temp}°;C
{this.item.time}
);
}
}
如您所见,我导入了画布代码,如下所示:
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 {
constructor(x, y, directionY, cpX, directionCPX, cpY, directionCPY, size, color) {
this.x = x;
this.y = y;
this.directionY = directionY;
this.cpX = cpX;
this.directionCPX = directionCPX;
this.cpY = cpY;
this.directionCPY = directionCPY;
this.size = size;
this.color = color;
}
draw() {
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.quadraticCurveTo(this.cpX, this.cpY, 400, this.y);
ctx.strokeStyle = this.color;
ctx.lineWidth = this.size;
ctx.stroke();
}
update() {
if (this.y > 490 || this.y < 400) {
this.directionY = -this.directionY;
}
if (this.color === '#E07D31') {
if (this.cpX > 390 || this.cpX < 10) {
this.directionCPX = -this.directionCPX;
}
if (this.cpY > 590 || this.cpY < 150) {
this.directionCPY = -this.directionCPY;
}
} else if (this.color === '#49E048') {
if (this.cpX > 390 || this.cpX < 10) {
this.directionCPX = -this.directionCPX;
}
if (this.cpY > 560 || this.cpY < 240) {
this.directionCPY = -this.directionCPY;
}
}
//this.y += this.directionY;
this.cpX += this.directionCPX;
this.cpY += this.directionCPY;
this.draw();
}
}
class Line extends LineGen {
constructor(x, y, directionY, cpX, directionCPX, cpY, directionCPY, size, color) {
super(x, y, directionY, cpX, directionCPX, cpY, directionCPY, size, color);
}
}
function init() {
let x = 0;
let y = 400;
let y2 = 380;
let directionY = -.2;
let cpX = 100;
let cpX2 = 100;
let directionCPX = .15;
let cpY = 300;
let cpY2 = 300;
let directionCPY = .15;
let directionCPY2 = .178125;
let size = 2;
let color = '#E07D31';
let color2 = '#49E048';
line1 = new Line(x, y, directionY, cpX, directionCPX, cpY, directionCPY2, size, color);
line2 = new Line(x, y2, directionY, cpX, directionCPX, cpY, directionCPY, size, color2);
}
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, canvasElem.width, canvasElem.height);
line1.update();
line2.update();
}
export { initCanvas, init, animate };
let line1;
让线2;
var-ctx;
var canvasElem;
函数初始化画布(画布){
画布=画布;
ctx=canvas.getContext(“2d”);
const parent=canvas.parentElement;
canvas.width=parent.clientWidth;
canvas.height=parent.scrollHeight;
}
类LineGen{
构造函数(x,y,directionY,cpX,directionCPX,cpY,directionCPY,size,color){
这个.x=x;
这个。y=y;
this.directionY=directionY;
这个.cpX=cpX;
this.directionCPX=directionCPX;
this.cpY=cpY;
this.directionCPY=directionCPY;
这个。大小=大小;
这个颜色=颜色;
}
画(){
ctx.beginPath();
ctx.moveTo(this.x,this.y);
ctx.quadraticCurveTo(this.cpX,this.cpY,400,this.y);
ctx.strokeStyle=this.color;
ctx.lineWidth=这个.size;
ctx.stroke();
}
更新(){
如果(this.y>490 | | this.y<400){
this.directionY=-this.directionY;
}
如果(this.color=='#E07D31'){
如果(this.cpX>390 | | this.cpX<10){
this.directionCPX=-this.directionCPX;
}
如果(this.cpY>590 | | this.cpY<150){
this.directionCPY=-this.directionCPY;
}
}else if(this.color=='#49E048'){
如果(this.cpX>390 | | this.cpX<10){
this.directionCPX=-this.directionCPX;
}
如果(this.cpY>560 | | this.cpY<240){
this.directionCPY=-this.directionCPY;
}
}
//this.y+=this.directionY;
this.cpX+=this.directionCPX;
this.cpY+=this.directionCPY;
这个.draw();
}
}
类行扩展LineGen{
构造函数(x,y,directionY,cpX,directionCPX,cpY,directionCPY,size,color){
super(x,y,directionY,cpX,directionCPX,cpY,directionCPY,size,color);
}
}
函数init(){
设x=0;
设y=400;
设y2=380;
设方向y=-.2;
设cpX=100;
设cpX2=100;
设方向Cpx=0.15;
设cpY=300;
设cpY2=300;
设方向cpy=0.15;
设方向cpy2=0.178125;
设尺寸=2;
设颜色='#E07D31';
设color2='#49E048';
line1=新行(x,y,方向y,cpX,方向cpX,cpY,方向CPY2,大小,颜色);
line2=新行(x,y2,方向Y,cpX,方向cpX,cpY,方向cpY,大小,颜色2);
}
函数animate(){
请求动画帧(动画);
ctx.clearRect(0,0,画布宽度,画布高度);
line1.update();
line2.update();
}
导出{initCanvas,init,animate};
现在,目录项组件位于容器组件内部,如下所示:
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>
);
let项目;
if(this.newItemsArr.length==0){
项目=项目;
}否则{
items=this.newItemsArr.map((项)=>(
));
}
返回(
{items}
);
最终结果是组件显示画布和线条,但动画仅在其中一个画布和线条中出现。其余的在初始状态下是静态的。请告诉我为什么会发生这种情况,以及我能做些什么来修复它,以便所有的组件都将动画化。需要注意的是,当我刷新代码并且浏览器通过热重新加载进行刷新时,另一个组件会在每次刷新时启动动画等等
谢谢您的帮助。问题在于一些变量是在
initCanvas
函数之外定义的,因此在所有组件之间共享(line1
、line2
、ctx
和canvasElem
)。因此,每次调用initCanvas
时,它们都会被覆盖
一个快速的解决方案是将其包装在一个类中:
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
的每个实例都将保存对正确的
元素的引用。非常感谢!!!我想补充一下你惊人的答案。我在重新讲述如何在WaveCanvas和Line这两个类中共享ctx变量时遇到了困难。我通过将WaveCanvas中的ctx变量通过构造函数传递给该行来解决这个问题<代码>this.line1=新行(this.ctx,x,y,directionY,cpX,directionCPX,cpY,directionCPY2,大小,颜色)代码>在此之前,Line类是在没有ctx变量的情况下实例化的。很乐意提供帮助。我可能自己也应该提到这一点,但我会这么做的。IMO类永远不应该访问外部变量。我只是给了你一个快速修复,因为我没有