Summary of canvas mouse tracking animation ideas
effect
Source code
html
Click to view the code<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Mouse tracking animation</title> <style> canvas { margin: 50px auto; display: block; box-shadow: 0 0 10px rgb(0 0 0 / 50%); } </style> </head> <body onload="draw()"> <canvas width="800" height="500"></canvas> <script src="./js/Mouse tracking animation.js"></script> <script> let offsetX = 0 let offsetY = 0 let targetArr = [] function draw() { const canvas = document.querySelector('canvas') const ctx = canvas.getContext('2d') canvas.onmousemove = function (e) { offsetX = e.offsetX offsetY = e.offsetY } targetArr = prepareLine(canvas.width / 2, canvas.height / 2) startAnimation(ctx, canvas.width, canvas.height) } function prepareLine(startX, startY) { const res = [] offsetX = startX offsetY = startY for (let i = 0; i < 100; i++) { res.push(new Line(startX, startY)) } return res } function startAnimation(ctx, width, height) { requestAnimationFrame(() => startAnimation(ctx, width, height)) // Transparency controls the length of the long tail effect ctx.fillStyle = 'rgba(0,0,0,0.05)' ctx.fillRect(0, 0, width, height) targetArr.forEach((obj) => { obj.draw(ctx, offsetX, offsetY) }) } </script> </body> </html>
js
Mouse tracking animation js
Click to view the codeclass Line { constructor(startX, startY) { this.startX = startX this.startY = startY // Random angle of line this.randomAngle = this._getRandomAngle() // Control range this.maxLineLength = 150 // Control thickness this.lineWidth = 4 // Frequency of angle change (speed) this.angleRate = 0.02 // From maxLineLength, control range this.lineLength = this._getRandomLength() this.lineColor = this._getRandomColor() } setMaxLineLength(length) { this.maxLineLength = length } setLineWidth(width) { this.lineWidth = width } draw(ctx, offsetX, offsetY) { ctx.save() const { lineW, lineH } = this._computeLocationData() ctx.lineWidth = this.lineWidth ctx.strokeStyle = this.lineColor ctx.beginPath() // Location of the previous point ctx.moveTo(this.startX, this.startY) // x coordinate from mouse position this.startX = offsetX + lineW // y coordinate from mouse position this.startY = offsetY + lineH // Draw from the position of the previous point to the position of the next point (this.angleRate degree difference in angle) ctx.lineTo(this.startX, this.startY) ctx.stroke() ctx.closePath() ctx.restore() } _computeLocationData() { this.randomAngle += this.angleRate return { lineW: Math.cos(this.randomAngle) * this.lineLength, // Random length of line (x coordinate) lineH: Math.sin(this.randomAngle) * this.lineLength // Random height of the line (y coordinate) } } _getRandomAngle() { return Math.random() * Math.PI * 2 } _getRandomLength() { return Math.random() * this.maxLineLength } _getRandomColor() { const s = '0123456789ABCDEF' let c = '#' for (let i = 0; i < 6; i++) { c += s[Math.ceil(Math.random() * 15)] } return c } }
Train of thought combing
- All lines have the same representation and can be abstracted into a Line class
- The length and color of each line are constant, and each line has a long tail effect during movement
- The movement of the line depends on the position of the mouse
- When the mouse moves, each line will follow
Main process
- The starting point of the initial line is in the middle of the canvas, and the length and color of each line are calculated randomly
- When preparing lines, draw lines from the center of the canvas outward according to the randomly calculated angle and line length (refer to step 4 for calculation method)
- After the animation starts, draw a new line starting from the end of the previous line
- Location of new line
- Mouse position dependent
- The length from the mouse position depends on the previously randomly calculated line length. It should be: mouse position + line length
- Because each line will have the effect of rotation, all the positions should have a certain angle change, otherwise the effect of line rotation cannot be realized
- Imagine a circle with radius r in a coordinate system
- Pull A line outward from the center of the circle and intersect the circle at point A (x, y) at an angle of θ
- From the trigonometric function, we can know that x = r * cos θ, y = r * sin θ
- angle θ When changes occur, the corresponding x and y will also change accordingly
- When the angle changes, the position of the new line should be
- X = mouse position x + line length * cos θ
- Y = mouse position Y + line length * sin θ
- Loop through step 3 and step 4 during animation
Long tail effect
The canvas code CTX. Is cleared clearRect(0, 0, canvas.width, canvas.heigth)
Change to the following code and let it repeatedly overwrite the previous style to achieve the long tail effect
ctx.fillStyle = 'rgba(0,0,0,0.05)' ctx.fillRect(0, 0, canvas.width, canvas.heigth)
reference resources
https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Basic_animations
https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Advanced_animations