massi-world

this website of mine
Log | Files | Refs

commit a7df5a25d9007831ec6bec7609c1558ff869af47
parent be41cccaa62cb9d2d4a6867cec2ce3952cf318c3
Author: massi <git@massi.world>
Date:   Fri, 30 Aug 2024 04:27:40 -0700

homepage header and blurb

Diffstat:
Asite/md/blurb.templ.md | 9+++++++++
Msite/style.templ.css | 76++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/site.clj | 7+++++--
Mts/the-world.ts | 108++++++++++++++++++++++++++++++++++++++++----------------------------------------
4 files changed, 110 insertions(+), 90 deletions(-)

diff --git a/site/md/blurb.templ.md b/site/md/blurb.templ.md @@ -0,0 +1,9 @@ +i'm massimo, a software dev based in southern oregon. i've worked at +various startups ([sigma&nbsp;computing](https://sigmacomputing.com), +[disqus](https://disqus.com), +[magnifi](https://www.linkedin.com/company/magnififm), +[music&nbsp;putty](https://musicputty.com)) doing front end web development. + +lately, i've been making audio/visual web apps and tools for learning +guitar. + diff --git a/site/style.templ.css b/site/style.templ.css @@ -2,7 +2,7 @@ --dark-bg: #1d2c3a; --dark-fg: #acbdcf; --dark-link: white; - + --light-bg: #def0ff; --light-fg: #455564; --light-link: black; @@ -10,7 +10,6 @@ --bg: var(--light-bg); --fg: var(--light-fg); --link: var(--light-link); - } @media (prefers-color-scheme: dark) { @@ -31,14 +30,16 @@ html { font-size: 20px; color: var(--fg); background: var(--bg); - font-family: Verdana, Geneva, sans-serif; + font-family: + Courier New, + monospace; } body { box-sizing: border-box; line-height: 1.7; margin: 0px auto; - max-width: 35rem; + max-width: 40rem; min-height: 100vh; padding: 0.75rem 0.75rem 10rem 0.75rem; position: relative; @@ -62,11 +63,16 @@ a { margin: 2rem 0 1rem; } -.md p, .md ul, .md ol { +.md p, +.md ul, +.md ol { margin-top: 0; } -h1 > a, h2 > a, h3 > a, h4 > a { +h1 > a, +h2 > a, +h3 > a, +h4 > a { color: inherit; text-decoration: none; position: relative; @@ -135,12 +141,12 @@ h4:hover > a::after { } ul > li { - list-style: url("@(web-root)/shared/assets/spiral-for-light-mode.svg") + list-style: url("@(web-root)/shared/assets/spiral-for-light-mode.svg"); } @media (prefers-color-scheme: dark) { ul > li { - list-style: url("@(web-root)/shared/assets/spiral-for-dark-mode.svg") + list-style: url("@(web-root)/shared/assets/spiral-for-dark-mode.svg"); } } @@ -152,7 +158,6 @@ ul > li { .color-synth .samples > * { flex: auto; min-width: 1px; - max-width: 8rem; margin: 0 0 0.5rem 0.5rem; border-radius: 0.2rem; } @@ -171,7 +176,7 @@ ul > li { .color-synth .samples > * { max-width: calc(50% - 0.25rem); } - .color-synth .samples > *:nth-child(2n+1) { + .color-synth .samples > *:nth-child(2n + 1) { margin-left: 0; } } @@ -189,10 +194,11 @@ ul > li { .gradient-swatch { height: 50px; - width: 100px; + width: 100px; } -picture, picture img { +picture, +picture img { max-width: 100%; } @@ -202,7 +208,7 @@ header span:last-child img { } :root { - --world-size: 30px; + --world-size: 60px; } #the-world { @@ -215,8 +221,22 @@ header span:last-child img { transition: transform 5s ease-out; } +p:first-child { + margin-top: 0; +} + +header.home-header { + display: flex; + justify-content: center; + padding: 1rem 0 1.75rem; +} + .header-home:not(:last-child) { - --world-size: 20px; + --world-size: 30px; +} + +header { + line-height: 1.4; } header a { @@ -224,13 +244,12 @@ header a { align-items: center; } -.header-home { - margin-left: calc(-0.5rem - 20px); +.header-home #contains-the-world { + position: absolute; + right: 100%; } #contains-the-world { - margin-top: 0.3rem; - margin-right: 0.5rem; display: inline-block; width: var(--world-size); height: var(--world-size); @@ -238,47 +257,37 @@ header a { } @media (max-width: 600px) { - .header-home { - margin-left: calc(-0.5rem - 40px); - } :root { --world-size: 60px; } .header-home:not(:last-child) { - margin-left: calc(-0.5rem - 30px); - } - .header-home:not(:last-child) { --world-size: 40px; } } @font-face { font-family: "Playfair Display"; - src: - local("Playfair Display"), + src: local("Playfair Display"), url("@(web-root)/shared/fonts/PlayfairDisplay-VariableFont_wght.ttf"); } @font-face { font-family: "Atkinson Hyperlegible"; - src: - local("Atkinson Hyperlegible"), + src: local("Atkinson Hyperlegible"), url("@(web-root)/shared/fonts/Atkinson-Hyperlegible-Regular-102.ttf"); } @font-face { font-family: "Atkinson Hyperlegible"; font-weight: 500 900; - src: - local("Atkinson Hyperlegible Bold"), + src: local("Atkinson Hyperlegible Bold"), url("@(web-root)/shared/fonts/Atkinson-Hyperlegible-Bold-102.ttf"); } @font-face { font-family: "Atkinson Hyperlegible"; font-style: oblique; - src: - local("Atkinson Hyperlegible Italic"), + src: local("Atkinson Hyperlegible Italic"), url("@(web-root)/shared/fonts/Atkinson-Hyperlegible-Italic-102.ttf"); } @@ -286,7 +295,6 @@ header a { font-family: "Atkinson Hyperlegible"; font-weight: 500 900; font-style: oblique; - src: - local("Atkinson Hyperlegible Bold Italic"), + src: local("Atkinson Hyperlegible Bold Italic"), url("@(web-root)/shared/fonts/Atkinson-Hyperlegible-BoldItalic-102.ttf"); } diff --git a/src/site.clj b/src/site.clj @@ -85,7 +85,7 @@ (list [:span {:class "header-home"} (mw-anchor :home - (fn [txt] (list the-world [:span {:class "home-anchor-text"} txt]))) + (fn [_] (list the-world [:span {:class "home-anchor-text"} "home"]))) (when crumbs [:span {:class "crumb-interposer"} svg-arrow])]) (map (fn [x] [:span x [:span {:class "crumb-interposer"} svg-arrow]]) (butlast crumbs)) @@ -131,7 +131,10 @@ (defpage :home {:path ["index.html"] :title "massi world" :desc "a website"} - (header) + [:header {:class "home-header"} + (mw-anchor :home (fn [_] (list (h/raw "massi&nbsp;") the-world (h/raw "&nbsp;world"))))] + [:section + (core/md "site/md/blurb.templ.md")] [:section [:ul [:li [:a {:href "https://git.massi.world"} "git"]] diff --git a/ts/the-world.ts b/ts/the-world.ts @@ -1,6 +1,8 @@ document.addEventListener("DOMContentLoaded", () => { - const siblingEl = document.querySelector(".home-anchor-text") as HTMLSpanElement; - const worldEl = document.querySelector("#the-world") as HTMLSpanElement; + const containerEl = document.querySelector( + "#contains-the-world", + ) as HTMLSpanElement; + const worldEl = document.querySelector("#the-world") as HTMLDivElement; const spriteWidth = worldEl.getBoundingClientRect().width; const initForce = 1; const maxVelocity = 100; @@ -14,32 +16,35 @@ document.addEventListener("DOMContentLoaded", () => { // targets 3 sprite frames per sec const steadyIncrease = (degreesInFrame * 3) / fps; - + const xOffset = (frame: number) => { return frame * spriteWidth; - } + }; let rotation = 0; // in degrees let frame = 0; let velocity = 0; - const physicsTime = 10_000; - const esplodeTime = 3_000; + const physicsTime = 3_000; + const esplodeTime = 100_000; const isTimeFor = (ts, tTimer, tgtTime) => { return ts - tTimer > tgtTime; - } - + }; + const drag = (v: number) => Math.max(v / 10, 0.005 * v * v); const updatePosition = (v = velocity) => { rotation = (rotation + v) % degreesInRotation; frame = Math.floor(rotation / degreesInFrame); - } + }; const updateVelocity = (deltaV: number) => { - velocity = Math.min(maxVelocity, velocity + deltaV - drag(Math.round(velocity))); - } + velocity = Math.min( + maxVelocity, + velocity + deltaV - drag(Math.round(velocity)), + ); + }; const physicsTick = (isHovering: boolean) => { updateVelocity(isHovering ? force : 0); @@ -47,62 +52,61 @@ document.addEventListener("DOMContentLoaded", () => { if (isHovering) { force += accel; - } - else { + } else { force = initForce; } if (velocity > 45) { shakeTick(); - } - else { + } else { resetShake(); } - + updateFrame(); - } + }; const steadyTick = (isHovering: boolean) => { if (isHovering) { updatePosition(steadyIncrease); updateFrame(); } - } + }; const updateFrame = () => { worldEl.style.backgroundPositionX = `${xOffset(frame)}px`; - } + }; + + const rBigPos = () => + (Math.random() > 0.5 ? 1 : -1) * (2000 + Math.random() * 2000); - const rBigPos = () => (Math.random() > 0.5 ? 1 : -1) * (2000 + Math.random() * 2000); - const esplode = () => { - console.log('boom!'); + console.log("boom!"); const pos = worldEl.getBoundingClientRect(); worldEl.style.position = "fixed"; worldEl.style.top = pos.y + "px"; - worldEl.style.left = pos.x + "px"; - const dest = `translate(${rBigPos()}px, ${rBigPos()}px) scale(${Math.random() > 0.5 ? 20 : 0.001 })` + worldEl.style.left = pos.x + "px"; + const dest = `translate(${rBigPos()}px, ${rBigPos()}px) scale(${Math.random() > 0.5 ? 20 : 0.001})`; worldEl.style.transform = dest; - } + }; let shakeDir = 1; let shakeTimer: number | null = null; const shakeTick = () => { if (!shakeTimer) { shakeTimer = setTimeout(() => { - esplode(); + esplode(); }, esplodeTime); } shakeDir *= -1; worldEl.style.translate = `${shakeDir}px`; - } + }; const resetShake = () => { if (shakeTimer !== null) { clearTimeout(shakeTimer); } worldEl.style.translate = ""; - } + }; let t = -Infinity; let tPhysics: number | null = null; @@ -112,51 +116,47 @@ document.addEventListener("DOMContentLoaded", () => { if (!doAnimation) { return; } - + if (!tPhysics) { tPhysics = timestamp; } if (isTimeFor(timestamp, t, tickTime)) { - t = timestamp; - + t = timestamp; const worldHovering = worldEl.matches(":hover"); - const textHovering = siblingEl.matches(":hover"); + const textHovering = containerEl.matches(":hover"); const isHovering = worldHovering || textHovering; // physics timer only run while hovering on world. if (!worldHovering) { - tPhysics = timestamp; + tPhysics = timestamp; } - inPhysics = (worldHovering && isTimeFor(timestamp, tPhysics, physicsTime)) || velocity > 0.5; - - if (!inPhysics && !isHovering) { - doAnimation = false; - return; - } - + inPhysics = + (worldHovering && isTimeFor(timestamp, tPhysics, physicsTime)) || + velocity > 0.5; + + // if (!inPhysics && !isHovering) { + // doAnimation = false; + // return; + // } + if (!inPhysics) { - steadyTick(isHovering); - } - else { - physicsTick(worldHovering); + steadyTick(true); + } else { + physicsTick(worldHovering); } } requestAnimationFrame(animate); - } + }; - worldEl.addEventListener("mouseenter", () => { - if (!doAnimation) { - doAnimation = true; - animate(); - } - }) + doAnimation = true; + animate(); - siblingEl.addEventListener("mouseenter", () => { + containerEl.addEventListener("mouseenter", () => { if (!doAnimation) { doAnimation = true; animate(); - } - }) + } + }); });