Dynamic Flow Fields with Vanilla JS and HTML Canvas
Have you ever been mesmerized by abstract particle animations? These flowing, dynamic visuals can be achieved with surprisingly simple techniques using plain JavaScript and the HTML canvas element. In this article, we will break down the process of creating a flow field that animates thousands of particles, giving them a natural movement.
1. Setting Up the Project
To start, we need three files: an HTML file to set up the canvas, a CSS file for styling, and a JavaScript file for handling the logic.
<meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Flow Fields</title> <link rel="stylesheet" href="styles.css"> <canvas id="canvas1"></canvas> <script src="script.js"></script>
Explanation:
- We define a
- The styles.css will be linked to style the canvas.
- The main animation logic is contained in script.js.
2. Styling the Canvas with CSS
Let’s add a simple style to give our canvas a black background and make sure all padding and margins are removed.
* { margin: 0; padding: 0; box-sizing: border-box; } canvas { background-color: black; }
Explanation:
- Setting margin and padding to zero ensures that the canvas fills the entire screen.
- The black background provides a nice contrast for the white particles.
3. Particle Class: Creating the Magic
The Particle class is where the core of the animation lies. Each particle moves across the canvas, leaving a trail of its past locations, creating the flowing effect.
class Particle { constructor(effect) { this.effect = effect; this.x = Math.floor(Math.random() * this.effect.width); this.y = Math.floor(Math.random() * this.effect.height); this.speedModifier = Math.floor(Math.random() * 5 + 1); this.history = [{ x: this.x, y: this.y }]; this.maxLength = Math.floor(Math.random() * 200 + 10); this.timer = this.maxLength * 2; this.colors = ['#4C026B', '#8E0E00', '#9D0208', '#BA1A1A', '#730D9E']; this.color = this.colors[Math.floor(Math.random() * this.colors.length)]; } draw(context) { context.beginPath(); context.moveTo(this.history[0].x, this.history[0].y); for (let i = 1; i = 1) { let x = Math.floor(this.x / this.effect.cellSize); let y = Math.floor(this.y / this.effect.cellSize); let index = y * this.effect.cols + x; let angle = this.effect.flowField[index]; this.speedX = Math.cos(angle); this.speedY = Math.sin(angle); this.x += this.speedX * this.speedModifier; this.y += this.speedY * this.speedModifier; this.history.push({ x: this.x, y: this.y }); if (this.history.length > this.maxLength) { this.history.shift(); } } else if (this.history.length > 1) { this.history.shift(); } else { this.reset(); } } reset() { this.x = Math.floor(Math.random() * this.effect.width); this.y = Math.floor(Math.random() * this.effect.height); this.history = [{ x: this.x, y: this.y }]; this.timer = this.maxLength * 2; } }
Explanation:
- Constructor: Each particle is initialized with a random position and movement speed. The history array tracks past positions to create trails.
- draw(): This function draws the particle’s path based on its history. The particle leaves a colorful trail that adds to the visual effect.
- update(): Here, the particle's position is updated by calculating the angle from the flow field. The speed and direction are controlled by trigonometric functions.
- reset(): When the particle finishes its trail, it is reset to a new random location.
4. Effect Class: Organizing the Animation
The Effect class handles the creation of particles and the flow field itself, which controls the movement of the particles.
class Effect { constructor(canvas) { this.canvas = canvas; this.width = this.canvas.width; this.height = this.canvas.height; this.particles = []; this.numberOfParticles = 3000; this.cellSize = 20; this.flowField = []; this.curve = 5; this.zoom = 0.12; this.debug = true; this.init(); } init() { this.rows = Math.floor(this.height / this.cellSize); this.cols = Math.floor(this.width / this.cellSize); for (let y = 0; y { particle.draw(context); particle.update(); }); } }
Explanation:
- Constructor: Initializes the canvas dimensions, the number of particles, and the flow field.
- init(): Calculates the angles for the flow field by combining trigonometric functions for each grid cell. This field influences how particles move.
- drawGrid(): Draws the grid that divides the canvas into cells, used when debugging.
- render(): Calls the draw and update methods for each particle to animate the particles across the canvas.
5. Bringing it to Life with the Animation Loop
To make everything work, we need an animation loop that continuously clears the canvas and re-renders the particles:
const effect = new Effect(canvas); function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); effect.render(ctx); requestAnimationFrame(animate); } animate();
Explanation:
- clearRect(): Clears the canvas on each frame to avoid drawing over previous frames.
- requestAnimationFrame: Keeps the animation smooth by recursively calling the animate() function.
Conclusion
By breaking down the Particle and Effect classes, we have created a fluid and dynamic flow field animation using only vanilla JavaScript. The simplicity of the HTML canvas, combined with JavaScript's trigonometric functions, allows us to build these mesmerizing visual effects.
Feel free to play around with the particle count, colors, or the flow field formula to create your own unique effects!
The above is the detailed content of Flow Field Screen. For more information, please follow other related articles on the PHP Chinese website!

JavaScript core data types are consistent in browsers and Node.js, but are handled differently from the extra types. 1) The global object is window in the browser and global in Node.js. 2) Node.js' unique Buffer object, used to process binary data. 3) There are also differences in performance and time processing, and the code needs to be adjusted according to the environment.

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

The main difference between Python and JavaScript is the type system and application scenarios. 1. Python uses dynamic types, suitable for scientific computing and data analysis. 2. JavaScript adopts weak types and is widely used in front-end and full-stack development. The two have their own advantages in asynchronous programming and performance optimization, and should be decided according to project requirements when choosing.

Whether to choose Python or JavaScript depends on the project type: 1) Choose Python for data science and automation tasks; 2) Choose JavaScript for front-end and full-stack development. Python is favored for its powerful library in data processing and automation, while JavaScript is indispensable for its advantages in web interaction and full-stack development.

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SublimeText3 English version
Recommended: Win version, supports code prompts!

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

Dreamweaver Mac version
Visual web development tools

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools
