LED Animation simulator

by nickcoutsos

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
<script src="https://raw.github.com/processing-js/processing-js/v1.4.8/processing.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.4.0/simplex-noise.min.js"></script>
<div id="leds"></div>

CSS

html, body {
  width: 100%;
  height: 100;
  background: #102030;
  padding: 0;
  margin: 0;
}

#leds {
  position: absolute;
  left: 50%;
  top: 50%;
  
  transform: translate(-50%, -50%);
}

.led-wrapper {
  background: #204060;
  border: 2px solid rgba(20, 20, 20, 0.5);
  padding: 0;
  margin: 0;
}

.led {
  position: relative;
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  mix-blend-mode: lighten;
}

JavaScript

const simplex = new SimplexNoise()
const TICK_MAX = Math.pow(2, 16)
const ledCount = 8
const RGBLED_NUM = ledCount
const led = []
const led_positions = [
	[-2, 1.5],
  [-2, 0.5],
  [-2, -0.5],
  [-2, -1.5],
  [2, 1.5],
  [2, 0.5],
  [2, -0.5],
  [2, -1.5],
];
const ledMinPos = {
	x: led_positions.reduce((min, pos) => Math.min(pos[0], min), Infinity),
  y: led_positions.reduce((min, pos) => Math.min(pos[1], min), Infinity)
}
const ledMaxPos = {
	x: led_positions.reduce((max, pos) => Math.max(pos[0], max), -Infinity),
  y: led_positions.reduce((max, pos) => Math.max(pos[1], max), -Infinity)
}
const led_ranges = {
	x: {
  	min: ledMinPos.x,
  	max: ledMaxPos.x,
    range: ledMaxPos.x - ledMinPos.x
  },
  y: {
  	min: ledMinPos.y,
  	max: ledMaxPos.y,
    range: ledMaxPos.y - ledMinPos.y
  }
}

const effects = {
	'Light Wave': rgblight_effect_light_wave,
  'Hue Wave': rgblight_effect_hue_wave,
  'Police Flash': rgblight_effect_police_flash,
  'Outrun': rgblight_effect_outrun,
  'Progress': rgblight_effect_progress
}

const config = {
  RGBLIGHT_HUE_STEP: 72,
  active_effect: 'Police Flash',
  glow: true,
  noise: 0.3
}

const rgblight_config = {
	hue: 112,
  sat: 100,
  val: 60,
  speed: 128
}

const anim = {
	pos: 0,
  tick: 0,
  run: true,
  loop: true,
  restart: function() {
    this.tick = 0
  	this.pos = 0
    this.run = true
    this.loop = true
    update()
  },
  current_hue: 0,
  current_offset: 0
}

function rgblight_effect_hue_wave(anim) {
  const t = (anim.tick * (rgblight_config.speed / 64) / 255) % 255

  for (let i = 0; i < RGBLED_NUM; i++) {
  	const [x, y] = led_positions[i]
    const d = t - (y - led_ranges.y.min) / led_ranges.y.range;
    const a = (Math.sin(d) + 1) / 2.0 * 255.0;
    const hue = BLEND(rgblight_config.hue, rgblight_config.hue + config.RGBLIGHT_HUE_STEP, a)
    const val = rgblight_config.val + 20 * (1 + simplex.noise2D(i, t*2))/2 * config.noise
    sethsv(hue, rgblight_config.sat, val, led[i]);
  }
}

function...