Preface: After learning JavaScript, you can use JavaScript to achieve some interesting effects. This article explains how to use JavaScript purely to implement an electronic spider on a web page.
Before we start learning how to write a web spider, let's take a look at what this electronic spider looks like:
You can see that it will move with our mouse, so how do you achieve this effect? Let's start explaining.
HTML 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>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>
As you can see our HTML code is very simple, let's start working on it!
Before you start writing JavaScript code, create a plan:
Overall process
When the page loads, the canvas element and drawing context are initialized.
Define tentacle objects . Each tentacle consists of multiple segments.
Listen to mouse movement events and update the mouse position in real time.
The tentacles are drawn through an animation loop, and they change dynamically according to the position of the mouse, creating a smooth animation effect.
The general process is the above steps, but I believe that you may not understand the above process before you have completed the writing of this code, but it doesn't matter anyways, so let's start writing our web spider:
Preface: In order to help you better understand the logic of the code, I have added comments to each code. I hope that you can understand the code bit by bit with the help of the comments:
JavaScript Code
// 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 }) }
Here I roughly sort out the process of the above code:
Initialization phase
- initFunction: When the page is loaded, the function init is called to get the canvas element and set its width and height to the size of the window. The obtained 2D drawing context is used for subsequent drawing.
- window.onload: After the page is loaded, initialize canvas and set context to the initial state of the mouse.
Definition of tentacle objects
- segmentClass: This is a segment of a tentacle. Each segment has a starting point (pos), length (l), angle (ang), and the position of the next segment is calculated by the angle ( nextPos).
- tentacleClass: Represents a complete tentacle, consisting of several segment. The starting point of the tentacle is at the center of the screen, and each tentacle contains multiple segments.
The main methods of tentacle are:
move: Update the position of each segment according to the mouse position.
show: Draw the path of the tentacle.
Event monitoring
- canvas.addEventListener('mousemove', ...): When the mouse moves, the mouse position is captured and stored in the mouse variable. Each mouse movement updates the coordinates of mouse and last_mouse for subsequent animations.
Animation loop
drawFunction : This is a recursive function used to create animation effects.
- First, it fills the canvas with a semi-transparent background in each frame, causing previously drawn content to gradually disappear, creating a smear effect.
- Then, iterate over all tentacles, calling their move and show methods, updating their positions and drawing each frame.
- Finally, use requestAnimFrame(draw) to make continuous recursive draw calls to form an animation loop.
Tentacle Behavior
- The movement of the tentacle move is implemented through the function. The last segment of the tentacle updates its position first, and then the other segments follow in sequence.
- The drawing of the tentacles is done through the show function, which iterates through all segments and draws lines, and finally displays them on the screen.
In this way, you have completed the production of the electronic spider!!!
Finally, let's take a look at the final effect:
以上是Frontend Refresh Project - An Electronic Spider的详细内容。更多信息请关注PHP中文网其他相关文章!

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。 1.Python以简洁语法和丰富库生态着称,适用于数据分析和Web开发。 2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

JavaScript不需要安装,因为它已内置于现代浏览器中。你只需文本编辑器和浏览器即可开始使用。1)在浏览器环境中,通过标签嵌入HTML文件中运行。2)在Node.js环境中,下载并安装Node.js后,通过命令行运行JavaScript文件。

如何在Quartz中提前发送任务通知在使用Quartz定时器进行任务调度时,任务的执行时间是由cron表达式设定的。现�...

在JavaScript中如何获取原型链上函数的参数在JavaScript编程中,理解和操作原型链上的函数参数是常见且重要的任�...

在微信小程序web-view中使用Vue.js动态style位移失效的原因分析在使用Vue.js...

在Tampermonkey中如何对多个链接进行并发GET请求并依次判断返回结果?在Tampermonkey脚本中,我们经常需要对多个链...


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SublimeText3 Linux新版
SublimeText3 Linux最新版

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SublimeText3汉化版
中文版,非常好用

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。