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

推荐订阅源

博客园 - 三生石上(FineUI控件)
S
SegmentFault 最新的问题
阮一峰的网络日志
阮一峰的网络日志
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
WordPress大学
WordPress大学
博客园 - 司徒正美
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
宝玉的分享
宝玉的分享
爱范儿
爱范儿
月光博客
月光博客
The GitHub Blog
The GitHub Blog
M
MIT News - Artificial intelligence
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog
T
Tailwind CSS Blog
美团技术团队
D
Docker
V
Visual Studio Blog
Martin Fowler
Martin Fowler
博客园 - 聂微东
The Cloudflare Blog

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.