You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 7-8.RSVP
Socket
Socket
Sign inDemoInstall

spin-wheel

Package Overview
Dependencies
Maintainers
0
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

spin-wheel

An easy to use, themeable component for randomising choices and prizes.


Version published
Weekly downloads
1.5K
increased by10.28%
Maintainers
0
Created
Weekly downloads
 

Readme

Source
thumbnail

Spin Wheel

GitHub tag maturity stable badge License

An easy to use, themeable component for randomising choices and prizes.

Features

  • Vanilla JavaScript (ES6).
  • No dependencies.
  • Simple, easy to use API.
  • Spin by applying momentum and drag, or animate to a specific angle with easing.
  • Interactable with click-drag or touch-flick.
  • Responsive layout (resizes automatically to fit it's container).
  • Easily themeable:
    • Give items their own color and weight.
    • Rotate labels and change alignment.
    • Draw images on items, the wheel, and the foreground.
    • Apply repeating colour sets.
  • Callbacks for events like onSpin and onCurrentIndexChange.
  • Clockwise and anti-clockwise spinning.

Examples

Installation

ESM

import {Wheel} from 'https://cdn.jsdelivr.net/npm/spin-wheel@5.0.0/dist/spin-wheel-esm.js';

IIFE

<script src="https://cdn.jsdelivr.net/npm/spin-wheel@5.0.0/dist/spin-wheel-iife.js"></script>

Local

npm install spin-wheel

How to make your own wheel

// 1. Configure the wheel's properties:
const props = {
  items: [
    {
      label: 'one',
    },
    {
      label: 'two',
    },
    {
      label: 'three',
    },
  ]
}

// 2. Decide where you want it to go:
const container = document.querySelector('.wheel-container');

// 3. Create the wheel in the container and initialise it with the props:
const wheel = new Wheel(container, props);

How to spin the wheel

For multiplayer games or awarding prizes with actual value, the best way is to call Wheel.spinToItem(). The wheel will spin for a certain duration, and once finished the pointer will be pointing at the specified item. You should always calculate the winning item on the back-end, for example:

const winningItemIndex = await fetchWinningItemIndex();
const duration = 4000;
const easing = easing.cubicOut;
wheel.spinToItem(winningItemIndex, duration, true, 2, 1, easing)

If precision is not important, you can use Wheel.spin() to immediately start spinning the wheel at a certain speed, which will be reduced over time according to Wheel.rotationResistance. You can also set Wheel.isInteractive = true to allow the user to spin the wheel themselves by dragging or flicking.

How to draw the pointer

The wheel doesn't have a built-in pointer, instead you set Wheel.pointerAngle and draw the pointer yourself. This is because there are many ways you might want the pointer to appear and behave, for example you might want to animate it.

Your options for drawing the pointer are:

  • Overlay an image using Wheel.overlayImage
  • Overlay something using the DOM

Images and fonts

Images are passed as instances of HTMLImageElement and should be pre-loaded, otherwise there will be an initial delay (or flicker) while the browser downloads them. Fonts should also be pre-loaded for the same reason. See the code behind the themes example for an example of how to pre-load images and fonts.

Configuration

Everything is easy to configure. The wheel is responsive and resizes automatically to fit it's container, so when the size of the container changes you don't have to worry about updating fiddly things like widths and font sizes. For that reason, some numeric properties are expressed as percentages, while others are expressed as pixels.

  • Percentage properties are a percent of the container size. For example, a Wheel.radius of 0.9 means the wheel will fill 90% of the container.

  • Pixel properties are relative to a container size of 500px. For example, a Wheel.LineWidth of 1 will be exactly 1px when the container size is 500px.

Labels are also simple to configure because the font size is calculated automatically. You can optionally set Wheel.itemLabelFontSizeMax (in pixels), but otherwise the largest item label will be sized to fit between Wheel.itemLabelRadius (percent) and Wheel.itemLabelRadiusMax (percent).

Here's a handy diagram:

diagram of props

Methods for Wheel

MethodDescription
constructor(container, props = {})Create the wheel inside a container Element and initialise it with props.

container must be an Element.

props must be an Object or null.

init(props = {})Initialise all properties.

If a value is not provided for a property then it will be given a default value.
resize()[Legacy] Re-calculate and redraw the wheel. Only needed in certain scenarios for older browsers that don't support ResizeObserver.
remove()Remove the wheel from the DOM and unregister event handlers.
spin(rotationSpeed = 0)Spin the wheel by setting rotationSpeed. The wheel will immediately start spinning, and slow down over time depending on the value of rotationResistance.

A positive number will spin clockwise, a negative number will spin anti-clockwise.

spinTo(rotation = 0, duration = 0, easingFunction = null)Spin the wheel to a particular rotation.

The animation will occur over the provided duration (milliseconds).

The animation can be adjusted by providing an optional easingFunction which accepts a single parameter n, where n is between 0 and 1 inclusive.

If no easing function is provided, the default easeSinOut will be used.

For example easing functions see easing-utils.

spinToItem(itemIndex = 0, duration = 0, spinToCenter = true, numberOfRevolutions = 1, direction = 1, easingFunction = null)Spin the wheel to a particular item.

The animation will occur over the provided duration (milliseconds).

If spinToCenter is true, the wheel will spin to the center of the item, otherwise the wheel will spin to a random angle inside the item.

numberOfRevolutions controls how many times the wheel will rotate a full 360 degrees before resting on the item.

direction can be 1 (clockwise) or -1 (anti-clockwise)

The animation can be adjusted by providing an optional easingFunction which accepts a single parameter n, where n is between 0 and 1 inclusive.

If no easing function is provided, the default easeSinOut will be used.

For example easing functions see easing-utils.

stop()Immediately stop the wheel from spinning, regardless of which method was used to spin it.
getCurrentIndex()Get the index of the item that the Pointer is pointing at.

An item is considered "current" if pointerAngle is between it's start angle (inclusive) and it's end angle (exclusive).

Properties for Wheel

Note: setting a property to undefined will reset it to the default value.

NameDefault ValueDescription
borderColor'#000'The CSS color for the line around the circumference of the wheel.
borderWidth0The width (in pixels) of the line around the circumference of the wheel.
debugfalseIf debugging info will be shown.

This is helpful when positioning labels.

imagenullThe image (HTMLImageElement) to draw on the wheel and rotate with the wheel.

It will be centered and scaled to fit Wheel.radius.

isInteractivetrueIf the user will be allowed to spin the wheel using click-drag/touch-flick.

User interaction will only be detected within the bounds of Wheel.radius.

itemBackgroundColors['#fff']The CSS colors to use as a repeating pattern for the background colors of all items.

Overridden by Item.backgroundColor.

Example: ['#fff','#000'].

itemLabelAlign'right'The alignment of all item labels.

Possible values: 'left','center','right'.

itemLabelBaselineOffset0The offset of the baseline (or line height) of all item labels (as a percent of the label's height).
itemLabelColors['#000']The CSS colors to use as a repeating pattern for the colors of all item labels.

Overridden by Item.labelColor.

Example: ['#fff','#000'].

itemLabelFont'sans-serif'The font familiy to use for all item labels.

Example: 'Helvetica, sans-serif'.

itemLabelFontSizeMax100The maximum font size (in pixels) for all item labels.
itemLabelRadius0.85The point along the wheel's radius (as a percent, starting from the center) to start drawing all item labels.
itemLabelRadiusMax0.2The point along the wheel's radius (as a percent, starting from the center) to limit the maximum width of all item labels.
itemLabelRotation0The rotation of all item labels.

Use this in combination with itemLabelAlign to flip the labels 180°.
itemLabelStrokeColor'#fff'The CSS color of the stroke applied to the outside of the label text.
itemLabelStrokeWidth0The width of the stroke applied to the outside of the label text.
items[]The items (or slices, wedges, segments) shown on the wheel.

Setting this property will re-create all of the items on the wheel based on the objects provided.

Accessing this property lets you change individual items. For example you could change the background color of an item.

lineColor'#000'The CSS color of the lines between the items.
lineWidth1The width (in pixels) of the lines between the items.
offset{x: 0, y: 0}The offset of the wheel from the center of it's container (as a percent of the wheel's diameter).
onCurrentIndexChangenullThe callback for the onCurrentIndexChange event.
onRestnullThe callback for the onRest event.
onSpinnullThe callback for the onSpin event.
overlayImagenullThe image (HTMLImageElement) to draw over the top of the wheel.

It will be centered and scaled to fit the container's smallest dimension.

Use this to draw decorations around the wheel, such as a stand or pointer.

pixelRatio0The pixel ratio (as a percent) used to draw the wheel.

Higher values will produce a sharper image at the cost of performance, but the sharpness depends on the current display device.

A value of 0 will use the pixel ratio of the current display device (see devicePixelRatio).

pointerAngle0The angle of the Pointer which will be used to determine the currentIndex (or the "winning" item).
radius0.95The radius of the wheel (as a percent of the container's smallest dimension).
rotation0The rotation (angle in degrees) of the wheel.

The first item will be drawn clockwise from this point.

rotationResistance-35The amount that rotationSpeed will be reduced by every second until the wheel stops spinning.

Set to 0 to spin the wheel infinitely.

rotationSpeed0[Readonly] How fast (angle in degrees) the wheel is spinning every 1 second.

A positive number means the wheel is spinning clockwise, a negative number means anti-clockwise, and 0 means the wheel is not spinning.

rotationSpeedMax250The maximum absolute value for rotationSpeed.

The wheel will not spin faster than this value in either direction.

Events for Wheel

onCurrentIndexChange(event = {})

Raised when a new item is pointed at. This can be used to change the color of the current item, or play a 'ticking' sound.

KeyValue
type'currentIndexChange'
currentIndexThe index of the item that the Pointer was pointing at.

See Wheel.pointerAngle.

onRest(event = {})

Raised when the wheel comes to a rest after spinning.

KeyValue
type'rest'
currentIndexThe index of the item that the Pointer was pointing at.

See Wheel.pointerAngle.

rotationThe rotation of the wheel.

See Wheel.rotation.

onSpin(event = {})

Raised when the wheel has been spun.

KeyValue
type'spin'
durationThe duration of the spin animation. Only provided when method = spinto or method = spintoitem.
methodThe method that was used to spin the wheel (interact, spin, spinto, spintoitem).
rotationResistanceThe value of Wheel.rotationResistance at the time the event was raised.

Only provided when method = interact or method = spin.

rotationSpeedThe value of Wheel.rotationSpeed at the time the event was raised.

Only provided when method = interact or method = spin.

targetItemIndexThe item that the Pointer will be pointing at once the spin animation has finished.

Only provided when method = spintoitem.

targetRotationThe value that Wheel.rotation will have once the spin animation has finished.

Only provided when method = spinto or method = spintoitem.

Methods for Item

NameDescription
getCenterAngle()Get the angle (in degrees) that this item ends at (exclusive), ignoring the current rotation of the wheel.
getEndAngle()Get the angle (in degrees) that this item ends at (inclusive), ignoring the current rotation of the wheel.
getIndex()Get the 0-based index of this item.
getRandomAngle()Return a random angle (in degrees) between this item's start angle (inclusive) and end angle (inclusive).
getStartAngle()Get the angle (in degrees) that this item starts at (inclusive), ignoring the current rotation of the wheel.
init(props = {})Initialise all properties.

If a value is undefined or invalid then that property will fall back to a default value.

Properties for Item

Note: setting a property to undefined will reset it to the default value.

NameDefault ValueDescription
backgroundColornullThe CSS color of the item's background.

When null, the color will fall back to Wheel.itemBackgroundColors.

Example: '#fff'.

imagenullThe image (HTMLImageElement) to draw on the item.

Any part of the image that extends outside the item will be clipped. The image will be drawn over the top of Item.backgroundColor.

imageOpacity1The opacity (as a percent) of Item.image.

Useful if you want to fade the image to make the item's label stand out.

imageRadius0.5The point along the wheel's radius (as a percent, starting from the center) to draw the center of Item.image.
imageRotation0The rotation (angle in degrees) of Item.image.
imageScale1The scale (size as a percent) of Item.image.
label''The text that will be drawn on the item.
labelColornullThe CSS color of the item's label.

When null, the color will fall back to Wheel.itemLabelColors.

Example: '#000'.

valuenullSome value that has meaning to your application. For example, a reference to the object representing the item on the wheel, or a database id.
weight1The proportional size of the item relative to other items on the wheel.

For example, if you have 2 items where item[0] has a weight of 1 and item[1] has a weight of 2, then item[0] will take up 1/3 of the space on the wheel.

Acknowledgements

Inspired by random-wheel.

Keywords

FAQs

Package last updated on 06 Jul 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc