Deno Logo Animated SVG

Mr. Denosaur with animated raindrops on the backdrop.

by Nicholas Berlette

HTML

<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 512 512" width="512" height="512" color="#000">
  <title>Deno Land</title>
  <circle fill="currentColor" cx="256" cy="256" r="256" style="z-index:-100" />
  <circle fill="currentColor" cx="256" cy="256" r="256" style="z-index:-100" filter="url(#light1)" mask="url(#deno-logo-mask)" />
  <g width="100%" height="100%" mask="url(#deno-logo-mask)">
    <use href="#raindrops" width="100%" height="100%" transform="scale(2.5)" x="-20">
      <animate attributeName="x" by="-300" dur="30s" begin="0s" repeatCount="indefinite" />
      <animate attributeName="y" values="-400; 0; 400" dur="30s" begin="0s" repeatCount="indefinite" />
    </use>
  </g>
  <g style="z-index:100">
    <path mask="url(#deno-logo-mask)" stroke="none" stroke-width="20" stroke-linecap="round" class="_raindrops" d="M71 319l17-63M107.964 161.095l17-63M36.93 221l17-63M125.964 385l17-63M160.372 486.829l17-63M230 456.329l17-63M206.257 92.587l17-63M326.395 173.004l17-63M452.182 304.693l17-63M409.124 221l17-63M299.027 54.558l17-63M400.624 86.058l17-63" />
    <path mask="url(#deno-logo-mask)" fill="white" stroke="black" stroke-width="12" d="M252.225 344.418c-86.65 2.61-144.576-34.5-144.576-94.363 0-61.494 60.33-111.145 138.351-111.145 37.683 0 69.532 10.65 94.392 30.092 21.882 17.113 37.521 40.526 45.519 66.312 2.574 8.301 22.863 83.767 61.112 227.295l1.295 4.86-159.793 74.443-1.101-8.063c-8.85-64.778-16.546-113.338-23.076-145.634-3.237-16.004-6.178-27.96-8.79-35.794-1.227-3.682-2.355-6.361-3.303-7.952a12.56 12.56 0 00-.03-.05z" />
    <circle cx="262" cy="203" r="16" style="z-index:1000;" transform-origin="50% 40%" transform="scale(1, 1);">
      <animateTransform attributeType="XML" attributeName="transform" type="scale" begin="3s" dur="3.3s" on="load" repeatCount="indefinite" values="1 1; 1 .2; 1 1; 1 1; 1 .2; 1 1; 1 1" keyTimes="0.0; 0.025; 0.06; 0.18; 0.2; 0.23; 1.0" />
    </circle>
  </g>
  <defs>
    <filter id="light1" x="0" y="0" width="100%"...

JavaScript

/* (() => {
    // deno:file:///home/runner/work/dotcom/dotcom/landingpage/main.js
    var observer = new IntersectionObserver((entries) => {
      for (const entry of entries) {
        if (entry.isIntersecting) {
          entry.target.className += " inview";
        }
      }
    });
    var observed = document.getElementsByClassName("observed");
    for (const target of observed) {
      observer.observe(target);
    }

    var canvas = document.querySelector("canvas");
    var ctx = canvas.getContext("2d");

    function resize(canvas2) {
      const displayWidth = canvas2.clientWidth;
      const displayHeight = canvas2.clientHeight;
      if (canvas2.width != displayWidth) {
        canvas2.width = displayWidth;
      }
      if (canvas2.height != displayHeight) {
        canvas2.height = displayHeight;
      }
    }
    var drops = [];
    for (let i = 0; i < 100; i++) {
      drops.push({
        t: Math.random(),
        deg: Math.random() * Math.PI
      });
    }
    var particles = [];
    var CY = -300;
    var RAIN_LENGTH = 0.05;
    var circleR = 300;
    var t = 0;
    var forward = true;

    function redraw(_timestamp, diff) {
      resize(canvas);
      circleR = canvas.height * 4;
      CY = -circleR * 3 / 4;
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.strokeStyle = "white";
      ctx.lineWidth = 1.25;
      ctx.save();
      ctx.translate(canvas.width / 2, CY);
      if (forward) {
        t += diff / 2e3;
      } else {
        t -= diff / 2e3;
      }
      t = 1;
      ctx.beginPath();
      for (const drop of drops) {
        const x1 = Math.cos(drop.deg) * drop.t * circleR;
        const x2 = Math.cos(drop.deg) * (drop.t + RAIN_LENGTH) * circleR;
        const y1 = Math.sin(drop.deg) * drop.t * circleR;
        const y2 = Math.sin(drop.deg) * (drop.t + RAIN_LENGTH) * circleR;
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        drop.t += diff / 800;
        if (drop.t > 1) {
          if (Math.random() <...