惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Jina AI
Jina AI
N
Netflix TechBlog - Medium
P
Proofpoint News Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
D
DataBreaches.Net
人人都是产品经理
人人都是产品经理
aimingoo的专栏
aimingoo的专栏
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
月光博客
月光博客
阮一峰的网络日志
阮一峰的网络日志
I
InfoQ
F
Fortinet All Blogs
J
Java Code Geeks
Last Week in AI
Last Week in AI
美团技术团队
大猫的无限游戏
大猫的无限游戏
有赞技术团队
有赞技术团队
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园_首页
量子位
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I Built a Random Wheel Spinner and Learned That Simple To...
Getinfo Toyou · 2026-06-27 · via DEV Community

Getinfo Toyou

The Itch I Needed to Scratch

Every few weeks, someone in a group chat would ask: "How do we decide?" Movie night. Who pays. Which game to play next. And every time, we'd spend more time arguing about how to decide than actually deciding.

I wanted something dead simple. Paste in some options, spin, done. But every tool I found either required an account, threw ads at you, or had so many settings you needed a tutorial. So I built SpinDecide — a free, no-login random wheel spinner that just works.

This post is about why "just works" is deceptively hard to build.


The Stack

I kept it deliberately lean:

  • Vanilla HTML, CSS, and JavaScript — no framework overhead
  • Canvas API for rendering and animating the wheel
  • CSS transitions for UI polish
  • Deployed as a static site — fast, cheap, no server costs

No React. No build pipeline. No dependencies to maintain. The goal was that anyone could open the source and understand it in under ten minutes.


The Technical Challenges (Yes, Even a Spinner Has Them)

1. Making the Spin Feel Real

A wheel that stops abruptly feels broken. A wheel that always decelerates the same way feels fake. Getting the easing curve right took more iteration than I expected.

I ended up using a custom cubic-bezier-style deceleration applied to the rotation delta per frame. The key insight: the perception of randomness matters as much as actual randomness. If the wheel always stops in roughly the same quadrant, users notice — even if the math is correct. I added a random offset to the final resting position so it never felt predictable.

2. Label Rendering on Canvas

Canvas text doesn't wrap. If someone adds a long option like "Hawaiian pizza (controversial but valid)", you either truncate it, shrink the font, or let it overflow the segment.

I implemented dynamic font sizing: measure the text width, compare it to the segment arc length at a given radius, and scale down if needed. It's not perfect for extreme edge cases, but it handles 95% of real-world inputs gracefully without any user intervention.

3. Segment Color Distribution

With fewer than 6 options, a fixed color palette works fine. With 20 options, you need to auto-generate colors that are visually distinct and don't accidentally repeat next to each other.

I went with HSL color generation — evenly distributed hue values with slight saturation/lightness variation. Adjacent segments get hues far apart on the wheel. Simple, and it looks good across all segment counts.

4. State Management Without a Framework

With no framework, managing app state — the list of options, spin history, current result — means discipline. I used a single appState object and explicit update functions. Boring, but it made debugging easy and the code readable six months later.


Lessons Learned

Simplicity is a product decision, not just a technical one. Every feature I considered adding (weighted options, saved wheels, user accounts) would have made the tool slightly more powerful and significantly more complicated. I cut most of them. The constraint made the product better.

Canvas is powerful but verbose. For a project like this it's the right call — no library weight, full control. But I wrote a lot of boilerplate I'd abstract into helpers on the next project.

Small tools still need good UX copy. The button says "Spin!" not "Submit" or "Randomize." The result shows up big and bold. These tiny decisions took real thought.

Deployment friction kills momentum. Static hosting meant I could push changes and see them live in seconds. That speed kept me motivated to iterate.


Try It

If you've got a group that can't decide on anything, or you're a teacher who needs a random name picker, or you're settling a debate the civilized way — give it a spin:

👉 spindecide.getinfotoyou.com

No account. No ads in your face. Just add your options and spin.


Wrapping Up

Building something simple taught me more about product thinking than any complex project has. When you strip away the features, what's left has to actually work — and work well. The wheel spins, a winner appears, someone loses the argument about pineapple on pizza.

That's the whole product. And getting that right took real effort.

If you're building small tools, I'd love to hear what you're working on in the comments.