Some droplets

This commit is contained in:
JP Hastings-Spital 2024-05-26 19:55:33 +01:00
parent f265cbe8ab
commit 4e7ff21197
5 changed files with 126 additions and 2 deletions

View file

@ -28,7 +28,7 @@ tasks:
cmds:
- |
[ -d "$HOME/.puma-dev/" ] && (echo {{ .port }} > $HOME/.puma-dev/{{ .domain }}) || echo "Puma dev not installed, https://{{ .domain }}{{ .puma_dev_tld }} will not work"
- hugo server --port {{ .port }} --minify --printUnusedTemplates --buildDrafts --baseURL "https://{{ .domain }}{{ .puma_dev_tld }}" --appendPort=false
- hugo server --bind "0.0.0.0" --port {{ .port }} --minify --printUnusedTemplates --buildDrafts --baseURL "https://{{ .domain }}{{ .puma_dev_tld }}" --appendPort=false
build:
desc: Builds the production-ready site in ./public/

View file

@ -107,3 +107,104 @@ document.addEventListener("DOMContentLoaded", () => {
.catch(console.error)
})
})
/* drops */
const dropsContainer = document.getElementById('drops');
let drops = [];
const dropLength = 0.5; // s
const fps = 60;
const dropIncrement = 1/(fps*dropLength);
function createDrop(posX, posY) {
startDropCounter();
const el = document.createElement('div');
let size = 0;
el.style.setProperty('--dropSize', size);
el.style.setProperty('top', posY);
el.style.setProperty('left', posX);
drops.push({ el, size });
dropsContainer.appendChild(el);
playDroplet();
}
let dropCounterInterval;
function startDropCounter() {
if (dropCounterInterval) {
return;
}
dropCounterInterval = setInterval(updateDropCounter, 1000/fps);
}
function updateDropCounter() {
for (const [i, drop] of drops.entries()) {
if (drop.size > 1) {
dropsContainer.removeChild(drop.el);
drops.splice(i, 1);
continue;
}
drop.size += dropIncrement;
drop.el.style.setProperty('--dropSize', `${drop.size}`);
}
if (drops.length == 0) {
clearInterval(dropCounterInterval);
dropCounterInterval = false;
}
}
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
function playDroplet() {
const playLength = dropLength * 2 / 3;
const startFreq = 98 + gRand(12);
const endFreq = 220 + gRand(12);
const oscillator = audioContext.createOscillator();
oscillator.type = 'sine'
oscillator.frequency.setValueAtTime(startFreq, audioContext.currentTime);
oscillator.frequency.exponentialRampToValueAtTime(endFreq, audioContext.currentTime + playLength);
const gainNode = audioContext.createGain();
gainNode.gain.setValueAtTime(0.2, audioContext.currentTime);
gainNode.gain.linearRampToValueAtTime(0, audioContext.currentTime + playLength);
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.start();
oscillator.stop(audioContext.currentTime + playLength);
}
let raining = false;
document.body.addEventListener('click', (e) => {
raining = false;
switch(e.target.tagName) {
case 'A':
case 'BUTTON':
return true;
default:
}
createDrop(`${e.pageX}px`, `${e.pageY}px`);
return true;
});
function gRand(scale = 1) {
return scale * Math.sqrt(-2 * Math.log(1 - Math.random())) * Math.cos(2 * Math.PI * Math.random())
}
function doRain() {
if (!raining) {
return
}
createDrop(`${Math.random() * document.body.scrollWidth}px`, `${Math.random() * document.body.scrollHeight}px`);
setTimeout(doRain, 250+gRand(250));
}
function rain() {
raining = true;
doRain();
}

21
assets/scss/_drops.scss Normal file
View file

@ -0,0 +1,21 @@
#drops {
overflow: clip;
max-height: 100%;
max-width: 100%;
div {
position: absolute;
aspect-ratio: 1/1;
border: 1px solid var(--accent);
width: calc(500px * var(--dropSize));
border-radius: calc(500px * var(--dropSize));
transform: translate(-50%, -50%);
opacity: calc(1 - var(--dropSize));
overflow: hidden;
filter: drop-shadow(0px 0px 4px var(--accent));
z-index: -1;
}
}

View file

@ -19,3 +19,4 @@
@import "404";
@import "search";
@import "links";
@import "drops";

View file

@ -7,7 +7,7 @@
{{ block "body" . }}
<body class="{{ with .Page.Params.stylescope }}{{ . }}{{ end }}">
{{ end }}
<div class="container">
{{ partial "header.html" . }}
@ -20,6 +20,7 @@
{{ end }}
</div>
<div id="drops"></div>
{{ partial "javascript.html" . }}
</body>
</html>