Here's the link: missingdice.com/spin-the-wheel. I'd really appreciate any feedback on improving it, i've been staring at it for a week!
I've been building a website of simple tools for boardgame players. For various reasons there are times when you need to roll dice, flip cards, or spin a spinner online.
The site is for simple things like that.
I want the site to be a success, so i first took a look at the competition and — for reasons I'll elaborate on in another post — decided that:
- the site should be as accessible as possible
- no page should be larger than
- every tool should have a
For this tool there we're some interestng hurdles to overcome:
It was important that the spinner have a satisfying clicking sound as it spun.
I found an
mp3 of a click, but even at less than 1 second long, it weighed
7kB. Using it would have put me over the
I'm sure there are lots of clever ways of reducing the file size of audio. But instead I chose to generate a click with
Luckily for me, I know a synth enthusiast, and he explained some of the terminology to me.
I found this tutorial on synthesizing drum sounds and tweaked the hi-hat example to fit.
This ended up being just
js - with room for further optimization.
To make the spinner work without
js was surprisingly simple.
If the browser has
spin the wheel submits a form…
Then the server:
- builds a spinner with the user's custom values
- randomly selects a winner
- generates in advanced a css animation that spins the wheel
- sends the html back to the client
It works surprisingly well.
I did this with Netlify Functions, so I'm not running an entire server for the tiny number of people who'll use the site without
While animating SVG is generally fine, some browsers really struggle with it (Safari). After a lot of tinkering, it turns out the best fix is just to use seperate SVGs for each animated component, and put them each in their own
<div> — then animate the
The spinner spins at different rates, durations, and with a random number of rotations — that way it stays surprising and dramatic.
For the spin to be really satisfying, it needed a little ticker on top. (like on the gameshow "wheel of fortune").
That meant having "pins" around the rim of the wheel, and animating a ticker each time it "hit" a "pin."
For performance reasons I thought it would be better to calculate the timings of the animation (and click sound) in advance.
This turns out to be a seriously complicated task, and after 3 days of learning calculus I gave up.
Instead it uses
requestAnimationFrame and measures the current rotation of the spinner. If the rotation is between certain ranges it produces a click.
This works okay, but it does make mistakes.
It also means the
One issue was allowing people to add 1000s of values to the spinner.
I figured there is a use case where someone might want to paste an entire spreadsheet of values to have one picked at random.
So, I decided to use a
<textarea> as the input, with a new line for each new value. Then, if the user pastes a comma-seperated list, it will reformat it before generating the wheel.
The big problem here is performance.
To make it work, the spinner
<svg> gets less complex as more values are added.
- The patterns are removed.
- The number of pins on the rim of the wheel is capped at
- The text paths become simpler.
I've only tested it on my fancy new computer, but it works fine up to around
6000 values. Feel free to test it out and let me know!
- The overall look and feel could do with a polish — particularly on the alternate color-schemes.
- The click sound could do with a tweak.
- Finding an accurate way of measuring the click animation in advanced would be amazing.
- Making custom wheels embeddable as an
<iframe>would be cool.
Let me know what you think and what can be improved?