我有下面的代码,我想知道让它在React.js中工作的最好方法。我的主要问题是,我不能理解React中的面向对象原则。用JS制作我的粒子类的许多示例是非常简单的。但怎么做才能做出React呢?如有任何帮助,我们不胜感激!
const canvas = document.getElementById('canvas1')
const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
class Particle {
constructor(x, y, size, weight) {
this.x = x
this.y = y
this.size = size
this.weight = weight
}
update() {
if (this.y > canvas.height) {
this.y = 0 - this.size
this.x = Math.random() * 60 + 200
this.weight = Math.random() * 0.5 + 1
}
this.y += this.weight
//console.log('y is inside the canvas', this.y)
}
draw() {
ctx.fillStyle = 'blue'
ctx.beginPath()
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI)
//ctx.fill()
ctx.stroke()
}
}
const particleArray = []
const numberOfBalls = 10
function createParticles() {
for (let i = 0; i < numberOfBalls; i++) {
const x = Math.random() * 60 + 200
const y = Math.random() * canvas.height
const size = Math.random() * 20 + 5
const weight = Math.random() * 0.5 + 1
particleArray.push(new Particle(x, y, size, weight))
}
}
createParticles()
// animate canvas
function animate() {
ctx.clearRect(0, 0, canvas.height, canvas.width)
for (let i = 0; i < particleArray.length; i++) {
particleArray[i].update()
particleArray[i].draw()
}
requestAnimationFrame(animate)
}
animate()
window.addEventListener('resize', (e) => {
canvas.width = window.innerWidth
canvas.height = window.innerHeight
})
<canvas id="canvas1"></canvas>
1条答案
按热度按时间whlutmcx1#
拥有类和相当数量的代码(游戏、动画等)应该不需要进行重大更改即可使用Reaction。
关键是重构您的代码,以便画布对象可以传递给您的动画/游戏代码,而不是作为Reaction无法管理的全局变量。即使您没有使用Reaction,避免使用全局变量也是一个很好的设计。
此外,
particleArray
、numberOfBalls
、createParticles
和animate
在全局范围内是松散的,但实际上,所有这些都一起工作来表示动画,并且应该分组到类、闭包、对象等中。重构动画代码以接受画布参数后,组件将呈现画布元素,将其传递到动画中并跟踪
requestAnimationFrame
,以便它可以在卸载时调用cancelAnimationFrame
。键盘和鼠标事件也由Reaction管理。您可以使用常规处理程序
onKeyDown
、onClick
、onMouseMove
等。您的游戏或动画管理器将公开函数来响应这些事件。您还需要在Reaction中处理窗口大小调整。Rerender view on browser resize with React中有代码,但我将使其适应挂钩,并使用去抖动而不是节流。
以下是对您的代码进行最小调整的快速、粗略的草图:
这是可行的,但由于前面提到的松散的全局函数和变量,设计不是很好。
从Reaction的Angular 来看,代码可以使用自定义挂钩来处理动画帧,并调整窗口大小来清理主组件。
顺便说一句,您的
clearRect
调用混淆了宽度和高度参数,因此它只能在正方形屏幕上准确地清除屏幕。为了完整,这里是一个简单的草图,它删除了动画全局变量,显示了处理事件并将逻辑移动到挂钩。分成模块时应该是干净的。