Loading

Swirly | Flow Field

Read more about how a Flow Field works on my blog: https://codepen.io/DonKarlssonSan/post/particles-in-simplex-noise-flow-field

<!DOCTYPE html>
<html >
<head>
  <meta charset="UTF-8">
  <title>Swirly | Flow Field</title>
  
  
  
      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>
  <canvas id="canvas"></canvas>
  <script src='js/jbwaad.js'></script>
<script src='js/jreejo.js'></script>

    <script  src="js/index.js"></script>

</body>
</html>
/* Downloaded from https://ahoj.co.uk/ */
body, html {
  margin: 0;
  background-color: black;
}

canvas {
  display: block;
}
/* Downloaded from https://ahoj.co.uk/ */
"use strict";

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/*
  Johan Karlsson (DonKarlssonSan) 2017
  Read more about how a Flow Field works on my blog:
  https://codepen.io/DonKarlssonSan/post/particles-in-simplex-noise-flow-field  
*/

var config = {
  size: 3,
  noiseSpeed: 0.01,
  fieldForce: 30,
  widthToSpikeLengthRatio: 0.02
};

var colorConfig = {
  particleOpacity: 0.1,
  baseHue: 30,
  hueRange: 20,
  hueSpeed: 0.01,
  colorSaturation: 100
};

var Particle = function () {
  function Particle(x, y) {
    _classCallCheck(this, Particle);

    this.pos = new Vector(x, y);
    this.vel = new Vector(0, spikeLength);
  }

  Particle.prototype.move = function move(force) {
    if (force) {
      this.vel.addTo(force);
    }
    if (this.vel.getLength() > spikeLength) {
      this.vel.setLength(spikeLength);
    }
  };

  Particle.prototype.draw = function draw() {
    ctx.beginPath();
    ctx.moveTo(this.pos.x, this.pos.y);
    var p2 = this.pos.add(this.vel);
    ctx.lineTo(p2.x, p2.y);
    ctx.stroke();
  };

  return Particle;
}();

var canvas = undefined;
var ctx = undefined;
var field = undefined;
var w = undefined,
    h = undefined;
var columns = undefined;
var rows = undefined;
var noiseZ = undefined;
var hue = undefined;
var zoom = undefined;
var particles = undefined;
var spikeLength = undefined;

function setup() {
  noiseZ = 0;
  canvas = document.querySelector("#canvas");
  ctx = canvas.getContext("2d");
  window.addEventListener("resize", reset);
  reset();
}

function reset() {
  hue = colorConfig.baseHue;
  noise.seed(Math.random());
  w = canvas.width = window.innerWidth;
  h = canvas.height = window.innerHeight;
  spikeLength = w * config.widthToSpikeLengthRatio;
  zoom = spikeLength * 3;
  columns = Math.floor(w / config.size) + 1;
  rows = Math.floor(h / config.size) + 1;
  drawText();
  initField();
}

// Please optimize me
// We just need the flow field where the text is
// An area above and an area below could sometimes
// be removed (depending on window height).
function initField() {
  field = new Array(columns);
  for (var x = 0; x < columns; x++) {
    field[x] = new Array(columns);
    for (var y = 0; y < rows; y++) {
      field[x][y] = new Vector(0, 0);
    }
  }
}

function calculateField() {
  for (var x = 0; x < columns; x++) {
    for (var y = 0; y < rows; y++) {
      var a = noise.simplex3(x / zoom, y / zoom, noiseZ) * Math.PI * 2;
      var l = noise.simplex3(x / zoom + 40000, y / zoom + 40000, noiseZ) * config.fieldForce;
      field[x][y].setLength(l);
      field[x][y].setAngle(a);
    }
  }
}

function draw() {
  drawBackground(0.3);
  requestAnimationFrame(draw);
  noiseZ += config.noiseSpeed;
  calculateField();
  drawParticles();
}

function drawBackground(alpha) {
  ctx.fillStyle = "rgba(0, 0, 0, " + alpha + ")";
  ctx.fillRect(0, 0, w, h);
}

function drawText() {
  ctx.save();
  var text = "Swirly";
  var fontSize = w * 0.26;
  ctx.font = "bold " + fontSize + "px sans-serif";
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";

  ctx.lineWidth = 1;
  ctx.strokeStyle = "white";
  ctx.strokeText(text, w / 2, h / 2);
  ctx.restore();
  var imageData = ctx.getImageData(0, 0, w, h);

  particles = [];

  for (var x = 0; x < w; x++) {
    for (var y = 0; y < h; y++) {
      var i = (x + w * y) * 4;
      var average = (imageData.data[i] + imageData.data[i + 1] + imageData.data[i + 2] + imageData.data[i + 3]) / 4;
      if (average > 200) {
        var particle = new Particle(x, y);
        particles.push(particle);
      }
    }
  }
  drawBackground(1);
}

function drawParticles() {
  hue += colorConfig.hueSpeed;
  var h = Math.sin(hue) * colorConfig.hueRange + colorConfig.baseHue;
  ctx.strokeStyle = "hsla(" + h + ", " + colorConfig.colorSaturation + "%, 50%, " + colorConfig.particleOpacity + ")";
  var x = undefined;
  var y = undefined;
  particles.forEach(function (p) {
    x = Math.floor(p.pos.x / config.size);
    y = Math.floor(p.pos.y / config.size);
    if (x >= 0 && x < columns && y >= 0 && y < rows) {
      p.move(field[x][y]);
    }
    p.draw();
  });
}

setup();
draw();

This awesome code is write by Johan Karlsson, you can se more from this user in the personal repository