我正在尝试将粒子发射器切换为打开或关闭。 我有一些Reactjs代码,用canvas元素创建雨/雪粒子。 我想出的正确杀死动画的每个概念仍会导致内存泄漏(在这种情况下,我认为它只是在旧的上投影一个新的画布并且仍然在内存中运行原始动画)。 这是Codepen.
以下是页面代码:
class CanvasComponent extends React.Component {
componentDidMount() {
this.BtnOnOff();
}
constructor() {
super();
this.toggleState = this.toggleState.bind(this);
this.state = {
isActive : false
}
}
toggleState() {
this.setState({isActive:!this.state.isActive});
this.BtnOnOff();
//console.log(this.state.isActive);
}
snowMaker() {
// Ref canvas & get context
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Weather Types/////////////
var liteSnow = 13; //code 13 for snow light fluries.
var snow = 16; //code 13 for snow fluries.
var hevySnow = 41; //code 41 for Heavy snow.
var hevySnow2 = 43; //code 43 for Heavy snow.
var DRain = 9; //code 9 for drizzel
var HRain = 3; //code 3/4 for Thunderstorms/severe thunderstorms
var Code = 43; // Code will take in the current weather code.
// Resize canvas
let width = canvas.width = window.innerWidth;
let height = canvas.height = window.innerHeight;
// Variables
if (Code === 13) { /// Make it snow (light fluries)
var drops = [];
var dropColour = "rgba(255,255,255,1)";
var dropLengths = [3, 3, 3, 3, 3, 3, 3];
var dropSkews = [-2, -1, 0, 1, 2];
var maxDrops = 100;
var velocity = 8;
var flutter = 5;
}
else if (Code === 16){ /// Make it snow (fluries)
var drops = [];
var dropColour = "rgba(255,255,255,1)";
var dropLengths = [3, 3, 3, 3, 3, 3, 3];
var dropSkews = [-2, -1, 0, 1, 2];
var maxDrops = 500;
var velocity = 7;
var flutter = 5;
}
else if (Code === 41||Code === 43){ /// Make it Heavy snow
var drops = [];
var dropColour = "rgba(255,255,255,1)";
var dropLengths = [3, 2, 3, 2, 3, 2, 3];
var dropSkews = [-3, -1, 0, 1, 3];
var maxDrops = 800;
var velocity = .5;
var flutter = 8;
}
else if (Code === 9){ /// Make it rain
var drops = [];
var dropColour = "rgba(255,255,255,0.41)";
var dropLengths = [4, 5, 3, 6, 2, 3, 3];
var dropSkews = [0, 0.2, 0, 0, 0.1];
var maxDrops = 100;
var velocity =1;
var flutter = 1;
}
else if (Code === 3||Code === 4){ /// Make it ThunderStorms
var drops = [];
var dropColour = "rgba(255,255,255,0.5)";
var dropLengths = [10, 8, 8, 8, 7, 15, 9];
var dropSkews = [-0.2, -0.3, -0.2, -0.2, 0.1];
var maxDrops = 1000;
var velocity = .8;
var flutter = .1;
}
// Raindrop class
class Droplet {
constructor(x, y, length, skew) {
this.x = x;
this.y = y;
this.length = length;
this.skew = skew;
}
// Move method
move() {
// Increment x & y
this.y += this.length / velocity;
this.x += this.skew / flutter;
// Set limits
if (this.y > height) {
this.y = 0;
}
if (this.x > width || this.x < 0) {
this.y = 0;
this.x = Math.floor(Math.random() * width);
}
}
// Draw method
draw(ctx) {
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.x + this.skew, this.y + this.length);
ctx.strokeStyle = dropColour;
ctx.stroke();
}
}
// Create drops and push to array
for (let i = 0; i < maxDrops; i++) {
let instance = new Droplet(
Math.floor(Math.random() * width),
Math.floor(Math.random() * height),
randVal(dropLengths),
randVal(dropSkews)
);
drops.push(instance);
}
// Animation loop
function loop() {
// Clear Canvas
ctx.clearRect(0, 0, width, height);
// Draw / Move drops
for (let drop of drops) {
drop.move();
drop.draw(ctx);
}
// Animation Frame
requestAnimationFrame(loop)
}
// Begin animation
loop();
// Resize canvas - responsive
window.addEventListener('resize', resize);
function resize() {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
}
// Function for random array values
function randVal(array) {
return array[Math.floor(Math.random() * array.length)];
}
}////////End of update canvas
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
snowKiller() {
// Ref canvas & get context
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
var Code = 13;
// Resize canvas
let width = canvas.width = window.innerWidth;
let height = canvas.height = window.innerHeight;
// Variables
if (Code === 13) { /// Make it snow (light fluries)
var drops = [];
var dropColour = "";
var dropLengths = [0];
var dropSkews = [0];
var maxDrops = 0;
var velocity = 0;
var flutter = 0;
}
// Raindrop class
class Droplet {
constructor(x, y, length, skew) {
this.x = x;
this.y = y;
this.length = length;
this.skew = skew;
}
// Move method
move() {
// Increment x & y
this.y += this.length / velocity;
this.x += this.skew / flutter;
// Set limits
if (this.y > height) {
this.y = 0;
}
if (this.x > width || this.x < 0) {
this.y = 0;
this.x = Math.floor(Math.random() * width);
}
}
// Draw method
draw(ctx) {
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.x + this.skew, this.y + this.length);
ctx.strokeStyle = dropColour;
ctx.stroke();
}
}
// Create drops and push to array
for (let i = 0; i < maxDrops; i++) {
let instance = new Droplet(
Math.floor(Math.random() * width),
Math.floor(Math.random() * height),
randVal(dropLengths),
randVal(dropSkews)
);
drops.push(instance);
}
// Animation loop
function loop() {
// Clear Canvas
ctx.clearRect(0, 0, width, height);
// Draw / Move drops
for (let drop of drops) {
drop.move();
drop.draw(ctx);
}
// Animation Frame
requestAnimationFrame(loop)
}
// Begin animation
loop();
// Resize canvas - responsive
window.addEventListener('resize', resize);
function resize() {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
}
// Function for random array values
function randVal(array) {
return array[Math.floor(Math.random() * array.length)];
}
}////////End of update canvas
BtnOnOff(){
const OnOff =$('#Button').attr('class');
if(OnOff=== "active"){
// alert('this is on!')
this.snowMaker();
}else {
this.snowKiller();
// alert('this is off!');
}
console.log(OnOff);
}
render() {
return (
<div>
<button id="Button" className={this.state.isActive ? 'inactive' : 'active'} onClick ={this.toggleState}>{this.state.isActive ? 'STOP' : 'START'}</button>
<canvas id="canvas"/>
</div>
);
}
}
ReactDOM.render(<CanvasComponent/>, document.getElementById('app'));
理想情况下解决方案就像清除requestAnimationFrame,但我似乎无法弄明白。 帮助将非常渺茫。 感谢
答案 0 :(得分:0)
(Code tl; dr)您始终可以使用requestAnimationFrame()
返回的请求ID,如下所示:
var reqID;
function loop() {
// rain
reqID = requestAnimationFrame(loop);
}
// start loop same way
reqID = requestAnimationFrame(loop);
然后当你想要阻止它时:
cancelAnimationFrame(reqID);
使用空“reqID
”调用它是安全的。