commit a7df5a25d9007831ec6bec7609c1558ff869af47
parent be41cccaa62cb9d2d4a6867cec2ce3952cf318c3
Author: massi <git@massi.world>
Date: Fri, 30 Aug 2024 04:27:40 -0700
homepage header and blurb
Diffstat:
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 computing](https://sigmacomputing.com),
+[disqus](https://disqus.com),
+[magnifi](https://www.linkedin.com/company/magnififm),
+[music 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 ") the-world (h/raw " 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();
- }
- })
+ }
+ });
});