Here’s the link: I’d really appreciate any feedback on improving it.

r/webdev - Spin the Wheel — a customizable roulette wheel in less than 30kb with a no-javascript fallback.

Spin the wheel screenshot

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 sometime in another post — decided that:

For this tool there we’re some interestng hurdles to overcome:

Satisfying Click

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 30kB budget.

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 JavaScript and the Web Audio API Something I hadn’t even heard of before now.

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 ~1.2kB of js – with room for further optimization.

Creating a no-javascript version

To make the spinner work without js was surprisingly simple.

If the browser has JavaScript disabled, instead of generating and spinning the wheel on the client-side, clicking 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 js*.*

Animating SVG

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 <div>.

Timing the clicks

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 no-javascript version has no ticker animation.

Spinning with 1000s of values

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 60

  • 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!

Things to Improve!

  • The overall look and feel could do with a polish — particularly on the alternate color-schemes.

  • The click sound use some tweaking.

  • 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?

Source link

Write A Comment