Skip to content

Commit

Permalink
Merge branch 'release/4.2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
CrazyTim committed Jul 25, 2023
2 parents 01c8ca9 + 940c294 commit 4debcd0
Show file tree
Hide file tree
Showing 31 changed files with 1,135 additions and 989 deletions.
25 changes: 12 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ An easy to use, themeable component for randomising choices and prizes.
- 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 - everything in the wheel resizes automatically to fit it's container.
- Responsive layout (resizes automatically to fit it's container).
- Easily themeable:
- Give items their own color and weight.
- Rotate labels and change alignment.
Expand All @@ -25,13 +25,13 @@ An easy to use, themeable component for randomising choices and prizes.
### ESM

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

### IIFE

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

### Local
Expand Down Expand Up @@ -67,18 +67,16 @@ const wheel = new Wheel(container, props);

## How to spin the wheel

The most useful 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. For non-trivial applications (such as multiplayer games, or awarding prizes with actual value) you should always calculate the winning item on the back-end, and only use the front-end to display the result. For example:
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:

```javascript
const winningItemIndex = await fetchWinningItemIndex(); // For example, this might return a value of 2.
const winningItemIndex = await fetchWinningItemIndex();
const duration = 4000;
const easing = easing.cubicOut;
wheel.spinToItem(winningItemIndex, duration, true, 2, 1, easing)
```

If precision is less important, you can use `Wheel.spin()` to immediately start spinning the wheel at a certain speed. This sets the wheel's `rotationSpeed`, 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.
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.

## Examples

Expand Down Expand Up @@ -109,8 +107,8 @@ Method | Descriptio
`constructor(container, props = {})` | `container` must be an Element.</p><p>`props` must be an Object or null.
`init(props = {})` | Initialise all properties.</p><The>If a value is not provided for a property then it will be given a default value.
`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`.</p><p>A positive number will spin clockwise, a negative number will spin anticlockwise.
`spinTo(rotation = 0, duration = 0, easingFunction = null)` | Spin the wheel to a particular rotation.</p><p>The animation will occur over the provided `duration` (milliseconds).</p><p>The `rotationSpeed` property will be ignored during the animation.</p><p>The animation can be adjusted by providing an optional `easingFunction` which accepts a single parameter n, where n is between 0 and 1 inclusive.</p><p>For example easing functions see [easing-utils](https://github.com/AndrewRayCode/easing-utils).
`spinToItem(itemIndex = 0, duration = 0, spinToCenter = true, numberOfRevolutions = 1, easingFunction = null)` | Spin the wheel to a particular item.</p><p>The animation will occur over the provided `duration` (milliseconds).</p><p>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.</p><p>`numberOfRevolutions` controls how many times the wheel will rotate a full 360 degrees before resting on the item.</p><p>The animation can be adjusted by providing an optional `easingFunction` which accepts a single parameter n, where n is between 0 and 1 inclusive.</p><p>If no easing function is provided, the default easeSinOut will be used.</p><p>For example easing functions see [easing-utils](https://github.com/AndrewRayCode/easing-utils).</p><p>Note: the `Wheel.rotationSpeed` property will be ignored during the animation.
`spinTo(rotation = 0, duration = 0, easingFunction = null)` | Spin the wheel to a particular rotation.</p><p>The animation will occur over the provided `duration` (milliseconds).<p>The animation can be adjusted by providing an optional `easingFunction` which accepts a single parameter n, where n is between 0 and 1 inclusive.</p><p>If no easing function is provided, the default easeSinOut will be used.</p><p>For example easing functions see [easing-utils](https://github.com/AndrewRayCode/easing-utils).
`spinToItem(itemIndex = 0, duration = 0, spinToCenter = true, numberOfRevolutions = 1, easingFunction = null)` | Spin the wheel to a particular item.</p><p>The animation will occur over the provided `duration` (milliseconds).</p><p>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.</p><p>`numberOfRevolutions` controls how many times the wheel will rotate a full 360 degrees before resting on the item.</p><p>The animation can be adjusted by providing an optional `easingFunction` which accepts a single parameter n, where n is between 0 and 1 inclusive.</p><p>If no easing function is provided, the default easeSinOut will be used.</p><>For example easing functions see [easing-utils](https://github.com/AndrewRayCode/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.</p><p>An item is considered "current" if `pointerAngle` is between it's start angle (inclusive) and it's end angle (exclusive).

Expand Down Expand Up @@ -202,13 +200,14 @@ Note: setting a property to `undefined` will reset it to the default value.

Name | Default Value | Description
------------------------------- | ----------------- | ---------------------------
`backgroundColor` | `null` | The background color of the item.</p><p>Falls back to `Wheel.itemBackgroundColors` when `null`.</p><p>Example: `'#fff'`.
`image` | `null` | The url of an image that will be drawn on the item. Any part of the image that extends outside the item will be clipped.
`backgroundColor` | `null` | The background color of the item.</p><p>When `null`, the actual color rendered will fall back to `Wheel.itemBackgroundColors`.</p><p>Example: `'#fff'`.
`image` | `null` | The url of an image that will be drawn 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`.
`imageOpacity` | `1` | The opacity (as a percent) of `Item.image`. Useful if you want to fade the image to make the item's label stand out.
`imageRadius` | `0.5` | The point along the radius (as a percent, starting from the center of the wheel) to draw the center of `Item.image`.
`imageRotation` | `0` | The rotation (angle in degrees) of `Item.image`.
`imageScale` | `1` | The scale (as a percent) to resize `Item.image`.
`label` | `''` | The text that will be drawn on the item.
`labelColor` | `null` | The color of the label.</p><p>Falls back to `Wheel.itemLabelColors` when `null`.</p><p>Example: `'#000'`.
`labelColor` | `null` | The color of the label.</p><p>When `null`, the actual color rendered will fall back to `Wheel.itemLabelColors`.</p><p>Example: `'#000'`.
`value` | `null` | Some value that has meaning to your application. For example, a reference to the object representing the item on the wheel, or a database id.
`weight` | `1` | The proportional size of the item relative to other items on the wheel.</p><p>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.

Expand Down
6 changes: 3 additions & 3 deletions dist/spin-wheel-esm.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions dist/spin-wheel-iife.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion examples/esm/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ select {

label {
margin-right: 5px;
}
}
30 changes: 2 additions & 28 deletions examples/esm/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="icon" href="data:image/x-icon;," type="image/x-icon">
<link rel="stylesheet" href="./css/index.css"/>

<script type='module'>
import {Wheel} from '/dist/spin-wheel-esm.js';

window.onload = () => {

const props = {
items: [
{
label: 'one',
},
{
label: 'two',
},
{
label: 'three',
},
]
};

const container = document.querySelector('.wheel-wrapper');

window.wheel = new Wheel(container, props);

}
</script>

<script src="./js/index.js" type="module"></script>
</head>

<body>
Expand All @@ -44,4 +18,4 @@
<div class="wheel-wrapper"></div>

</body>
</html>
</html>
23 changes: 23 additions & 0 deletions examples/esm/js/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {Wheel} from '../../../dist/spin-wheel-esm.js';

window.onload = () => {

const props = {
items: [
{
label: 'one',
},
{
label: 'two',
},
{
label: 'three',
},
]
};

const container = document.querySelector('.wheel-wrapper');

window.wheel = new Wheel(container, props);

}
2 changes: 1 addition & 1 deletion examples/iife/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<link rel="icon" href="data:image/x-icon;," type="image/x-icon">
<link rel="stylesheet" href="./css/index.css"/>

<script src="/dist/spin-wheel-iife.js"></script>
<script src="../../dist/spin-wheel-iife.js"></script>

<script>
window.onload = () => {
Expand Down
8 changes: 2 additions & 6 deletions examples/playground/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="icon" href="data:image/x-icon;," type="image/x-icon">
<link rel="stylesheet" href="./css/index.css"/>

<script src="js/initWheel.js" type="module"></script>
<script src="js/initEventListeners.js" type="module"></script>

<script src="./js/index.js" type="module"></script>
</head>

<body>
Expand Down Expand Up @@ -142,6 +139,5 @@ <h2><span class="prop-name"></span><span class="prop-value"></span></h2>
</div>

</div>

</body>
</html>
</html>
2 changes: 2 additions & 0 deletions examples/playground/js/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import './initWheel.js';
import './initEventListeners.js';
2 changes: 1 addition & 1 deletion examples/playground/js/initEventListeners.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,4 @@ function downloadTextFile(text, fileName, mimeType) {
a.href = URL.createObjectURL( new Blob([text], {type: mimeType} ) );
a.download = fileName;
a.click();
}
}
8 changes: 7 additions & 1 deletion examples/playground/js/initWheel.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,10 @@ const props = {

const container = document.querySelector('.wheel-wrapper');

window.wheel = new Wheel(container, props);
// Save object globally for easy debugging.
window.wheel = new Wheel(container, props);

// Log events for easy debugging:
wheel.onCurrentIndexChange = e => console.log(e);
wheel.onRest = e => console.log(e);
wheel.onSpin = e => console.log(e);
2 changes: 1 addition & 1 deletion examples/spin-to-item/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ label {

button {
padding: 10px 20px;
align-self: start;
cursor: pointer;
margin-right: 10px;
}

input[type="radio"],
Expand Down
143 changes: 7 additions & 136 deletions examples/spin-to-item/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,143 +2,11 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>Spin Wheel Example - Spin to a specific item</title>
<title>Spin Wheel Example - Spin to an Item</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="icon" href="data:image/x-icon;," type="image/x-icon">
<link rel="stylesheet" href="./css/index.css"/>

<script type='module'>
import {Wheel} from '../../dist/spin-wheel-esm.js';
import * as easing from "https://cdn.skypack.dev/d3-ease@3";
import * as util from "../../src/util.js";

window.onload = () => {
const numberOfRevolutions = 1;

const container = document.querySelector('.wheel-wrapper');
const dropdownWinningItem = document.querySelector('select.winning-item');
const dropdownEasingFunction = document.querySelector('select.easing-function');
const dropdownSpinDirection = document.querySelector('select.spin-direction');
const dropdownRevolutions = document.querySelector('select.revolutions');

const btnSpin = document.querySelector('.gui-wrapper button');

const props = {
debug: true, // So we can see pointer angle.
items: [
{
label: 'Dog',
weight: 6,
},
{
label: 'Cat',
weight: 4.9,
},
{
label: 'Fish',
weight: 4.1,
},
{
label: 'Rabbit',
weight: 3.7,
},
{
label: 'Bird',
weight: 3,
},
{
label: 'Chicken',
weight: 2.8,
},
{
label: 'Lizard',
weight: 2.5,
},
{
label: 'Turtle',
weight: 1,
},
],
itemLabelRadiusMax: .5,
};

const easingFunctions = [
{
label: 'default (easeSinOut)',
function: null,
},
{
label: 'easeSinInOut',
function: easing.easeSinInOut,
},
{
label: 'easeCubicOut',
function: easing.easeCubicOut,
},
{
label: 'easeCubicInOut',
function: easing.easeCubicInOut,
},
{
label: 'easeElasticOut',
function: easing.easeElasticOut,
},
{
label: 'easeBounceOut',
function: easing.easeBounceOut,
},
];

window.wheel = new Wheel(container, props);

// Initalise winning item dropdown:
for (const [i, item] of wheel.items.entries()) {
const opt = document.createElement('option');
opt.textContent = item.label;
opt.value = i;
dropdownWinningItem.appendChild(opt);
}

// Initalise easing functions dropdown:
for (const [i, item] of easingFunctions.entries()) {
const opt = document.createElement('option');
opt.textContent = item.label;
opt.value = i;
dropdownEasingFunction.appendChild(opt);
}

window.addEventListener('click', (e) => {

// Listen for click event on spin button:
if (e.target == btnSpin) {
const winningItemIndex = fetchWinningItemIndexFromApi();
const easing = easingFunctions[dropdownEasingFunction.value];
const easingFunction = easing.function;
const duration = 2600;
const spinDirection = parseInt(document.querySelector('input[name="spinDirection"]:checked').value);
const revolutions = parseInt(dropdownRevolutions.value);
wheel.spinToItem(winningItemIndex, duration, true, revolutions, spinDirection, easingFunction);
}

});

window.addEventListener('keyup', (e) => {

if (e.target && e.target.matches('#pointerAngle')) {
console.log(e.target.value);
wheel.pointerAngle = parseInt(e.target.value) || 0;
}

});

function fetchWinningItemIndexFromApi() {
// Simulate a call to the back-end
return dropdownWinningItem.value;
}

}
</script>

<script src="./js/index.js" type="module"></script>
</head>

<body>
Expand All @@ -161,10 +29,13 @@
<p>
<label>Wheel pointer angle (Degrees):</label><input type="text" id="pointerAngle" value="0">
</p>
<button>Spin to Item!</button>
<div>
<button class="btn-spin">Spin to Item</button>
<button class="btn-stop">Stop</button>
</div>
</div>

<div class="wheel-wrapper"></div>

</body>
</html>
</html>
Loading

0 comments on commit 4debcd0

Please sign in to comment.