npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

canvas-spin-wheel

v0.2.0

Published

A tiny, dependency-free, canvas-based spin wheel widget for the browser. Weighted entries, realistic spin physics, TypeScript types included.

Readme

canvas-spin-wheel

CI npm version minzipped size license

A tiny, dependency-free, canvas-based spin wheel widget for the browser. Weighted entries, realistic spin physics, and full TypeScript types, in about 6 KB minified.

Live demo

import { SpinWheel } from "canvas-spin-wheel";

const wheel = new SpinWheel(document.querySelector("canvas"), {
  entries: [
    { text: "Pizza", color: "#3498db" },
    { text: "Burger", color: "#e74c3c" },
    { text: "Sushi", color: "#2ecc71" },
  ],
  onSpinEnd: (winner) => console.log("Winner:", winner.text),
});

// Spins on click by default, or trigger it yourself:
wheel.spin();

Install

npm install canvas-spin-wheel

Features

  • Zero runtime dependencies
  • Weighted entries (a weight: 3 entry is 3x as likely, and takes a proportionally bigger slice)
  • Physics-based spin (air drag, bearing friction, peg drag) instead of a linear ease-out, so every spin feels a little different
  • Cryptographically random winner selection (crypto.getRandomValues, with a Math.random fallback)
  • Automatic text color contrast per slice
  • Full TypeScript types, ESM + CJS builds

API

new SpinWheel(canvas, options)

| Option | Type | Description | | --- | --- | --- | | entries | WheelEntry[] | Required. { text, color, weight? } | | size | number | Rendered size in CSS px. Defaults to the canvas's own width. | | fontFamily | string | CSS font stack for labels. | | spinOnClick | boolean | Spin when the canvas is clicked. Default true. | | pointerColor | string | Color of the fixed top pointer. Default #e11d48. | | highlightColor | string | Fill flashed over the winning slice after landing. Default rgba(255, 255, 255, 0.35). | | highlightDuration | number | How long the winning slice stays highlighted before onSpinEnd fires, in ms. Default 700. | | physics | Partial<PhysicsConfig> | Override any spin-physics constant (air drag, bearing friction, turn count, ...). See PhysicsConfig in the types. | | onSpinStart | () => void | Called when a spin begins. | | onSpinEnd | (winner: WheelEntry, index: number) => void | Called after the winner is highlighted. | | onSegmentCross | (index: number) => void | Called each time the pointer crosses a slice, useful for a tick sound. |

Instance methods

| Method | Description | | --- | --- | | wheel.spin() | Trigger a spin. No-op if already spinning or there are no entries. | | wheel.setEntries(entries) | Replace the entries. Ignored mid-spin. | | wheel.resize(size) | Resize the canvas (CSS px), accounting for device pixel ratio. | | wheel.isSpinning() | Returns whether a spin is currently in progress. | | wheel.getRotation() | Current wheel rotation, in radians. | | wheel.getEntries() | The wheel's current entries. | | wheel.destroy() | Cancel any in-flight spin and remove event listeners. Call on teardown. |

What this package doesn't do

This is the lite, single-file engine: colored slices, labels, and physics. It doesn't include image entries, background images, sound/confetti plugins, or a UI for building and sharing a wheel.

For the full editor (drag-and-drop entry list, images, sound and confetti, saving and sharing a wheel by link, and a library of ready-made wheels), see Wheel of Names, which this package's spin physics is extracted from.

License

MIT