Top Tweets for #f5f3ed
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#f5f3ed">
<title>Revolving pill · A study in depth</title>
<style>
:root { color-scheme: light; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; color: #36362f; background: #f5f3ed; }
* { box-sizing: border-box; }
body { margin: 0; min-height: 100svh; display: grid; place-items: center; }
button, input { font: inherit; }
button { -webkit-tap-highlight-color: transparent; }
main { width: min(880px, 100%); padding: 52px 32px 28px; }
header { display: flex; justify-content: space-between; align-items: start; gap: 20px; }
.eyebrow { display: flex; align-items: center; gap: 8px; margin: 0 0 14px; font-size: 10px; font-weight: 600; letter-spacing: .15em; text-transform: uppercase; color: #77796d; }
.dot { width: 6px; height: 6px; border-radius: 50%; background: #b18b34; }
h1 { margin: 0; font-size: clamp(27px, 4vw, 36px); letter-spacing: -.045em; font-weight: 500; }
.subtitle { margin: 12px 0 0; font-size: 13px; line-height: 1.6; color: #77796d; }
.stage { height: 400px; position: relative; display: grid; place-items: center; margin-top: 20px; }
.scene { width: 100%; height: 100%; position: absolute; inset: 0; display: block; pointer-events: none; }
.shadow { position: absolute; width: 300px; height: 32px; top: calc(50% + 97px); left: calc(50% - 150px); background: radial-gradient(ellipse, #69501c38, #69501c0b 55%, transparent 73%); filter: blur(9px); pointer-events: none; }
.hit { position: absolute; width: 100%; height: calc(100% - 32px); top: 0; left: 0; background: transparent; border: 0; border-radius: 32px; cursor: grab; touch-action: pan-y; user-select: none; }
.hit:active { cursor: grabbing; }
.hit:focus-visible { outline: 2px solid #9a783b; outline-offset: 8px; }
.hint { position: absolute; bottom: 10px; margin: 0; color: #88897d; font-size: 11px; letter-spacing: .015em; }
.hint span { margin: 0 7px; color: #b7b6aa; }
.controls { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: center; gap: 25px 32px; border-top: 1px solid #ddded3; border-bottom: 1px solid #ddded3; padding: 23px 0; }
.field label { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 12px; margin-bottom: 13px; }
output { color: #858679; font: 11px ui-monospace, SFMono-Regular, monospace; }
input[type="range"] { appearance: none; -webkit-appearance: none; display: block; width: 100%; height: 16px; margin: 0; background: transparent; accent-color: #a98534; cursor: pointer; }
input[type="range"]::-webkit-slider-runnable-track { height: 3px; background: #d4d5c8; border-radius: 3px; }
input[type="range"]::-webkit-slider-thumb { appearance: none; -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: #a98534; border: 2px solid #f5f3ed; box-shadow: 0 0 0 1px #a98534; margin-top: -4.5px; }
input[type="range"]::-moz-range-track { height: 3px; background: #d4d5c8; border-radius: 3px; }
input[type="range"]::-moz-range-thumb { width: 9px; height: 9px; border-radius: 50%; background: #a98534; border: 2px solid #f5f3ed; box-shadow: 0 0 0 1px #a98534; }
input:focus-visible { outline: 2px solid #9a783b; outline-offset: 5px; }
.actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: center; grid-column: 1 / -1; }
.control-button { background: #eeede4; border: 1px solid #d8dacd; color: #515447; height: 40px; padding: 0 15px; border-radius: 7px; font-size: 12px; cursor: pointer; display: inline-flex; gap: 8px; justify-content: center; align-items: center; }
.control-button:hover { background: #e5e6da; border-color: #c1c3b1; }
.control-button:focus-visible { outline: 2px solid #9a783b; outline-offset: 3px; }
#toggle { min-width: 94px; }
#toggle svg { width: 12px; height: 12px; fill: currentColor; }
footer { display: flex; justify-content: space-between; gap: 20px; margin-top: 19px; font-size: 10px; line-height: 1.5; color: #999a8f; }
footer a { color: inherit; text-decoration-color: #c5c6bb; text-underline-offset: 3px; }
footer a:hover { color: #676a5d; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
@media (max-width: 600px) { main { padding: 32px 24px 24px; } .stage { height: 330px; margin-top: 8px; } .controls { grid-template-columns: 1fr 1fr; gap: 24px; } footer { flex-direction: column; gap: 6px; text-align: center; } .shadow { top: calc(50% + 75px); } }
</style>
</head>
<body>
<main>
<header>
<div>
<p class="eyebrow"><span class="dot"></span>A study in depth</p>
<h1>A little more dimension.</h1>
<p class="subtitle">A pill with two faces and a solid, curved edge.</p>
</div>
</header>
<div class="stage" id="stage">
<div class="shadow" id="shadow" aria-hidden="true"></div>
<canvas class="scene" id="pill-canvas" aria-hidden="true"></canvas>
<button type="button" class="hit" id="pill" aria-label="Play revolving pill" aria-describedby="instructions keyboard-help"></button>
<p class="hint" id="instructions">Drag left or right<span>·</span>Click to play</p>
<p id="render-error" hidden></p>
<p class="sr-only" id="keyboard-help">Left and Right arrow keys revolve the pill. Enter or Space plays or pauses. Home resets the view.</p>
</div>
<div class="controls" aria-label="Animation controls">
<div class="field">
<label for="depth">Thickness <output id="depth-value" for="depth">44 px</output></label>
<input id="depth" type="range" min="8" max="80" step="1" value="44">
</div>
<div class="field">
<label for="roundness">Edge roundness <output id="roundness-value" for="roundness">65%</output></label>
<input id="roundness" type="range" min="0" max="100" step="1" value="65" aria-describedby="roundness-help">
<span class="sr-only" id="roundness-help">Zero is a flat side wall. One hundred is a fully rounded edge.</span>
</div>
<div class="actions">
<button type="button" class="control-button" id="toggle"><svg viewBox="0 0 12 12" aria-hidden="true"><path d="M3 1l8 5-8 5z"/></svg><span>Play</span></button>
<button type="button" class="control-button" id="edge" title="Inspect the thickness from the side">Side view</button>
<button type="button" class="control-button" id="reset">Reset view</button>
</div>
</div>
<footer>
<span>A single HTML file. No libraries.</span>
<a href="https://t.co/e9UpQNp6j2" target="_blank" rel="noopener noreferrer">Inspired by Pillar’s original ↗</a>
</footer>
<p class="sr-only" id="status" role="status"></p>
<noscript><p>This demo needs JavaScript to construct the curved edge and animate the pill.</p></noscript>
</main>
<script>
// Dependency-free WebGL 1 renderer. Angles passed to render() are degrees.
class GoldPillRenderer {
constructor(canvas) {
this.canvas = canvas;
const gl = canvas.getContext('webgl', {
alpha: true, antialias: true, premultipliedAlpha: true, depth: true
});
if (!gl) throw new Error('This 3D pill requires WebGL. Enable hardware acceleration or open it in a browser with WebGL support.');
https://t.co/G0OaljFJrW = gl;
const vertexSource = `
attribute vec3 aPosition;
attribute vec3 aNormal;
attribute vec2 aUV;
attribute float aLabel;
uniform mat3 uRotation;
uniform mat4 uProjection;
varying vec3 vNormal;
varying vec3 vPosition;
varying vec2 vUV;
varying float vLabel;
void main() {
vec3 p = uRotation * aPosition;
vPosition = p;
vNormal = uRotation * aNormal;
vUV = aUV;
vLabel = aLabel;
gl_Position = uProjection * vec4(p + vec3(0.0, 0.0, -1000.0), 1.0);
gl_Position.y += 0.08 * gl_Position.w;
}
`;
const fragmentSource = `
precision mediump float;
uniform sampler2D uLabels;
varying vec3 vNormal;
varying vec3 vPosition;
varying vec2 vUV;
varying float vLabel;
void main() {
vec3 n = normalize(vNormal);
vec3 light = normalize(vec3(-0.42, 0.64, 1.0));
vec3 eye = normalize(vec3(0.0, 0.0, 1000.0) - vPosition);
vec3 halfway = normalize(light + eye);
float diffuse = max(dot(n, light), 0.0);
float highlight = pow(max(dot(n, halfway), 0.0), 34.0);
// One yellow-gold material covers the faces and the entire rim.
vec3 color = vec3(0.980, 0.760, 0.140);
color *= 0.97 + 0.03 * diffuse;
color += vec3(1.0, 0.95, 0.80) * highlight * 0.075;
if (vLabel > 0.5) {
float ink = texture2D(uLabels, vUV).a;
color = mix(color, vec3(0.395, 0.255, 0.075) * (0.95 + diffuse * 0.05), ink);
}
gl_FragColor = vec4(clamp(color, 0.0, 1.0), 1.0);
}
`;
const compile = (type, source) => {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
const message = gl.getShaderInfoLog(shader);
gl.deleteShader(shader);
throw new Error(`The 3D pill shader could not compile: ${message}`);
}
return shader;
};
const vs = compile(gl.VERTEX_SHADER, vertexSource);
const fs = compile(gl.FRAGMENT_SHADER, fragmentSource);
this.program = gl.createProgram();
gl.attachShader(this.program, vs);
gl.attachShader(this.program, fs);
gl.linkProgram(this.program);
gl.deleteShader(vs);
gl.deleteShader(fs);
if (!gl.getProgramParameter(this.program, https://t.co/WeEG7XKfny_STATUS)) {
throw new Error(`The 3D pill renderer could not start: ${gl.getProgramInfoLog(this.program)}`);
}
gl.useProgram(this.program);
this.uniforms = {};
for (const name of ['uRotation', 'uProjection', 'uLabels']) {
this.uniforms[name] = gl.getUniformLocation(this.program, name);
}
this.vertexBuffer = gl.createBuffer();
this.indexBuffer = gl.createBuffer();
this.attributes = [
['aPosition', 3, 0], ['aNormal', 3, 12], ['aUV', 2, 24], ['aLabel', 1, 32]
].map(([name, size, offset]) => [gl.getAttribLocation(this.program, name), size, offset]);
this.texture = gl.createTexture();
this.labelCanvas = document.createElement('canvas');
this.labelCanvas.width = 1024;
this.labelCanvas.height = 256;
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.enable(gl.CULL_FACE);
gl.cullFace(gl.BACK);
gl.frontFace(gl.CCW);
gl.clearColor(0, 0, 0, 0);
this.angle = 25;
this.setShape(44, 0.65);
this.resize();
}
setShape(depth, roundness) {
depth = Number(depth);
roundness = Number(roundness);
if (!Number.isFinite(depth) || !Number.isFinite(roundness)) throw new Error('Pill depth and roundness must be finite numbers.');
this.depth = Math.max(8, Math.min(80, depth));
this.roundness = Math.max(0, Math.min(1, roundness));
const d = this.depth, bevel = this.roundness * d / 2;
const radius = 56, centerX = 124, arcSegments = 48, bevelSegments = 16;
const perimeter = [];
for (const side of [1, -1]) {
for (let i = 0; i <= arcSegments; i++) {
const a = -Math.PI / 2 + (side === -1 ? Math.PI : 0) + i * Math.PI / arcSegments;
perimeter.push({center: side * centerX, nx: Math.cos(a), ny: Math.sin(a)});
}
}
// Each profile entry is [inset, z, radial normal, axial normal].
const profile = [];
const addRing = (inset, z, radial, axial) => {
const previous = profile[profile.length - 1];
if (previous && Math.abs(previous[0] - inset) < 1e-8 && Math.abs(previous[1] - z) < 1e-8) return;
profile.push([inset, z, radial, axial]);
};
if (bevel < 1e-6) {
addRing(0, -d / 2, 1, 0);
// A middle ring makes the symmetric material gradient well sampled.
addRing(0, 0, 1, 0);
addRing(0, d / 2, 1, 0);
} else {
for (let i = 0; i <= bevelSegments; i++) {
const a = i * Math.PI / (2 * bevelSegments);
addRing(bevel * (1 - Math.sin(a)), -d / 2 + bevel * (1 - Math.cos(a)), Math.sin(a), -Math.cos(a));
}
if (d / 2 - bevel > 1e-8) addRing(0, 0, 1, 0);
for (let i = 0; i <= bevelSegments; i++) {
const a = i * Math.PI / (2 * bevelSegments);
addRing(bevel * (1 - Math.cos(a)), d / 2 - bevel + bevel * Math.sin(a), Math.cos(a), Math.sin(a));
}
}
const vertices = [], indices = [], count = perimeter.length;
const vertex = (x, y, z, nx, ny, nz, u = 0, v = 0, label = 0) => {
const index = vertices.length / 9;
vertices.push(x, y, z, nx, ny, nz, u, v, label);
return index;
};
for (const [inset, z, nr, nz] of profile) {
for (const p of perimeter) {
vertex(https://t.co/PAz0QaNZeO + (radius - inset) * p.nx, (radius - inset) * p.ny, z, p.nx * nr, p.ny * nr, nz);
}
}
for (let row = 0; row < profile.length - 1; row++) {
for (let i = 0; i < count; i++) {
const next = (i + 1) % count;
const a = row * count + i, b = row * count + next;
const c = (row + 1) * count + next, e = (row + 1) * count + i;
indices.push(a, b, c, a, c, e);
}
}
const faceWidth = 360 - 2 * bevel, faceHeight = 112 - 2 * bevel;
for (const side of [-1, 1]) {
const z = side * d / 2;
const center = vertex(0, 0, z, 0, 0, side, side === 1 ? 0.25 : 0.75, 0.5, 1);
const edge = [];
// Copy exact boundary coordinates from the corresponding side ring.
const ringOffset = (side === -1 ? 0 : profile.length - 1) * count * 9;
for (let i = 0; i < count; i++) {
const offset = ringOffset + i * 9;
const x = vertices[offset], y = vertices[offset + 1], exactZ = vertices[offset + 2];
const u = side === 1 ? (x / faceWidth + 0.5) * 0.5 : 0.5 + (0.5 - x / faceWidth) * 0.5;
edge.push(vertex(x, y, exactZ, 0, 0, side, u, y / faceHeight + 0.5, 1));
}
for (let i = 0; i < count; i++) {
const next = (i + 1) % count;
if (side === 1) indices.push(center, edge[i], edge[next]);
else indices.push(center, edge[next], edge[i]);
}
}
const gl = https://t.co/G0OaljFJrW;
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
this.indexCount = indices.length;
this.updateLabels(faceWidth, faceHeight);
}
updateLabels(faceWidth, faceHeight) {
const canvas = this.labelCanvas, ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Fixed in model space: changing thickness or roundness never resizes text.
const fontSize = 35;
for (let i = 0; i < 2; i++) {
https://t.co/B8EUo1L4cb();
ctx.translate(i * 512 + 256, 128);
ctx.scale(512 / faceWidth, 256 / faceHeight);
ctx.fillStyle = '#ffffff';
ctx.font = `bold ${fontSize}px Georgia, "Times New Roman", serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(i === 0 ? 'FRONT' : 'BACK', 0, 1);
ctx.restore();
}
const gl = https://t.co/G0OaljFJrW;
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
gl.generateMipmap(gl.TEXTURE_2D);
}
resize() {
const rect = this.canvas.getBoundingClientRect();
this.cssWidth = Math.max(1, rect.width);
this.cssHeight = Math.max(1, rect.height);
const dpr = Math.min(2, window.devicePixelRatio || 1);
const width = Math.max(1, Math.round(this.cssWidth * dpr));
const height = Math.max(1, Math.round(this.cssHeight * dpr));
if (this.canvas.width !== width || this.canvas.height !== height) {
this.canvas.width = width;
this.canvas.height = height;
}
// A little angular clearance keeps the maximum-depth pill inside the stage.
const scale = Math.min(1, Math.max(1, this.cssWidth - 24) / 380);
const focal = 1000 * scale, near = 10, far = 3000;
this.projection = new Float32Array([
2 * focal / this.cssWidth, 0, 0, 0,
0, 2 * focal / this.cssHeight, 0, 0,
0, 0, (far + near) / (near - far), -1,
0, 0, 2 * far * near / (near - far), 0
]);
this.render(this.angle);
}
render(angle) {
this.angle = Number.isFinite(angle) ? angle : this.angle;
if (!this.projection || https://t.co/G0OaljFJrW.isContextLost()) return;
const gl = https://t.co/G0OaljFJrW, a = this.angle * Math.PI / 180, t = 12 * Math.PI / 180;
const ca = Math.cos(a), sa = Math.sin(a), ct = Math.cos(t), st = Math.sin(t);
const rotation = new Float32Array([ca, st * sa, -ct * sa, 0, ct, st, sa, -st * ca, ct * ca]);
gl.viewport(0, 0, this.canvas.width, this.canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.useProgram(this.program);
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
for (const [location, size, offset] of this.attributes) {
gl.enableVertexAttribArray(location);
gl.vertexAttribPointer(location, size, gl.FLOAT, false, 36, offset);
}
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.uniform1i(this.uniforms.uLabels, 0);
gl.uniformMatrix3fv(this.uniforms.uRotation, false, rotation);
gl.uniformMatrix4fv(this.uniforms.uProjection, false, this.projection);
gl.drawElements(gl.TRIANGLES, this.indexCount, gl.UNSIGNED_SHORT, 0);
}
}
const $ = id => document.getElementById(id);
const pill = $('pill');
const reducedMotion = matchMedia('(prefers-reduced-motion: reduce)');
let depth = 44, roundness = .65, angle = 25;
let playing = false, pointer = null, dragged = false;
let frameId = 0, lastTime = null, meshDirty = false;
let renderer;
try {
renderer = new GoldPillRenderer($('pill-canvas'));
} catch (error) {
$('status').textContent = error.message;
$('render-error').hidden = false;
$('render-error').textContent = 'This 3D demo needs WebGL enabled in your browser.';
}
function updateShape() {
renderer?.setShape(depth, roundness);
$('depth-value').value = `${depth} px`;
$('depth').setAttribute('aria-valuetext', `${depth} pixels`);
const percent = Math.round(roundness * 100);
$('roundness-value').value = percent === 0 ? 'Flat' : percent === 100 ? 'Rounded' : `${percent}%`;
$('roundness').setAttribute('aria-valuetext', `${percent} percent. ${percent === 0 ? 'Flat edge.' : percent === 100 ? 'Fully rounded edge.' : ''}`);
}
function render() {
renderer?.render(angle);
const scale = Math.min(1, ($('stage').clientWidth - 24) / 420);
const width = 300 * scale;
Object.assign($('shadow').style, {
width: `${width}px`, left: `calc(50% - ${width / 2}px)`,
transform: `scaleX(${.3 + .7 * Math.abs(Math.cos(angle * Math.PI / 180))})`
});
}
function frame(time) {
frameId = 0;
if (meshDirty) { meshDirty = false; updateShape(); }
if (playing && !pointer && !document.hidden) {
if (lastTime !== null) angle = (angle + Math.min(time - lastTime, 50) * .045) % 360;
lastTime = time;
} else lastTime = null;
render();
if (playing && !pointer && !document.hidden) frameId = requestAnimationFrame(frame);
}
function requestRender(rebuild = false) {
meshDirty ||= rebuild;
if (!frameId) frameId = requestAnimationFrame(frame);
}
function setPlaying(value, announce = false) {
playing = value;
lastTime = null;
$('toggle').querySelector('span').textContent = playing ? 'Pause' : 'Play';
$('toggle').querySelector('path').setAttribute('d', playing ? 'M2 1h3v10H2zm5 0h3v10H7z' : 'M3 1l8 5-8 5z');
pill.setAttribute('aria-label', playing ? 'Pause revolving pill' : 'Play revolving pill');
$('instructions').innerHTML = `Drag left or right<span>·</span>Click to ${playing ? 'pause' : 'play'}`;
if (announce) $('status').textContent = playing ? 'Rotation playing.' : 'Rotation paused.';
requestRender();
}
$('depth').addEventListener('input', e => { depth = Number(https://t.co/ZnGOrOtyEq.value); requestRender(true); });
$('roundness').addEventListener('input', e => { roundness = Number(https://t.co/ZnGOrOtyEq.value) / 100; requestRender(true); });
$('toggle').addEventListener('click', () => setPlaying(!playing, true));
$('edge').addEventListener('click', () => {
setPlaying(false); angle = 90; requestRender();
$('status').textContent = `Side view. The pill is ${depth} pixels thick.`;
});
function resetView() {
setPlaying(false); angle = 25; requestRender();
$('status').textContent = 'View reset.';
}
$('reset').addEventListener('click', resetView);
pill.addEventListener('click', e => {
if (!dragged || e.detail === 0) setPlaying(!playing, true);
dragged = false;
});
pill.addEventListener('pointerdown', e => {
if (!e.isPrimary || e.button !== 0) return;
pointer = { id: e.pointerId, x: e.clientX, angle };
dragged = false;
lastTime = null;
pill.setPointerCapture(e.pointerId);
});
pill.addEventListener('pointermove', e => {
if (!pointer || e.pointerId !== https://t.co/tOZLX2d4bb) return;
const dx = e.clientX - pointer.x;
if (!dragged && Math.abs(dx) > 4) { dragged = true; setPlaying(false); }
if (dragged) { angle = pointer.angle + dx * .65; requestRender(); }
});
function releasePointer(e) {
if (!pointer || e.pointerId !== https://t.co/tOZLX2d4bb) return;
pointer = null;
lastTime = null;
if (pill.hasPointerCapture(e.pointerId)) pill.releasePointerCapture(e.pointerId);
requestRender();
}
pill.addEventListener('pointerup', releasePointer);
pill.addEventListener('pointercancel', releasePointer);
pill.addEventListener('lostpointercapture', releasePointer);
pill.addEventListener('keydown', e => {
if (e.key === 'Home') { e.preventDefault(); resetView(); return; }
if (!['ArrowLeft', 'ArrowRight'].includes(e.key)) return;
e.preventDefault(); setPlaying(false);
angle += e.key === 'ArrowLeft' ? -10 : 10;
requestRender();
});
new ResizeObserver(() => { renderer?.resize(); requestRender(); }).observe($('stage'));
document.addEventListener('visibilitychange', () => { lastTime = null; requestRender(); });
reducedMotion.addEventListener('change', e => { if (e.matches) setPlaying(false); });
updateShape();
setPlaying(false);
render();
</script>
</body>
</html>
@w_s_bitcoin Hey Wicked, I’m trying to make the 3d revolving effect using html/css/js but my element lacks depth making it look flat/2d when spinning. Any advice how to make it look more 3d? Thanks man
🪨🍰D_14
#F5F3ED🤍 & #OB0004🖤
#라키 #박민혁 #朴敏赫 #ROCKY @p_rockyent @onefinedayent
#ROCKY_0225시간Challenge ❤️🔥

Last Seen Hashtags on Sotwe
val2legit
Seen from Turkey
男娘
Seen from Netherlands
minichatt video()*************************
Seen from Brazil
รับงานพิจิตร
Seen from Thailand
Ghostsoap
Seen from Malaysia
anxiouspandaa
Seen from Italy
anxiouspanda filter:videos since:2026-10-17
Seen from United Kingdom
ngentodcrot
Seen from Germany
graphart
Seen from Indonesia
ايفا
Seen from Singapore
Trends for you
Most Popular Users

Elon Musk 
@elonmusk
241.5M followers

Barack Obama 
@barackobama
118.8M followers

Cristiano Ronaldo 
@cristiano
114.5M followers

Donald J. Trump 
@realdonaldtrump
111.9M followers

Narendra Modi 
@narendramodi
107.1M followers

Rihanna 
@rihanna
98.7M followers

NASA 
@nasa
92.3M followers

Justin Bieber 
@justinbieber
91.8M followers

KATY PERRY 
@katyperry
90M followers

Taylor Swift 
@taylorswift13
84M followers

Lady Gaga 
@ladygaga
75.5M followers

Virat Kohli 
@imvkohli
73.5M followers

Kim Kardashian 
@kimkardashian
70.9M followers

YouTube 
@youtube
68.8M followers

Neymar Jr 
@neymarjr
66.5M followers

Bill Gates 
@billgates
65.3M followers

Selena Gomez 
@selenagomez
63.1M followers

The Ellen Show
@theellenshow
62.2M followers

CNN 
@cnn
61.7M followers

X 
@x
60.7M followers


