>_htmlhub
library/retro & cyberpunk/neon-hexagon-patterns

Neon Hexagons

Live previewPerformance varies by device
neon-hexagon-patterns.html

No account needed to copy or download. Check dependencies and thelicense status before publishing.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Neon Hexagon Patterns</title>
  <style>
    html, body {
      margin: 0;
      padding: 0;
      overflow: hidden;
      background: #000;
    }
    /* Make the canvas cover the entire viewport */
    canvas {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      display: block;
    }
  </style>
</head>
<body>
  <canvas id="c"></canvas>
  <script>
    // Grab the canvas and context
    var c = document.getElementById('c');
    var ctx = c.getContext('2d');
    var w = c.width = window.innerWidth;
    var h = c.height = window.innerHeight;
    // Configuration options controlling the behaviour of the lines
    var opts = {
      len: 20,
      count: 50,
      baseTime: 10,
      addedTime: 10,
      dieChance: 0.05,
      spawnChance: 1,
      sparkChance: 0.1,
      sparkDist: 10,
      sparkSize: 2,
      color: 'hsl(hue,100%,light%)',
      baseLight: 50,
      addedLight: 10,        // range: [50-10, 50+10]
      shadowToTimePropMult: 6,
      baseLightInputMultiplier: 0.01,
      addedLightInputMultiplier: 0.02,
      cx: w / 2,
      cy: h / 2,
      repaintAlpha: 0.04,
      hueChange: 0.1
    };
    var tick = 0;
    var lines = [];
    var dieX = w / 2 / opts.len;
    var dieY = h / 2 / opts.len;
    var baseRad = Math.PI * 2 / 6;
    ctx.fillStyle = 'black';
    ctx.fillRect(0, 0, w, h);
    /**
     * Primary animation loop. Clears the canvas with a semi‑transparent fill,
     * spawns new lines as needed, and advances existing lines.
     */
    function loop() {
      window.requestAnimationFrame(loop);
      tick++;
      ctx.globalCompositeOperation = 'source-over';
      ctx.shadowBlur = 0;
      ctx.fillStyle = 'rgba(0,0,0,' + opts.repaintAlpha + ')';
      ctx.fillRect(0, 0, w, h);
      ctx.globalCompositeOperation = 'lighter';
      if (lines.length < opts.count && Math.random() < opts.spawnChance) {
        lines.push(new Line());
      }
      lines.forEach(function(line) {
        line.step();
      });
    }
    /**
     * Construct a line and initialise its state.
     */
    function Line() {
      this.reset();
    }
    Line.prototype.reset = function() {
      this.x = 0;
      this.y = 0;
      this.addedX = 0;
      this.addedY = 0;
      this.rad = 0;
      this.lightInputMultiplier = opts.baseLightInputMultiplier + opts.addedLightInputMultiplier * Math.random();
      this.color = opts.color.replace('hue', tick * opts.hueChange);
      this.cumulativeTime = 0;
      this.beginPhase();
    };
    /**
     * Begin a new movement phase for the line. Chooses a random direction
     * and duration. If the line travels too far or randomly dies, it resets.
     */
    Line.prototype.beginPhase = function() {
      this.x += this.addedX;
      this.y += this.addedY;
      this.time = 0;
      this.targetTime = (opts.baseTime + opts.addedTime * Math.random()) | 0;
      this.rad += baseRad * (Math.random() < 0.5 ? 1 : -1);
      this.addedX = Math.cos(this.rad);
      this.addedY = Math.sin(this.rad);
      if (Math.random() < opts.dieChance || this.x > dieX || this.x < -dieX || this.y > dieY || this.y < -dieY) {
        this.reset();
      }
    };
    /**
     * Advance the line one frame. Draws its current position with a glow.
     */
    Line.prototype.step = function() {
      this.time++;
      this.cumulativeTime++;
      if (this.time >= this.targetTime) {
        this.beginPhase();
      }
      var prop = this.time / this.targetTime;
      var wave = Math.sin(prop * Math.PI / 2);
      var x = this.addedX * wave;
      var y = this.addedY * wave;
      ctx.shadowBlur = prop * opts.shadowToTimePropMult;
      ctx.fillStyle = ctx.shadowColor = this.color.replace('light', opts.baseLight + opts.addedLight * Math.sin(this.cumulativeTime * this.lightInputMultiplier));
      ctx.fillRect(opts.cx + (this.x + x) * opts.len, opts.cy + (this.y + y) * opts.len, 2, 2);
      // occasional sparks
      if (Math.random() < opts.sparkChance) {
        ctx.fillRect(
          opts.cx + (this.x + x) * opts.len + Math.random() * opts.sparkDist * (Math.random() < 0.5 ? 1 : -1) - opts.sparkSize / 2,
          opts.cy + (this.y + y) * opts.len + Math.random() * opts.sparkDist * (Math.random() < 0.5 ? 1 : -1) - opts.sparkSize / 2,
          opts.sparkSize,
          opts.sparkSize
        );
      }
    };
    loop();
    // Resize handler to keep canvas full‑screen
    window.addEventListener('resize', function() {
      w = c.width = window.innerWidth;
      h = c.height = window.innerHeight;
      ctx.fillStyle = 'black';
      ctx.fillRect(0, 0, w, h);
      opts.cx = w / 2;
      opts.cy = h / 2;
      dieX = w / 2 / opts.len;
      dieY = h / 2 / opts.len;
    });
  </script>
</body>
</html>

About this animation

Glowing hexagonal grid pattern with neon effects.

Source Code
Copied to clipboard