我基本上是试图让几个球排在一起,让球在 Y 轴上上下移动,但每个球开始时都有一点延迟,所以最终它应该产生无限的波效果
我首先尝试增加速度,虽然它创造了我想要的效果,但它暂时做到了,因为它不断增加动画的动态。
我认为只有当我能让每个球在不同的时间开始动画时,它才能解决这个问题。 对此有什么建议吗?
查看我的代码笔上的动画 https://codepen.io/jinnn0/pen/zgRrKm?editors=0010
const canvas = document.querySelector('canvas')
const c = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
function Circle(x, y, radius, color, velocity, amplitude) {
this.x = x
this.y = y
this.color = color
this.radius = radius
this.radian = 1
this.velocity = velocity
this.amplitude = amplitude
this.acceleration = 0.001
this.count = 0
this.draw = function(){
c.beginPath()
c.fillStyle = color
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2)
c.lineWidth = 3
c.stroke()
c.fill()
c.closePath()
}
this.update = function(){
this.draw()
this.radian += this.velocity
this.y = y + Math.sin(this.radian) * this.amplitude
this.count ++
}
}
let circleArr;
function init(){
circleArr = []
let radius = 25
let x = radius
let y = 200
let color = "rgba(140, 140, 140)"
let velocity = 0.05
let amplitude = 100
for( let i =0; i < 10; i++ ) {
circleArr.push(new Circle(x, y, radius, color, velocity,
amplitude))
x += radius * 2
// velocity += 0.001
}
}
function animate(){
c.clearRect(0, 0, canvas.width, canvas.height)
for(let i = 0; i < circleArr.length; i++) {
circleArr[i].update()
}
requestAnimationFrame(animate)
}
init()
animate()
Date.now()
存储开始时间戳,然后将自动画开始以来的十多次时间与每个球的指定延迟(以毫秒为单位(进行比较(请注意,我还将起始弧度更改为 0,以便当动画开始时球不会"跳"到底部,以及开始 y,以便我们在片段预览中实际看到球(:
const canvas = document.querySelector('canvas')
const c = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
const start = Date.now();
const delay = 2000;
function Circle(x, y, radius, color, velocity, amplitude, delay) {
this.x = x
this.y = y
this.color = color
this.radius = radius
this.radian = 0
this.velocity = velocity
this.amplitude = amplitude
this.acceleration = 0.001
this.count = 0
this.delay = delay
this.draw = function(){
c.beginPath()
c.fillStyle = color
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2)
c.lineWidth = 3
c.stroke()
c.fill()
c.closePath()
}
this.update = function(ellapsed){
this.draw()
if (ellapsed > this.delay) {
this.radian += this.velocity
this.y = y + Math.sin(this.radian) * this.amplitude
this.count ++
}
}
}
let circleArr;
function init(){
circleArr = []
let radius = 25
let x = radius
let y = 130
let color = "rgba(140, 140, 140)"
let velocity = 0.05
let amplitude = 100
let delay = 0
for( let i =0; i < 10; i++ ) {
circleArr.push(new Circle(x, y, radius, color, velocity,
amplitude, delay))
x += radius * 2
delay += 100
// velocity += 0.001
}
}
function animate(){
// ellapsed time from the start (you should initialize start
// closer to the animation start if there is a noticeably long
// operation in between)
const ellapsed = Date.now() - start;
c.clearRect(0, 0, canvas.width, canvas.height)
for(let i = 0; i < circleArr.length; i++) {
// ellapsed is passed to the ball's update method
circleArr[i].update(ellapsed)
}
requestAnimationFrame(animate)
}
init()
animate()
<html>
<body>
<canvas />
</body>
</html>
或者,您可以在我们第一次调用更新时为每个球初始化一个开始变量(这样并非所有球都依赖于全局开始,这可能对它们没有意义(
编辑: 重新阅读您的问题后,我注意到您可能会寻找另一种不涉及延迟的解决方案。实际上更容易:只需给每个球一个不同的(递增的(起始弧度。
下面我用弧度参数替换了额外的延迟参数:
function Circle(x, y, radius, color, velocity, amplitude, radian) {
this.x = x
this.y = y
this.color = color
this.radius = radius
this.velocity = velocity
this.amplitude = amplitude
this.acceleration = 0.001
this.count = 0
this.radian = radian
this.draw = function(){
c.beginPath()
c.fillStyle = color
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2)
c.lineWidth = 3
c.stroke()
c.fill()
c.closePath()
}
this.update = function(){
this.draw()
this.radian += this.velocity
this.y = y + Math.sin(this.radian) * this.amplitude
this.count ++
}
}
然后,我没有为每个球输入经过的时间,而是用递增的弧度初始化它们:
function init(){
circleArr = []
let radius = 25
let x = radius
let radian = 0
let y = 130
let color = "rgba(140, 140, 140)"
let velocity = 0.05
let amplitude = 100
let delay = 0
for( let i =0; i < 10; i++ ) {
circleArr.push(
new Circle(
x, y,
radius, color,
velocity, amplitude, radian
)
)
x += radius * 2
radian += Math.PI / 10
// velocity += 0.001
}
}
const canvas = document.querySelector('canvas')
const c = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
function Circle(x, y, radius, color, velocity, amplitude, startRadian) {
this.x = x
this.y = y
this.color = color
this.radius = radius
this.velocity = velocity
this.amplitude = amplitude
this.acceleration = 0.001
this.count = 0
this.radian = startRadian
this.draw = function(){
c.beginPath()
c.fillStyle = color
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2)
c.lineWidth = 3
c.stroke()
c.fill()
c.closePath()
}
this.update = function(){
this.draw()
this.radian += this.velocity
this.y = y + Math.sin(this.radian) * this.amplitude
this.count ++
}
}
let circleArr;
function init(){
circleArr = []
let radius = 25
let x = radius
let radian = 0
let y = 130
let color = "rgba(140, 140, 140)"
let velocity = 0.05
let amplitude = 100
let delay = 0
for( let i =0; i < 10; i++ ) {
circleArr.push(new Circle(x, y, radius, color, velocity,
amplitude, radian))
x += radius * 2
radian += Math.PI / 10
// velocity += 0.001
}
}
function animate(){
c.clearRect(0, 0, canvas.width, canvas.height)
for(let i = 0; i < circleArr.length; i++) {
circleArr[i].update()
}
requestAnimationFrame(animate)
}
init()
animate()
<html>
<body>
<canvas/>
</body>
</html>
它的效果更好,但会改变球的起始位置。 您可以通过结合这两种技术(弧度偏移+延迟(来实现非常酷的效果。
我让你试验不同的参数。