Start with a neat lava lamp effect

This commit is contained in:
Emi Simpson 2023-10-28 12:09:52 -04:00
commit 3654ae61df
Signed by: Emi
GPG key ID: A12F2C2FFDC3D847
3 changed files with 142 additions and 0 deletions

68
drift.js Normal file
View file

@ -0,0 +1,68 @@
const m = 76667 * 78887;
const nextRandom = x => x ** 2 % m
const generateRandomArray = (initialSeed, count) => (
count <= 0
? []
: [initialSeed].concat(generateRandomArray(nextRandom(initialSeed), count - 1)))
const zip = (f, ...lists) => (
lists.some(l => l.length == 0)
? []
: [f(...lists.map(l => l[0]))].concat(zip(f, ...lists.map(l => l.slice(1)))))
const goopZoneElem = document.getElementById("goop-zone");
const goopHeader = document.getElementById("header-box");
const nextState = (state, width, height) => document.hidden ? state : state.map(orig => {
const projectedNewX = orig.x + orig.vx;
const projectedNewY = orig.y + orig.vy;
const [newX, newVX] =
projectedNewX < 0 || projectedNewX > width
? [orig.x - orig.vx, -orig.vx]
: [projectedNewX, orig.vx];
const [newY, newVY] =
projectedNewY < -50 || projectedNewY > height - 20
? [orig.y - orig.vy, -orig.vy]
: [projectedNewY, orig.vy];
return ({
elem: orig.elem,
x: newX,
y: newY,
vx: newVX,
vy: newVY
})
});
const mkInitialState = (drifters, width, height) => zip(
(elem, random1, random2, random3) => (direction =>
({ elem: elem
, x: random1 % width
, y: random2 % height
, vx: 20 * Math.cos(direction)
, vy: 20 * Math.sin(direction)
})
)(random3 % 2000 / 1000 * Math.PI),
drifters,
generateRandomArray(5737051, drifters.length),
generateRandomArray(5457297, drifters.length),
generateRandomArray(3631413, drifters.length))
const applyState = states => states.map(s => {
s.elem.setAttribute('style', `transform: translate(${s.x}px, ${s.y}px)`)
});
loop = (state) => {
setInterval(() => {
const goopZoneWidth = goopZoneElem.width.baseVal.value;
const goopZoneHeight = goopZoneElem.height.baseVal.value;
goopHeader.setAttribute("x", goopZoneWidth/2-300);
state = nextState(state, goopZoneWidth, goopZoneHeight);
applyState(state)
}, 500)
}
const drifters = Array.from(document.getElementsByClassName("glob"));
loop(mkInitialState(drifters, goopZoneElem.width.baseVal.value, goopZoneElem.height.baseVal.value));

47
index.html Normal file
View file

@ -0,0 +1,47 @@
<!Doctype HTML>
<html>
<head>
<title>Emi Simpson - Nice to meet you!</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<header>
<svg id=goop-zone>
<defs>
<filter id="goop-full">
<feGaussianBlur stdDeviation="30"/>
<feColorMatrix values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1000 -250"/>
</filter>
<path
id="the-one-true-glob"
d="M 24.0,158.5 0,67.2 48.1,0 189.7,36.6 146.5,87.4 185.2,135.3 84.8,134.1 Z" />
</defs>
<g style="filter:url(#goop-full);width:100%;height:100%">
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<use class="glob" xlink:href="#the-one-true-glob" />
<rect width=2000 height=30 x=-60 y=400 /> <!-- base -->
<rect width=600 height=130 x=100 y=135 id="header-box" />
</g>
</svg>
<h1>Emi Simpson</h1>
</header>
<script src="drift.js"></script>
<main>
</main>
</body>
</html>

27
style.sass Normal file
View file

@ -0,0 +1,27 @@
body, html
margin: 0
padding: 0
display: grid
grid-template-rows: 400px 1fr
height: 100vh
h1
position: absolute
top: 140px
text-align: center
width: 100vw
color: white
font-family: Atkinson Hyperlegible
font-size: 3em
#goop-zone
position: relative
width: 100vw
height: 400px
fill: #b50931
.glob
transition: transform 0.485s linear
main
background-color: #b50931