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() <...