flow field
A Pen by Fabio Ottaviani on CodePen.
flow field
A Pen by Fabio Ottaviani on CodePen.
| <!-- | |
| Follow me on | |
| Instagram: https://www.instagram.com/supahfunk/ | |
| Dribbble: https://dribbble.com/supahfunk | |
| Twitter: https://twitter.com/supahfunk | |
| Codepen: https://codepen.io/supah/ | |
| --> |
| /*-------------------- | |
| Vars | |
| --------------------*/ | |
| const deg = (a) => Math.PI / 180 * a | |
| const rand = (v1, v2) => Math.floor(v1 + Math.random() * (v2 - v1)) | |
| const opt = { | |
| particles: window.width / 500 ? 1000 : 500, | |
| noiseScale: 0.009, | |
| angle: Math.PI / 180 * -90, | |
| h1: rand(0, 360), | |
| h2: rand(0, 360), | |
| s1: rand(20, 90), | |
| s2: rand(20, 90), | |
| l1: rand(30, 80), | |
| l2: rand(30, 80), | |
| strokeWeight: 1.2, | |
| tail: 82, | |
| } | |
| const Particles = [] | |
| let time = 0 | |
| document.body.addEventListener('click', () => { | |
| opt.h1 = rand(0, 360) | |
| opt.h2 = rand(0, 360) | |
| opt.s1 = rand(20, 90) | |
| opt.s2 = rand(20, 90) | |
| opt.l1 = rand(30, 80) | |
| opt.l2 = rand(30, 80) | |
| opt.angle += deg(random(60, 60)) * (Math.random() > .5 ? 1 : -1) | |
| for (let p of Particles) { | |
| p.randomize() | |
| } | |
| }) | |
| /*-------------------- | |
| Particle | |
| --------------------*/ | |
| class Particle { | |
| constructor(x, y) { | |
| this.x = x | |
| this.y = y | |
| this.lx = x | |
| this.ly = y | |
| this.vx = 0 | |
| this.vy = 0 | |
| this.ax = 0 | |
| this.ay = 0 | |
| this.hueSemen = Math.random() | |
| this.hue = this.hueSemen > .5 ? 20 + opt.h1 : 20 + opt.h2 | |
| this.sat = this.hueSemen > .5 ? opt.s1 : opt.s2 | |
| this.light = this.hueSemen > .5 ? opt.l1 : opt.l2 | |
| this.maxSpeed = this.hueSemen > .5 ? 3 : 2 | |
| } | |
| randomize() { | |
| this.hueSemen = Math.random() | |
| this.hue = this.hueSemen > .5 ? 20 + opt.h1 : 20 + opt.h2 | |
| this.sat = this.hueSemen > .5 ? opt.s1 : opt.s2 | |
| this.light = this.hueSemen > .5 ? opt.l1 : opt.l2 | |
| this.maxSpeed = this.hueSemen > .5 ? 3 : 2 | |
| } | |
| update() { | |
| this.follow() | |
| this.vx += this.ax | |
| this.vy += this.ay | |
| var p = Math.sqrt(this.vx * this.vx + this.vy * this.vy) | |
| var a = Math.atan2(this.vy, this.vx) | |
| var m = Math.min(this.maxSpeed, p) | |
| this.vx = Math.cos(a) * m | |
| this.vy = Math.sin(a) * m | |
| this.x += this.vx | |
| this.y += this.vy | |
| this.ax = 0 | |
| this.ay = 0 | |
| this.edges() | |
| } | |
| follow() { | |
| let angle = (noise(this.x * opt.noiseScale, this.y * opt.noiseScale, time * opt.noiseScale)) * Math.PI * 0.5 + opt.angle | |
| this.ax += Math.cos(angle) | |
| this.ay += Math.sin(angle) | |
| } | |
| updatePrev() { | |
| this.lx = this.x | |
| this.ly = this.y | |
| } | |
| edges() { | |
| if (this.x < 0) { | |
| this.x = width | |
| this.updatePrev() | |
| } | |
| if (this.x > width) { | |
| this.x = 0 | |
| this.updatePrev() | |
| } | |
| if (this.y < 0) { | |
| this.y = height | |
| this.updatePrev() | |
| } | |
| if (this.y > height) { | |
| this.y = 0 | |
| this.updatePrev() | |
| } | |
| } | |
| render () { | |
| stroke(`hsla(${this.hue}, ${this.sat}%, ${this.light}%, .5)`) | |
| line(this.x, this.y, this.lx, this.ly) | |
| this.updatePrev() | |
| } | |
| } | |
| /*-------------------- | |
| Setup | |
| --------------------*/ | |
| function setup() { | |
| createCanvas(windowWidth, windowHeight) | |
| for (let i = 0; i < opt.particles; i++) { | |
| Particles.push(new Particle(Math.random() * width, Math.random() * height)) | |
| } | |
| strokeWeight(opt.strokeWeight) | |
| } | |
| /*-------------------- | |
| Draw | |
| --------------------*/ | |
| function draw() { | |
| time++ | |
| background(0, 100 - opt.tail) | |
| for (let p of Particles) { | |
| p.update() | |
| p.render() | |
| } | |
| } | |
| /*-------------------- | |
| Resize | |
| --------------------*/ | |
| function windowResized() { | |
| resizeCanvas(windowWidth, windowHeight) | |
| } |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.min.js"></script> |
| body { | |
| margin: 0; | |
| height: 100vh; | |
| overflow: hidden; | |
| background: black; | |
| } |