Look at the effect
Results show
github
The cause of
The next morning before the Lunar New Year holiday, I saw the picture on the design draft (below) and had the following conversation
– Me: Pass it on.
-UI: Ok, you mean GIF.
– Me: What? This is an animation, right?
– the UI: what? It’s not animation, right?
– Me: Excuse me.
So for the rest of the day, I whipped out this wave animation
To start preparing
- Think about the demand
The first thing we can think of is that the number of waves must be customizable, followed by color, speed, transparency, height, and so on. These customizable parameters should be passed in when the function is instantiated. So let’s start by customizing an interface (including what I think we’ll need later when we write it).
interface Options {
number: number
smooth: number
velocity: number
height: number
colors: Array<{ hex: string, rgba: string }>
opacity: number
border: {
show: boolean,
width: number,
color: string[]
}
position: 'top' | 'bottom' | 'left' | 'right'
}
Copy the code
For those unfamiliar with typescript, key refers to the name of an incoming variable and value to the type specification of the variable
- Design of the interface
Here’s a preview of what might happen:
- Animation requires a command start or pause
- Methods can be used to set or change parameters in real time and are reflected in the animation
- The canvas should be able to be reset when the container of the animation is scaled
Public animate, Pause, setOptions, reset
interface Core {
animate: (a)= > void
pause: (a)= > void
setOptions: (options: Object) = > void
reset: (a)= > void
}
Copy the code
Start writing animations
The preparation is almost complete, and now it’s time to write the core animation.
- I have a canvas
Basic operation, not much introduction.
<body>
<canvas id="canvas"></canvas>
</body>
Copy the code
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
canvas.width = document.body.offsetWidth
canvas.height = document.body.offsetHeight
Copy the code
- Let’s draw a pool of water
Draw a rectangle and fill it with color.
ctx.fillStyle = "rgba(255,118,87,.6)"
ctx.beginPath()
ctx.moveTo(0, canvas.height/2)
ctx.lineTo(canvas.width, canvas.height/2)
ctx.lineTo(canvas.width, canvas.height)
ctx.lineTo(0, canvas.height)
ctx.lineTo(0, canvas.height/2)
ctx.closePath()
ctx.fill()
Copy the code
- Let the water move
To make the water in the pool rise and fall periodically, it is easy to think of using the sine or cosine function to accomplish this. Increase step by 1 degree in each frame rendering, set 50 as the change value, and use the sine function to apply the change amount to the left and right vertices.
let step = 0
function loop(){
/ / empty canvas
ctx.clearRect(0.0,canvas.width,canvas.height)
ctx.clearRect(0.0,canvas.width,canvas.height)
ctx.fillStyle = "rgba(255,118,87,.6)"
step++
const angle = step * Math.PI / 180
const deltaHeight = Math.sin(angle) * 50
ctx.beginPath()
ctx.moveTo(0, canvas.height/2+deltaHeight)
ctx.lineTo(canvas.width, canvas.height/2+deltaHeight)
ctx.lineTo(canvas.width, canvas.height)
ctx.lineTo(0, canvas.height)
ctx.lineTo(0, canvas.height/2+deltaHeight)
ctx.closePath()
ctx.fill()
requestAnimationFrame(loop)
}
loop()
Copy the code
- Let the water swirl
Making the left and right vertices out of sync makes the water shake, so we can use the cosine function for the left vertex.
let step = 0
function loop() {
/ / empty canvas
ctx.clearRect(0.0, canvas.width, canvas.height)
ctx.clearRect(0.0, canvas.width, canvas.height)
ctx.fillStyle = "rgba(255,118,87,.6)"
step++
const angle = step * Math.PI / 180
const deltaHeight = Math.sin(angle) * 50
const deltaHeightRight = Math.cos(angle) * 50
ctx.beginPath()
ctx.moveTo(0, canvas.height / 2 + deltaHeight)
ctx.lineTo(canvas.width, canvas.height / 2 + deltaHeightRight)
ctx.lineTo(canvas.width, canvas.height)
ctx.lineTo(0, canvas.height)
ctx.lineTo(0, canvas.height / 2 + deltaHeight)
ctx.closePath()
ctx.fill()
requestAnimationFrame(loop)
}
loop()
Copy the code
- Making waves
Turn one side of the rectangle into a wave using a Bezier curve.
In the canvas drawing, we use bezierCurveTo(cpX1, cpY1, cpX2, cpY2, x, Y) to draw the Bezier curve. As can be seen from the above picture, the horizontal coordinate of the two control points should be set as the midpoint of the width of the rectangle. The y-coordinate follows the peak.
let step = 0
function loop() {
/ / empty canvas
ctx.clearRect(0.0, canvas.width, canvas.height)
ctx.clearRect(0.0, canvas.width, canvas.height)
ctx.fillStyle = "rgba(255,118,87,.6)"
step++
const angle = step * Math.PI / 180
const deltaHeight = Math.sin(angle) * 50
const deltaHeightRight = Math.cos(angle) * 50
ctx.beginPath()
ctx.moveTo(0, canvas.height/2+deltaHeight)
ctx.bezierCurveTo(canvas.width /2, canvas.height/2+deltaHeight- 50, canvas.width / 2, canvas.height/2+deltaHeightRight- 50, canvas.width, canvas.height/2+deltaHeightRight)
ctx.lineTo(canvas.width, canvas.height)
ctx.lineTo(0, canvas.height)
ctx.lineTo(0, canvas.height/2+deltaHeight)
ctx.closePath()
ctx.fill()
requestAnimationFrame(loop)
}
loop()
Copy the code
- Multiple wave
Write the above wave as a for loop multiple times.
let step = 0
const lines = 3
function loop() {
ctx.clearRect(0.0, canvas.width, canvas.height)
step++
for (let i = 0; i < lines; i++) {
ctx.fillStyle = 'rgba(255,118,87,.3)'
var angle = (step + i * 180 / lines) * Math.PI / 180
var deltaHeight = Math.sin(angle) * 50
var deltaHeightRight = Math.cos(angle) * 50
ctx.beginPath()
ctx.moveTo(0, canvas.height / 2 + deltaHeight)
ctx.bezierCurveTo(canvas.width / 2, canvas.height / 2 + deltaHeight - 50, canvas.width / 2, canvas.height / 2 + deltaHeightRight - 50, canvas.width, canvas.height / 2 + deltaHeightRight)
ctx.lineTo(canvas.width, canvas.height)
ctx.lineTo(0, canvas.height)
ctx.lineTo(0, canvas.height / 2 + deltaHeight)
ctx.closePath()
ctx.fill()
}
requestAnimationFrame(loop)
}
loop()
Copy the code
conclusion
The core code has been described, and the rest of the encapsulation of the Settings is not described.
If you have such a need, you can use the examples above, or you can use the ones I wrote
Last but not least, welcome star ~
github