Maison >interface Web >js tutoriel >Projet d'actualisation du frontend - Une araignée électronique
Préface : Après avoir appris JavaScript, vous pouvez utiliser JavaScript pour obtenir des effets intéressants. Cet article explique comment utiliser JavaScript uniquement pour implémenter un robot électronique sur une page Web.
Avant de commencer à apprendre à écrire une araignée Web, regardons à quoi ressemble cette araignée électronique :
Vous pouvez voir qu'il bougera avec notre souris, alors comment obtenir cet effet ? Commençons à expliquer.
<!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>Dreaming</title> <!-- External JavaScript files --> <script src=".test.js"></script> <style> /* Remove default padding and margins from body */ body { margin: 0px; padding: 0px; position: fixed; /* Set the background color of webpage to black */ background: rgb(0, 0, 0); } </style> </head> <body> <!-- Create a canvas for drawing --> <canvas id="canvas"></canvas> </body> </html>
Comme vous pouvez le constater, notre code HTML est très simple, commençons à travailler dessus !
Avant de commencer à écrire du code JavaScript, créez un plan :
Lorsque la page se charge, l'élément canevas et le contexte de dessin sont initialisés.
Définir les objets tentacules. Chaque tentacule se compose de plusieurs segments.
Écoutez les événements de mouvement de la souris et mettez à jour la position de la souris en temps réel.
Les tentacules sont dessinés à travers une boucle d'animation et changent dynamiquement en fonction de la position de la souris, créant un effet d'animation fluide.
Le processus général correspond aux étapes ci-dessus, mais je pense que vous ne comprendrez peut-être pas le processus ci-dessus avant d'avoir terminé l'écriture de ce code, mais cela n'a pas d'importance de toute façon, alors commençons à écrire notre araignée Web :
Préface : Afin de vous aider à mieux comprendre la logique du code, j'ai ajouté des commentaires à chaque code. J'espère que vous pourrez comprendre le code petit à petit à l'aide des commentaires :
// Define requestAnimFrame function window.requestAnimFrame = function () { // Check if the browser supports requestAnimFrame function return ( window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || // If all these options are unavailable, use setTimeout to call the callback function function (callback) { window.setTimeout(callback) } ) } // Initialization function to get canvas element and return related information function init(elemid) { // Get canvas element let canvas = document.getElementById(elemid) // Get 2d drawing context, note that 'd' is lowercase c = canvas.getContext('2d') // Set canvas width to window inner width and height to window inner height w = (canvas.width = window.innerWidth) h = (canvas.height = window.innerHeight) // Set fill style to semi-transparent black c.fillStyle = "rgba(30,30,30,1)" // Fill the entire canvas with the fill style c.fillRect(0, 0, w, h) // Return drawing context and canvas element return { c: c, canvas: canvas } } // Execute function when page is fully loaded window.onload = function () { // Get drawing context and canvas element let c = init("canvas").c, canvas = init("canvas").canvas, // Set canvas width to window inner width and height to window inner height w = (canvas.width = window.innerWidth), h = (canvas.height = window.innerHeight), // Initialize mouse object mouse = { x: false, y: false }, last_mouse = {} // Function to calculate distance between two points function dist(p1x, p1y, p2x, p2y) { return Math.sqrt(Math.pow(p2x - p1x, 2) + Math.pow(p2y - p1y, 2)) } // Define segment class class segment { // Constructor to initialize segment object constructor(parent, l, a, first) { // If it's the first tentacle segment, position is the tentacle top position // Otherwise, position is the nextPos coordinates of the previous segment object this.first = first if (first) { this.pos = { x: parent.x, y: parent.y, } } else { this.pos = { x: parent.nextPos.x, y: parent.nextPos.y, } } // Set segment length and angle this.l = l this.ang = a // Calculate coordinates for the next segment this.nextPos = { x: this.pos.x + this.l * Math.cos(this.ang), y: this.pos.y + this.l * Math.sin(this.ang), } } // Method to update segment position update(t) { // Calculate angle between segment and target point this.ang = Math.atan2(t.y - this.pos.y, t.x - this.pos.x) // Update position coordinates based on target point and angle this.pos.x = t.x + this.l * Math.cos(this.ang - Math.PI) this.pos.y = t.y + this.l * Math.sin(this.ang - Math.PI) // Update nextPos coordinates based on new position coordinates this.nextPos.x = this.pos.x + this.l * Math.cos(this.ang) this.nextPos.y = this.pos.y + this.l * Math.sin(this.ang) } // Method to return segment to initial position fallback(t) { // Set position coordinates to target point coordinates this.pos.x = t.x this.pos.y = t.y this.nextPos.x = this.pos.x + this.l * Math.cos(this.ang) this.nextPos.y = this.pos.y + this.l * Math.sin(this.ang) } show() { c.lineTo(this.nextPos.x, this.nextPos.y) } } // Define tentacle class class tentacle { // Constructor to initialize tentacle object constructor(x, y, l, n, a) { // Set tentacle top position coordinates this.x = x this.y = y // Set tentacle length this.l = l // Set number of tentacle segments this.n = n // Initialize tentacle target point object this.t = {} // Set random movement parameter for tentacle this.rand = Math.random() // Create first segment of the tentacle this.segments = [new segment(this, this.l / this.n, 0, true)] // Create other segments for (let i = 1; i < this.n; i++) { this.segments.push( new segment(this.segments[i - 1], this.l / this.n, 0, false) ) } } // Method to move tentacle to target point move(last_target, target) { // Calculate angle between tentacle top and target point this.angle = Math.atan2(target.y - this.y, target.x - this.x) // Calculate tentacle distance parameter this.dt = dist(last_target.x, last_target.y, target.x, target.y) // Calculate tentacle target point coordinates this.t = { x: target.x - 0.8 * this.dt * Math.cos(this.angle), y: target.y - 0.8 * this.dt * Math.sin(this.angle) } // If target point is calculated, update position coordinates of last segment object // Otherwise, update position coordinates of last segment object to target point coordinates if (this.t.x) { this.segments[this.n - 1].update(this.t) } else { this.segments[this.n - 1].update(target) } // Iterate through all segment objects, update their position coordinates for (let i = this.n - 2; i >= 0; i--) { this.segments[i].update(this.segments[i + 1].pos) } if ( dist(this.x, this.y, target.x, target.y) <= this.l + dist(last_target.x, last_target.y, target.x, target.y) ) { this.segments[0].fallback({ x: this.x, y: this.y }) for (let i = 1; i < this.n; i++) { this.segments[i].fallback(this.segments[i - 1].nextPos) } } } show(target) { // If distance between tentacle and target point is less than tentacle length, draw tentacle if (dist(this.x, this.y, target.x, target.y) <= this.l) { // Set global composite operation to "lighter" c.globalCompositeOperation = "lighter" // Begin new path c.beginPath() // Start drawing line from tentacle starting position c.moveTo(this.x, this.y) // Iterate through all segment objects and use their show method to draw lines for (let i = 0; i < this.n; i++) { this.segments[i].show() } // Set line style c.strokeStyle = "hsl(" + (this.rand * 60 + 180) + ",100%," + (this.rand * 60 + 25) + "%)" // Set line width c.lineWidth = this.rand * 2 // Set line cap style c.lineCap = "round" // Set line join style c.lineJoin = "round" // Draw line c.stroke() // Set global composite operation to "source-over" c.globalCompositeOperation = "source-over" } } // Method to draw tentacle's circular head show2(target) { // Begin new path c.beginPath() // If distance between tentacle and target point is less than tentacle length, draw white circle // Otherwise draw cyan circle if (dist(this.x, this.y, target.x, target.y) <= this.l) { c.arc(this.x, this.y, 2 * this.rand + 1, 0, 2 * Math.PI) c.fillStyle = "white" } else { c.arc(this.x, this.y, this.rand * 2, 0, 2 * Math.PI) c.fillStyle = "darkcyan" } // Fill circle c.fill() } } // Initialize variables let maxl = 400, // Maximum tentacle length minl = 50, // Minimum tentacle length n = 30, // Number of tentacle segments numt = 600, // Number of tentacles tent = [], // Array of tentacles clicked = false, // Whether mouse is pressed target = { x: 0, y: 0 }, // Tentacle target point last_target = {}, // Previous tentacle target point t = 0, // Current time q = 10; // Step length for each tentacle movement // Create tentacle objects for (let i = 0; i < numt; i++) { tent.push( new tentacle( Math.random() * w, // Tentacle x-coordinate Math.random() * h, // Tentacle y-coordinate Math.random() * (maxl - minl) + minl, // Tentacle length n, // Number of tentacle segments Math.random() * 2 * Math.PI, // Tentacle angle ) ) } // Method to draw image function draw() { // If mouse moves, calculate deviation between tentacle target point and current point if (mouse.x) { target.errx = mouse.x - target.x target.erry = mouse.y - target.y } else { // Otherwise, calculate x-coordinate of tentacle target point target.errx = w / 2 + ((h / 2 - q) * Math.sqrt(2) * Math.cos(t)) / (Math.pow(Math.sin(t), 2) + 1) - target.x; target.erry = h / 2 + ((h / 2 - q) * Math.sqrt(2) * Math.cos(t) * Math.sin(t)) / (Math.pow(Math.sin(t), 2) + 1) - target.y; } // Update tentacle target point coordinates target.x += target.errx / 10 target.y += target.erry / 10 // Update time t += 0.01; // Draw tentacle target point c.beginPath(); c.arc( target.x, target.y, dist(last_target.x, last_target.y, target.x, target.y) + 5, 0, 2 * Math.PI ); c.fillStyle = "hsl(210,100%,80%)" c.fill(); // Draw center points of all tentacles for (i = 0; i < numt; i++) { tent[i].move(last_target, target) tent[i].show2(target) } // Draw all tentacles for (i = 0; i < numt; i++) { tent[i].show(target) } // Update previous tentacle target point coordinates last_target.x = target.x last_target.y = target.y } // Function to loop animation drawing function loop() { // Use requestAnimFrame function to loop window.requestAnimFrame(loop) // Clear canvas c.clearRect(0, 0, w, h) // Draw animation draw() } // Listen for window resize event window.addEventListener("resize", function () { // Reset canvas size w = canvas.width = window.innerWidth h = canvas.height = window.innerHeight // Loop animation drawing function loop() }) // Loop animation drawing function loop() // Use setInterval function to loop setInterval(loop, 1000 / 60) // Listen for mouse move event canvas.addEventListener("mousemove", function (e) { // Record previous mouse position last_mouse.x = mouse.x last_mouse.y = mouse.y // Update current mouse position mouse.x = e.pageX - this.offsetLeft mouse.y = e.pageY - this.offsetTop }, false) // Listen for mouse leave event canvas.addEventListener("mouseleave", function (e) { // Set mouse to false mouse.x = false mouse.y = false }) }
Ici, je règle grossièrement le processus du code ci-dessus :
Phase d'initialisation
Définition des objets tentacules
Les principales méthodes de tentacule sont :
move : Mettez à jour la position de chaque segment en fonction de la position de la souris.
show : Dessinez le chemin du tentacule.
Surveillance des événements
Boucle d'animation
drawFunction : Il s'agit d'une fonction récursive utilisée pour créer des effets d'animation.
Comportement des tentacules
De cette façon, vous avez terminé la production de l'araignée électronique !!!
Enfin, jetons un œil à l'effet final :
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!