我尽可能地组装了您的代码,看起来您有缓冲区溢出(蓝色js堆),您需要在这里进行调查,这些是根本原因。
最初的方法是只创建一个圆圈,然后从父级动画子级,通过这种方式,您可以避免密集的内存和CPU计算。
通过单击画布添加多少个圆圈,画布信用归Martin所有。
根据Alexander的讨论,可以使用setTimeout或Timeinterval(Solution 2)
Soltion #1
App.js
import React from 'react';
import { useCircle } from './useCircle';
import './App.css';
const useAnimationFrame = callback => {
const requestRef = React.useRef();
const previousTimeRef = React.useRef();
const animate = time => {
if (previousTimeRef.current != undefined) {
const deltaTime = time - previousTimeRef.current;
callback(deltaTime)
}
previousTimeRef.current = time;
requestRef.current = requestAnimationFrame(animate);
}
React.useEffect(() => {
requestRef.current = requestAnimationFrame(animate);
return () => cancelAnimationFrame(requestRef.current);
}, []);
}
function App() {
const [count, setCount] = React.useState(0)
const [coordinates, setCoordinates, canvasRef, canvasWidth, canvasHeight, counts] = useCircle();
const speedX = 1
const speedY = 1
const requestRef = React.useRef();
const previousTimeRef = React.useRef();
const handleCanvasClick = (event) => {
const currentCoord = { x: event.clientX, y: event.clientY ,directionX:"right",directionY:"down"};
setCoordinates([...coordinates, currentCoord]);
};
const move = () => {
let q = [...coordinates]
q.map(coordinate => { return { x: coordinate.x + 10, y: coordinate.y + 10 } })
setCoordinates(q)
}
const handleClearCanvas = (event) => {
setCoordinates([]);
};
const animate = time => {
setCount(time)
if (previousTimeRef.current != undefined) {
const deltaTime = time - previousTimeRef.current;
setCoordinates(coordinates => coordinates.map((coordinate)=> {
let x=coordinate.x;
let y=coordinate.y;
let directionX=coordinate.directionX
let directionY=coordinate.directionY
if (x < 0) directionX = "right"
if (x > canvasWidth) directionX = "left"
if (y < 0) directionY = "down"
if (y > canvasHeight) directionY = "up"
if (directionX === "left") x -= speedX
else x += speedX
if (directionY === "up") y -= speedY
else y += speedY
return { x:x,y:y,directionX:directionX,directionY:directionX}
}))
}
previousTimeRef.current = time;
requestRef.current = requestAnimationFrame(animate);
}
React.useEffect(() => {
requestRef.current = requestAnimationFrame(animate);
return () => cancelAnimationFrame(requestRef.current);
}, []);
return (
<main className="App-main" >
<div>{Math.round(count)}</div>
<canvas
className="App-canvas"
ref={canvasRef}
width={canvasWidth}
height={canvasHeight}
onClick={handleCanvasClick}
/>
<div className="button" >
<button onClick={handleClearCanvas} > CLEAR </button>
</div>
</main>
);
};
export default App;
userCircle.js
import React, { useState, useEffect, useRef } from 'react';
var circle = new Path2D();
circle.arc(100, 100, 50, 0, 2 * Math.PI);
const SCALE = 1;
const OFFSET = 80;
export const canvasWidth = window.innerWidth * .5;
export const canvasHeight = window.innerHeight * .5;
export const counts=0;
export function draw(ctx, location) {
console.log("attempting to draw")
ctx.fillStyle = 'red';
ctx.shadowColor = 'blue';
ctx.shadowBlur = 15;
ctx.save();
ctx.scale(SCALE, SCALE);
ctx.translate(location.x / SCALE - OFFSET, location.y / SCALE - OFFSET);
ctx.rotate(225 * Math.PI / 180);
ctx.fill(circle);
ctx.restore();
};
export function useCircle() {
const canvasRef = useRef(null);
const [coordinates, setCoordinates] = useState([]);
useEffect(() => {
const canvasObj = canvasRef.current;
const ctx = canvasObj.getContext('2d');
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
coordinates.forEach((coordinate) => {
draw(ctx, coordinate)
}
);
});
return [coordinates, setCoordinates, canvasRef, canvasWidth, canvasHeight,counts];
}
方案#2 使用间隔
IntervalExample.js (应用程序) 9个样本圆形
import React, { useState, useEffect } from 'react';
import Circlo from './Circlo'
const IntervalExample = () => {
const [seconds, setSeconds] = useState(0);
const [circules, setCircules] = useState([]);
let arr =[
{x:19,y:15, r:3,directionX:'left',directionY:'down'},
{x:30,y:10,r:4,directionX:'left',directionY:'down'},
{x:35,y:20,r:5,directionX:'left',directionY:'down'},
{x:0,y:15, r:3,directionX:'left',directionY:'down'},
{x:10,y:30,r:4,directionX:'left',directionY:'down'},
{x:20,y:50,r:5,directionX:'left',directionY:'down'},
{x:70,y:70, r:3,directionX:'left',directionY:'down'},
{x:80,y:80,r:4,directionX:'left',directionY:'down'},
{x:10,y:20,r:5,directionX:'left',directionY:'down'},
]
const reno =(arr)=>{
const table = Array.isArray(arr) && arr.map(item => <Circlo x={item.x} y={item.y} r={item.r} />);
return(table)
}
const speedX = 0.1
const speedY = o.1
const move = (canvasHeight,canvasWidth) => {
let xarr= arr.map(((coordinate)=> {
let x=coordinate.x;
let y=coordinate.y;
let directionX=coordinate.directionX
let directionY=coordinate.directionY
let r=coordinate.r
if (x < 0) directionX = "right"
if (x > canvasWidth) directionX = "left"
if (y < 0) directionY = "down"
if (y > canvasHeight) directionY = "up"
if (directionX === "left") x -= speedX
else x += speedX
if (directionY === "up") y -= speedY
else y += speedY
return { x:x,y:y,directionX:directionX,directionY:directionY,r:r}
}))
return xarr;
}
useEffect(() => {
const interval = setInterval(() => {
arr =move(100,100)
setCircules( arr)
setSeconds(seconds => seconds + 1);
}, 10);
return () => clearInterval(interval);
}, []);
return (
<div className="App">
<p>
{seconds} seconds have elapsed since mounting.
</p>
<svg viewBox="0 0 100 100">
{ reno(circules)}
</svg>
</div>
);
};
export default IntervalExample;
Circlo.js
import React from 'react';
export default function Circlo(props) {
return (
<circle cx={props.x} cy={props.y} r={props.r} fill="red" />
)
}
![enter image description here](https://istack.dev59.com/xhzcE.webp)
![enter image description here](https://istack.dev59.com/7fSdI.webp)
![enter image description here](https://istack.dev59.com/aEIL4.webp)
let y = canvas.height;
的大部分代码似乎都可能返回相同的结果。但无论如何,如果您还没有对代码进行过性能分析,那么这些讨论大多是无意义的。浏览器中的开发工具可以帮助您,在任何代码片段消耗的时间方面告诉您准确的数据。既然可以测量,就没有必要猜测! - enhzflepanimate
方法)进行动画处理呢?对于你的特定任务而言,这种方式比canvas更具性能优势。 - Alex