Brass hummingbird
A giant mint-green SWIFT wordmark with a clockwork hummingbird sprite that flaps, hovers, and darts between letters along curved paths, weaving in front of some letters and behind others.
Assets
Code: MIT license. three.js 0.184.0 (MIT) · Imagery generated with Google Gemini
<!doctype html>
<html lang="en"
><head
><script>
/* 6to9 pattern harness */ (function () {
var parentPaused = false,
hidden = document.hidden,
p = (window.__pattern = { paused: false, reducedMotion: false, maxDpr: 2 });
function sync() {
p.paused = parentPaused || hidden;
}
sync();
try {
p.reducedMotion = matchMedia("(prefers-reduced-motion: reduce)").matches;
} catch (e) {}
document.addEventListener("visibilitychange", function () {
hidden = document.hidden;
sync();
});
addEventListener("message", function (e) {
var d = e.data || {};
if (d.pattern === "pause") {
parentPaused = true;
sync();
}
if (d.pattern === "play") {
parentPaused = false;
sync();
}
});
})();</script
><meta charset="utf-8" /><meta
name="viewport"
content="width=device-width,initial-scale=1"
/><title>Swift — clockwork hummingbird</title
><style>
html,
body {
margin: 0;
height: 100%;
background: #9fe8c1;
overflow: hidden;
}
.hero {
position: relative;
width: 100vw;
height: 100vh;
height: 100svh;
overflow: hidden;
background: radial-gradient(120% 90% at 50% 40%, #aef2cb 0%, #9fe8c1 55%, #8fdcb3 100%);
font-family: "Helvetica Neue", Arial, system-ui, sans-serif;
color: #0d3b2a;
}
.word {
position: absolute;
left: 0;
right: 0;
top: 44%;
transform: translateY(-50%);
text-align: center;
font-family: "Arial Black", "Helvetica Neue", Impact, system-ui, sans-serif;
font-weight: 900;
font-size: min(28vw, 60vh);
line-height: 0.82;
letter-spacing: -0.05em;
white-space: nowrap;
margin: 0;
user-select: none;
-webkit-user-select: none;
}
.word span {
display: inline-block;
}
.back {
z-index: 1;
}
.front {
z-index: 3;
pointer-events: none;
}
.front .o {
color: transparent;
}
canvas {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 2;
display: block;
pointer-events: none;
}
.m {
display: none;
}
.nav {
position: absolute;
z-index: 4;
left: 0;
right: 0;
top: 0;
display: flex;
justify-content: space-between;
align-items: center;
padding: 22px 5vw;
font-size: 14px;
font-weight: 700;
letter-spacing: 0.14em;
text-transform: uppercase;
}
.nav a {
color: inherit;
text-decoration: none;
opacity: 0.8;
}
.info {
position: absolute;
z-index: 4;
left: 0;
right: 0;
bottom: 6vh;
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
text-align: center;
padding: 0 6vw;
}
.info p {
margin: 0;
font-size: clamp(15px, 1.5vw, 20px);
font-weight: 600;
max-width: 34ch;
line-height: 1.35;
}
.btn {
appearance: none;
border: 0;
background: #0d3b2a;
color: #c9f7dd;
font:
700 15px system-ui,
sans-serif;
letter-spacing: 0.08em;
text-transform: uppercase;
padding: 15px 30px;
border-radius: 99px;
cursor: pointer;
transition:
transform 0.2s,
background 0.2s;
}
.btn:hover {
transform: translateY(-2px);
background: #145239;
}
.fb {
display: none;
position: absolute;
z-index: 2;
left: 50%;
top: 44%;
width: 90px;
height: 90px;
margin: -45px 0 0 -45px;
border-radius: 50%;
background: radial-gradient(circle at 35% 30%, #ffe9a8, #c9923a 55%, #7a4e16);
box-shadow: 0 0 0 10px rgba(201, 146, 58, 0.25);
animation: fb 2.4s ease-in-out infinite;
}
@keyframes fb {
0%,
100% {
transform: translate(-120px, -20px);
}
50% {
transform: translate(120px, 20px);
}
}
.nogl .fb {
display: block;
}
@media (max-aspect-ratio: 1/1) {
.word {
font-size: 44vw;
top: 40%;
}
.m {
display: block;
height: 0;
}
.nav {
padding: 18px 6vw;
}
}</style
><script type="importmap">
{ "imports": { "three": "https://cdn.jsdelivr.net/npm/three@0.184.0/build/three.module.js" } }
</script></head
><body
><main class="hero nogl" id="hero"
><div class="nav"><span>Brasswing</span><a href="#">Workshop</a></div
><h1 class="word back" id="wb"
><span>S</span><span>W</span><span>I</span><i class="m"></i><span>F</span><span>T</span></h1
><div class="fb"></div
><div class="word front" aria-hidden="true"
><span class="o">S</span><span>W</span><span class="o">I</span><i class="m"></i
><span>F</span><span class="o">T</span></div
><div class="info"
><p>Hand-wound precision that hovers, darts and never misses a beat.</p
><button class="btn">Wind it up</button></div
></main
><script type="module">
import * as THREE from "three";
const P = window.__pattern || { paused: false, reducedMotion: false, maxDpr: 2 };
const hero = document.getElementById("hero");
const letters = Array.prototype.slice.call(document.querySelectorAll("#wb span"));
let renderer = null;
try {
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
} catch (e) {
renderer = null;
}
if (renderer) {
try {
init();
} catch (e) {
hero.classList.add("nogl");
}
}
function init() {
renderer.setClearColor(0x000000, 0);
hero.insertBefore(renderer.domElement, hero.querySelector(".front"));
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(0, 1, 1, 0, -10, 10);
const geo = new THREE.PlaneGeometry(1, 1, 24, 24);
const vs =
"uniform float uTime;uniform vec2 uVel;varying vec2 vUv;void main(){vUv=uv;vec3 p=position;p*=1.0+sin(uTime*3.1)*0.012;p.y+=sin(uTime*2.4)*0.012;p.x+=sin(uv.y*7.0+uTime*5.0)*0.004;p.y+=sin(uv.x*6.0+uTime*4.0)*0.004;p.x-=uVel.x*0.00006*(0.5-uv.y);p.y+=uVel.y*0.00003*(0.5-uv.x)*0.0;p.y-=uVel.y*0.00004*(uv.y-0.5)*0.5;gl_Position=projectionMatrix*modelViewMatrix*vec4(p,1.0);}";
const fs =
"precision highp float;uniform sampler2D map;uniform float uFrame;uniform float uNext;uniform float uMix;varying vec2 vUv;vec4 fr(float f){float i=0.0015;float u=(f+i+vUv.x*(1.0-2.0*i))/8.0;float v=0.004+vUv.y*0.992;return texture2D(map,vec2(u,v));}void main(){vec4 a=fr(uFrame);vec4 b=fr(uNext);float al=mix(a.a,b.a,uMix);vec3 c=(a.rgb*a.a*(1.0-uMix)+b.rgb*b.a*uMix)/max(al,0.001);gl_FragColor=vec4(c,al);}";
const mat = new THREE.ShaderMaterial({
uniforms: {
map: { value: null },
uFrame: { value: 0 },
uNext: { value: 1 },
uMix: { value: 0 },
uTime: { value: 0 },
uVel: { value: new THREE.Vector2() },
},
vertexShader: vs,
fragmentShader: fs,
transparent: true,
depthTest: false,
depthWrite: false,
});
const mesh = new THREE.Mesh(geo, mat);
scene.add(mesh);
let W = 1,
H = 1,
rects = [],
bw = 300,
bh = 290;
let pos = { x: 0, y: 0 },
prev = { x: 0, y: 0 },
vel = { x: 0, y: 0 };
let from = { x: 0, y: 0 },
to = { x: 0, y: 0 },
ctrl = { x: 0, y: 0 };
let phase = "hover",
phaseT = 0,
dur = 1,
hoverDur = 1.5,
seqI = 0,
facing = 1,
facingT = 1,
T = 0,
dirty = true;
const seq = [1, 3, 0, 2, 4, 3, 1, 0, 2, 4];
function rnd(a, b) {
return a + Math.random() * (b - a);
}
function clampPt(p) {
const mx = bw * 0.45,
my = bh * 0.4;
p.x = Math.max(mx, Math.min(W - mx, p.x));
p.y = Math.max(my + 50, Math.min(H * 0.7, p.y));
return p;
}
function target(i) {
const r = rects[i] || { x: W / 2, y: H / 2, w: 50, h: 50 };
return clampPt({ x: r.x + r.w * rnd(0.4, 0.6), y: r.y + r.h * rnd(0.35, 0.55) });
}
function layout() {
W = hero.clientWidth || window.innerWidth;
H = hero.clientHeight || window.innerHeight;
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, P.maxDpr || 2));
renderer.setSize(W, H, false);
const cv = renderer.domElement;
cv.style.width = "100%";
cv.style.height = "100%";
camera.right = W;
camera.top = H;
camera.updateProjectionMatrix();
const hr = hero.getBoundingClientRect();
rects = letters.map(function (el) {
const r = el.getBoundingClientRect();
return { x: r.left - hr.left, y: r.top - hr.top, w: r.width, h: r.height };
});
const portrait = W < H;
bw = portrait ? Math.min(W * 0.62, 420) : Math.min(W * 0.26, H * 0.46);
bh = (bw * 323) / 333;
clampPt(pos);
clampPt(to);
dirty = true;
}
function startMove() {
from = { x: pos.x, y: pos.y };
const i = seq[seqI++ % seq.length];
to = target(i);
const dx = to.x - from.x,
dy = to.y - from.y;
const d = Math.sqrt(dx * dx + dy * dy);
ctrl = {
x: (from.x + to.x) / 2 + rnd(-0.12, 0.12) * W * 0.3 - dy * 0.18,
y: (from.y + to.y) / 2 + rnd(-0.1, 0.1) * H * 0.3 + dx * 0.12,
};
clampPt(ctrl);
dur = Math.max(0.7, Math.min(1.5, (d / Math.max(W, 1)) * 1.8 + 0.5));
phase = "move";
phaseT = 0;
if (Math.abs(dx) > 40) facingT = dx > 0 ? -1 : 1;
}
function update(dt) {
phaseT += dt;
if (phase === "move") {
const u = Math.min(1, phaseT / dur);
const e = u < 0.5 ? 4 * u * u * u : 1 - Math.pow(-2 * u + 2, 3) / 2;
const a = 1 - e;
pos.x = a * a * from.x + 2 * a * e * ctrl.x + e * e * to.x;
pos.y = a * a * from.y + 2 * a * e * ctrl.y + e * e * to.y;
if (u >= 1) {
phase = "hover";
phaseT = 0;
hoverDur = rnd(1.3, 2.3);
}
} else {
pos.x = to.x + Math.sin(T * 1.7) * 6;
pos.y = to.y + Math.sin(T * 2.3) * 5;
if (phaseT > hoverDur) startMove();
}
const ivx = (pos.x - prev.x) / Math.max(dt, 0.001),
ivy = (pos.y - prev.y) / Math.max(dt, 0.001);
vel.x += (ivx - vel.x) * Math.min(1, dt * 8);
vel.y += (ivy - vel.y) * Math.min(1, dt * 8);
prev.x = pos.x;
prev.y = pos.y;
facing += (facingT - facing) * Math.min(1, dt * 10);
}
function render() {
const fps = 14;
const ft = T * fps;
const f = Math.floor(ft);
const m = ft - f;
const sg = facing < 0 ? -1 : 1;
mat.uniforms.uFrame.value = ((f % 8) + 8) % 8;
mat.uniforms.uNext.value = (((f + 1) % 8) + 8) % 8;
mat.uniforms.uMix.value = m * m * (3 - 2 * m);
mat.uniforms.uTime.value = T;
mat.uniforms.uVel.value.set(vel.x * (facing < 0 ? -1 : 1) * sg * sg, vel.y);
mesh.position.set(pos.x, H - pos.y, 0);
mesh.scale.set(bw * facing, bh, 1);
const sp = Math.max(-0.3, Math.min(0.3, Math.abs(vel.x) * 0.0002));
mesh.rotation.z =
-sg * (0.14 + sp) +
Math.max(-0.2, Math.min(0.2, vel.y * 0.0001)) * sg * 0.0 +
-vel.y * 0.00008 * sg;
renderer.render(scene, camera);
}
function still() {
const r = rects[2];
if (r) {
pos.x = r.x + r.w * 0.5;
pos.y = r.y + r.h * 0.4;
} else {
pos.x = W / 2;
pos.y = H * 0.4;
}
clampPt(pos);
prev.x = pos.x;
prev.y = pos.y;
to = { x: pos.x, y: pos.y };
T = 0.12;
vel.x = 0;
vel.y = 0;
render();
}
let last = performance.now();
function loop(now) {
requestAnimationFrame(loop);
const dt = Math.min(0.05, Math.max(0, (now - last) / 1000));
last = now;
if (P.paused) return;
if (P.reducedMotion) {
if (dirty) {
still();
dirty = false;
}
return;
}
T += dt;
update(dt);
render();
}
const loader = new THREE.TextureLoader();
loader.setCrossOrigin("anonymous");
loader.load(
"https://agents-dev.6to9.ai/visuals/3cc24f85de3cde3746f0651b4712f125.png",
function (tex) {
tex.minFilter = THREE.LinearFilter;
tex.magFilter = THREE.LinearFilter;
tex.generateMipmaps = false;
mat.uniforms.map.value = tex;
layout();
pos = { x: W * 0.12, y: H * 0.3 };
clampPt(pos);
prev.x = pos.x;
prev.y = pos.y;
to = { x: pos.x, y: pos.y };
seqI = 0;
startMove();
hero.classList.remove("nogl");
window.addEventListener("resize", layout);
if (document.fonts && document.fonts.ready) {
document.fonts.ready.then(layout);
}
requestAnimationFrame(loop);
},
undefined,
function () {
hero.classList.add("nogl");
},
);
}
</script></body
></html
>
Made by 6to9. Back to all motion patterns.