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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@zohaibtariq/vuewinwheel

v1.0.2

Published

### install with ``` npm i @zohaibtariq/vuewinwheel ```

Downloads

13

Readme

Vue 3 Win Wheel

This is based on library winwheel.js, all examples are in vue 3 composition api, it helps you programatically stop at any segment of your criteria just pass segment number in stopAt variable.

install with

npm i @zohaibtariq/vuewinwheel

npmjs

@zohaibtariq/vuewinwheel

Vue 3 Winwheel Examples


Basic code wheel

<template>
  <VueWinWheel ref="winWheel" :options="allOptions" :canvasWidth="canvasWidth" :canvasHeight="canvasHeight" :stopAt="stopAt" />
  <br/>
  <br/>
  <br/>
  <button @click="spinWinWheel">Random Spin</button>
  <button @click="spinWinWheelStopAt">Defined Spin</button>
</template>

<script setup>
import {VueWinWheel} from '@zohaibtariq/vuewinwheel'
import '@zohaibtariq/vuewinwheel/dist/style.css';
import { ref, onMounted } from 'vue';

const winWheel = ref();

const spinWinWheel = () => {
  spinStartTime = Date.now() // if you miss this sound will not play after first run
  if(winWheel.value)
    winWheel.value.spin() // winWheelInstances is only required for the (2 part wheel)
};

const spinWinWheelStopAt = () => {
  spinStartTime = Date.now() // if you miss this sound will not play after first run
  if(winWheel.value)
    winWheel.value.spinAndStopAt(stopAt)
};

const canvasWidth = 500; // set custom canvas width
const canvasHeight = 500; // set custom canvas height
const stopAt = 3; // Segment at which you want to stop at

let spinningAudio = new Audio('./spinning.mp3'); // update this with your own tik sound
let winnerAudio = new Audio('./winner.mp3'); // update this with your own win sound

// Called when the animation has finished.
function spinStopped(indicatedSegment)
{
  playWinningSound()
  // Display different message if win/lose/bankrupt.
  // this must need to be updated according to your segment text
  if (indicatedSegment.text == 'LOOSE TURN')
    alert('Sorry but you loose a turn.');
  else if (indicatedSegment.text == 'BANKRUPT')
    alert('Oh no, you have gone BANKRUPT!');
  else
    alert("You have won " + indicatedSegment.text);
}

function eachSegmentSpin()
{
  playSpinningSound()
}

let spinStartTime;

function playSpinningSound()
{
  if(!spinStartTime){
    spinStartTime = Date.now(); // this must start when spin starts
  }
  spinningAudio.pause();
  const spinEndTime = Date.now();
  const diffInSpinTime = spinEndTime - spinStartTime
  // do not play this sound if animation time is exceeded
  if(options?.animation?.duration === undefined || diffInSpinTime < ((options.animation.duration * 1000)/1.4)) { // if you observe wheel stop but tik sound continues to play increase value of 1.4 to gradually a higher digit number like 1.5, 1.6 what ever suites you, animation duration and spin setting effects it
    spinningAudio.currentTime = 0;
    spinningAudio.play();
  }
}

function playWinningSound()
{
  winnerAudio.pause();
  winnerAudio.currentTime = 0;
  winnerAudio.play();
}

const options = { // basic_code_wheel
  'numSegments'  : 8,			// Number of segments
  'outerRadius'  : 212,		// The size of the wheel.
  'centerX'      : 217,		// Used to position on the background correctly.
  'centerY'      : 219,
  'textFontSize' : 28,		// Font size.
  'segments'     :			// Definition of all the segments.
      [
        {'fillStyle' : '#eae56f', 'text' : 'Prize 1'},
        {'fillStyle' : '#89f26e', 'text' : 'Prize 2'},
        {'fillStyle' : '#7de6ef', 'text' : 'Prize 3'},
        {'fillStyle' : '#e7706f', 'text' : 'Prize 4'},
        {'fillStyle' : '#eae56f', 'text' : 'Prize 5'},
        {'fillStyle' : '#89f26e', 'text' : 'Prize 6'},
        {'fillStyle' : '#7de6ef', 'text' : 'Prize 7'},
        {'fillStyle' : '#e7706f', 'text' : 'Prize 8'}
      ],
  'animation' :				// Definition of the animation
      {
        'type'     : 'spinToStop',
        'duration' : 5,
        'spins'    : 8,
        'callbackFinished' : spinStopped,  // Function to call when the spinning has stopped.
        'callbackSound'    : eachSegmentSpin,   // Called when the tick sound is to be played.
      }
};

const allOptions = {
  ...options,
  outerRadius: (canvasWidth / 2) - (options.lineWidth || 1)
};

onMounted(() => {
  allOptions.outerRadius = (canvasWidth / 2) - (options.lineWidth || 1);
});

</script>

<style scoped>
/* Define your css here inspect dom to see what ids and classes are available */
</style>

Wheel of fortune

<template>
  <VueWinWheel ref="winWheel" :options="allOptions" :canvasWidth="canvasWidth" :canvasHeight="canvasHeight" :stopAt="stopAt" />
  <br/>
  <br/>
  <br/>
  <button @click="spinWinWheel">Random Spin</button>
  <button @click="spinWinWheelStopAt">Defined Spin</button>
</template>

<script setup>
import {VueWinWheel} from '@zohaibtariq/vuewinwheel'
import '@zohaibtariq/vuewinwheel/dist/style.css';
import { ref, onMounted } from 'vue';

const winWheel = ref();

const spinWinWheel = () => {
  spinStartTime = Date.now() // if you miss this sound will not play after first run
  if(winWheel.value)
    winWheel.value.spin() // winWheelInstances is only required for the (2 part wheel)
};

const spinWinWheelStopAt = () => {
  spinStartTime = Date.now() // if you miss this sound will not play after first run
  if(winWheel.value)
    winWheel.value.spinAndStopAt(stopAt)
};

const canvasWidth = 500; // set custom canvas width
const canvasHeight = 500; // set custom canvas height
const stopAt = 3; // Segment at which you want to stop at

let spinningAudio = new Audio('./spinning.mp3'); // update this with your own tik sound
let winnerAudio = new Audio('./winner.mp3'); // update this with your own win sound

// Called when the animation has finished.
function spinStopped(indicatedSegment)
{
  playWinningSound()
  // Display different message if win/lose/bankrupt.
  // this must need to be updated according to your segment text
  if (indicatedSegment.text == 'LOOSE TURN')
    alert('Sorry but you loose a turn.');
  else if (indicatedSegment.text == 'BANKRUPT')
    alert('Oh no, you have gone BANKRUPT!');
  else
    alert("You have won " + indicatedSegment.text);
}

function eachSegmentSpin()
{
  playSpinningSound()
}

let spinStartTime;

function playSpinningSound()
{
  if(!spinStartTime){
    spinStartTime = Date.now(); // this must start when spin starts
  }
  spinningAudio.pause();
  const spinEndTime = Date.now();
  const diffInSpinTime = spinEndTime - spinStartTime
  // do not play this sound if animation time is exceeded
  if(options?.animation?.duration === undefined || diffInSpinTime < ((options.animation.duration * 1000)/1.4)) { // if you observe wheel stop but tik sound continues to play increase value of 1.4 to gradually a higher digit number like 1.5, 1.6 what ever suites you, animation duration and spin setting effects it
    spinningAudio.currentTime = 0;
    spinningAudio.play();
  }
}

function playWinningSound()
{
  winnerAudio.pause();
  winnerAudio.currentTime = 0;
  winnerAudio.play();
}

const options = { // wheel_of_fortune
  'outerRadius'     : 212,        // Set outer radius so wheel fits inside the background.
  'innerRadius'     : 75,         // Make wheel hollow so segments don't go all way to center.
  'textFontSize'    : 24,         // Set default font size for the segments.
  'textOrientation' : 'vertical', // Make text vertical so goes down from the outside of wheel.
  'textAlignment'   : 'outer',    // Align text to outside of wheel.
  'numSegments'     : 24,         // Specify number of segments.
  'segments'        :             // Define segments including colour and text.
      [                               // font size and text colour overridden on bankrupt segments.
        {'fillStyle' : '#ee1c24', 'text' : '300'},
        {'fillStyle' : '#3cb878', 'text' : '450'},
        {'fillStyle' : '#f6989d', 'text' : '600'},
        {'fillStyle' : '#00aef0', 'text' : '750'},
        {'fillStyle' : '#f26522', 'text' : '500'},
        {'fillStyle' : '#000000', 'text' : 'BANKRUPT', 'textFontSize' : 16, 'textFillStyle' : '#ffffff'},
        {'fillStyle' : '#e70697', 'text' : '3000'},
        {'fillStyle' : '#fff200', 'text' : '600'},
        {'fillStyle' : '#f6989d', 'text' : '700'},
        {'fillStyle' : '#ee1c24', 'text' : '350'},
        {'fillStyle' : '#3cb878', 'text' : '500'},
        {'fillStyle' : '#f26522', 'text' : '800'},
        {'fillStyle' : '#a186be', 'text' : '300'},
        {'fillStyle' : '#fff200', 'text' : '400'},
        {'fillStyle' : '#00aef0', 'text' : '650'},
        {'fillStyle' : '#ee1c24', 'text' : '1000'},
        {'fillStyle' : '#f6989d', 'text' : '500'},
        {'fillStyle' : '#f26522', 'text' : '400'},
        {'fillStyle' : '#3cb878', 'text' : '900'},
        {'fillStyle' : '#000000', 'text' : 'BANKRUPT', 'textFontSize' : 16, 'textFillStyle' : '#ffffff'},
        {'fillStyle' : '#a186be', 'text' : '600'},
        {'fillStyle' : '#fff200', 'text' : '700'},
        {'fillStyle' : '#00aef0', 'text' : '800'},
        {'fillStyle' : '#ffffff', 'text' : 'LOOSE TURN', 'textFontSize' : 12}
      ],
  'animation' :           // Specify the animation to use.
      {
        'type'     : 'spinToStop',
        'duration' : 3,
        'spins'    : 10,
        'callbackFinished' : spinStopped,  // Function to call when the spinning has stopped.
        'callbackSound'    : eachSegmentSpin,   // Called when the tick sound is to be played.
        'soundTrigger'     : 'pin'        // Specify pins are to trigger the sound.
      },
  'pins' :				// Turn pins on.
      {
        'number'     : 24,
        'fillStyle'  : 'silver',
        'outerRadius': 4,
      }
};

const allOptions = {
  ...options,
  outerRadius: (canvasWidth / 2) - (options.lineWidth || 1)
};

onMounted(() => {
  allOptions.outerRadius = (canvasWidth / 2) - (options.lineWidth || 1);
});

</script>

<style scoped>
/* Define your css here inspect dom to see what ids and classes are available */
</style>

Basic image wheel

<template>
  <VueWinWheel ref="winWheel" :options="allOptions" :canvasWidth="canvasWidth" :canvasHeight="canvasHeight" :stopAt="stopAt" />
  <br/>
  <br/>
  <br/>
  <button @click="spinWinWheel">Random Spin</button>
  <button @click="spinWinWheelStopAt">Defined Spin</button>
</template>

<script setup>
import {VueWinWheel} from '@zohaibtariq/vuewinwheel'
import '@zohaibtariq/vuewinwheel/dist/style.css';
import { ref, onMounted } from 'vue';

const winWheel = ref();

const spinWinWheel = () => {
  spinStartTime = Date.now() // if you miss this sound will not play after first run
  if(winWheel.value)
    winWheel.value.spin() // winWheelInstances is only required for the (2 part wheel)
};

const spinWinWheelStopAt = () => {
  spinStartTime = Date.now() // if you miss this sound will not play after first run
  if(winWheel.value)
    winWheel.value.spinAndStopAt(stopAt)
};

const canvasWidth = 500; // set custom canvas width
const canvasHeight = 500; // set custom canvas height
const stopAt = 3; // Segment at which you want to stop at

let spinningAudio = new Audio('./spinning.mp3'); // update this with your own tik sound
let winnerAudio = new Audio('./winner.mp3'); // update this with your own win sound

// Called when the animation has finished.
function spinStopped(indicatedSegment)
{
  playWinningSound()
  // Display different message if win/lose/bankrupt.
  // this must need to be updated according to your segment text
  if (indicatedSegment.text == 'LOOSE TURN')
    alert('Sorry but you loose a turn.');
  else if (indicatedSegment.text == 'BANKRUPT')
    alert('Oh no, you have gone BANKRUPT!');
  else
    alert("You have won " + indicatedSegment.text);
}

function eachSegmentSpin()
{
  playSpinningSound()
}

let spinStartTime;

function playSpinningSound()
{
  if(!spinStartTime){
    spinStartTime = Date.now(); // this must start when spin starts
  }
  spinningAudio.pause();
  const spinEndTime = Date.now();
  const diffInSpinTime = spinEndTime - spinStartTime
  // do not play this sound if animation time is exceeded
  if(options?.animation?.duration === undefined || diffInSpinTime < ((options.animation.duration * 1000)/1.4)) { // if you observe wheel stop but tik sound continues to play increase value of 1.4 to gradually a higher digit number like 1.5, 1.6 what ever suites you, animation duration and spin setting effects it
    spinningAudio.currentTime = 0;
    spinningAudio.play();
  }
}

function playWinningSound()
{
  winnerAudio.pause();
  winnerAudio.currentTime = 0;
  winnerAudio.play();
}

const options = { // basic_image_wheel
  'numSegments'       : 4,        	// Specify number of segments.
  'outerRadius'       : 150,      	// Set outer radius so wheel fits inside the background.
  'drawMode'          : 'image',  	// drawMode must be set to image.
  'imageSrc'          : "./wheel-colored.png",
  'drawText'          : true,     	// Need to set this true if want code-drawn text on image wheels.
  'textFontSize'      : 24,
  'textOrientation'   : 'curved',		// Note use of curved text.
  'textDirection'     : 'reversed',	// Set other text options as desired.
  'textAlignment'     : 'outer',
  'textMargin'        : 5,
  'textFontFamily'    : 'monospace',
  'textStrokeStyle'   : 'black',
  'textLineWidth'     : 2,
  'textFillStyle'     : 'white',
  'segments'     :                // Define segments.
      [
        {'text' : 'T-55 Vampire'},
        {'text' : 'P-40 Kittyhawk'},
        {'text' : 'North American Harvard'},
        {'text' : 'L-39C Albatross'}
      ],
  'animation' :                   // Specify the animation to use.
      {
        'type'     : 'spinToStop',
        'duration' : 5,     		// Duration in seconds.
        'spins'    : 8,     		// Number of complete spins.
        'callbackFinished' : spinStopped
      }
};

const allOptions = {
  ...options,
  outerRadius: (canvasWidth / 2) - (options.lineWidth || 1)
};

onMounted(() => {
  allOptions.outerRadius = (canvasWidth / 2) - (options.lineWidth || 1);
});

</script>

<style scoped>
/* Define your css here inspect dom to see what ids and classes are available */
</style>

One image per segment

<template>
  <VueWinWheel ref="winWheel" :options="allOptions" :canvasWidth="canvasWidth" :canvasHeight="canvasHeight" :stopAt="stopAt" />
  <br/>
  <br/>
  <br/>
  <button @click="spinWinWheel">Random Spin</button>
  <button @click="spinWinWheelStopAt">Defined Spin</button>
</template>

<script setup>
import {VueWinWheel} from '@zohaibtariq/vuewinwheel'
import '@zohaibtariq/vuewinwheel/dist/style.css';
import { ref, onMounted } from 'vue';

const winWheel = ref();

const spinWinWheel = () => {
  spinStartTime = Date.now() // if you miss this sound will not play after first run
  if(winWheel.value)
    winWheel.value.spin() // winWheelInstances is only required for the (2 part wheel)
};

const spinWinWheelStopAt = () => {
  spinStartTime = Date.now() // if you miss this sound will not play after first run
  if(winWheel.value)
    winWheel.value.spinAndStopAt(stopAt)
};

const canvasWidth = 500; // set custom canvas width
const canvasHeight = 500; // set custom canvas height
const stopAt = 3; // Segment at which you want to stop at

let spinningAudio = new Audio('./spinning.mp3'); // update this with your own tik sound
let winnerAudio = new Audio('./winner.mp3'); // update this with your own win sound

// Called when the animation has finished.
function spinStopped(indicatedSegment)
{
  playWinningSound()
  // Display different message if win/lose/bankrupt.
  // this must need to be updated according to your segment text
  if (indicatedSegment.text == 'LOOSE TURN')
    alert('Sorry but you loose a turn.');
  else if (indicatedSegment.text == 'BANKRUPT')
    alert('Oh no, you have gone BANKRUPT!');
  else
    alert("You have won " + indicatedSegment.text);
}

function eachSegmentSpin()
{
  playSpinningSound()
}

let spinStartTime;

function playSpinningSound()
{
  if(!spinStartTime){
    spinStartTime = Date.now(); // this must start when spin starts
  }
  spinningAudio.pause();
  const spinEndTime = Date.now();
  const diffInSpinTime = spinEndTime - spinStartTime
  // do not play this sound if animation time is exceeded
  if(options?.animation?.duration === undefined || diffInSpinTime < ((options.animation.duration * 1000)/1.4)) { // if you observe wheel stop but tik sound continues to play increase value of 1.4 to gradually a higher digit number like 1.5, 1.6 what ever suites you, animation duration and spin setting effects it
    spinningAudio.currentTime = 0;
    spinningAudio.play();
  }
}

function playWinningSound()
{
  winnerAudio.pause();
  winnerAudio.currentTime = 0;
  winnerAudio.play();
}

const options = { // one_image_per_segment
  'numSegments'       : 8,                // Specify number of segments.
  'outerRadius'       : 200,              // Set outer radius so wheel fits inside the background.
  'drawText'          : true,             // Code drawn text can be used with segment images.
  'textFontSize'      : 16,				// Set text options as desired.
  'textOrientation'   : 'curved',
  'textAlignment'     : 'inner',
  'textMargin'        : 90,
  'textFontFamily'    : 'monospace',
  'textStrokeStyle'   : 'black',
  'textLineWidth'     : 3,
  'textFillStyle'     : 'white',
  'drawMode'          : 'segmentImage',    // Must be segmentImage to draw wheel using one image per segemnt.
  'segments'          :                    // Define segments including image and text.
      [
        {'image' : './tom.png',  'text' : 'Jane'}, // please update tom.png with your image path
        {'image' : './tom.png',   'text' : 'Tom'},
        {'image' : './tom.png',  'text' : 'Mary'},
        {'image' : './tom.png',  'text' : 'Alex'},
        {'image' : './tom.png', 'text' : 'Sarah'},
        {'image' : './tom.png', 'text' : 'Bruce'},
        {'image' : './tom.png',  'text' : 'Rose'},
        {'image' : './tom.png', 'text' : 'Steve'}
      ],
  'animation' :           // Specify the animation to use.
      {
        'type'     : 'spinToStop',
        'duration' : 5,
        'spins'    : 8,
        'callbackFinished' : spinStopped
      }
}

const allOptions = {
  ...options,
  outerRadius: (canvasWidth / 2) - (options.lineWidth || 1)
};

onMounted(() => {
  allOptions.outerRadius = (canvasWidth / 2) - (options.lineWidth || 1);
});

</script>

<style scoped>
/* Define your css here inspect dom to see what ids and classes are available */
</style>

Hollow wheel

<template>
  <VueWinWheel ref="winWheel" :options="allOptions" :canvasWidth="canvasWidth" :canvasHeight="canvasHeight" :stopAt="stopAt" />
  <br/>
  <br/>
  <br/>
  <button @click="spinWinWheel">Random Spin</button>
  <button @click="spinWinWheelStopAt">Defined Spin</button>
</template>

<script setup>
import {VueWinWheel} from '@zohaibtariq/vuewinwheel'
import '@zohaibtariq/vuewinwheel/dist/style.css';
import { ref, onMounted } from 'vue';

const winWheel = ref();

const spinWinWheel = () => {
  spinStartTime = Date.now() // if you miss this sound will not play after first run
  if(winWheel.value)
    winWheel.value.spin() // winWheelInstances is only required for the (2 part wheel)
};

const spinWinWheelStopAt = () => {
  spinStartTime = Date.now() // if you miss this sound will not play after first run
  if(winWheel.value)
    winWheel.value.spinAndStopAt(stopAt)
};

const canvasWidth = 500; // set custom canvas width
const canvasHeight = 500; // set custom canvas height
const stopAt = 3; // Segment at which you want to stop at

let spinningAudio = new Audio('./spinning.mp3'); // update this with your own tik sound
let winnerAudio = new Audio('./winner.mp3'); // update this with your own win sound

// Called when the animation has finished.
function spinStopped(indicatedSegment)
{
  playWinningSound()
  // Display different message if win/lose/bankrupt.
  // this must need to be updated according to your segment text
  if (indicatedSegment.text == 'LOOSE TURN')
    alert('Sorry but you loose a turn.');
  else if (indicatedSegment.text == 'BANKRUPT')
    alert('Oh no, you have gone BANKRUPT!');
  else
    alert("You have won " + indicatedSegment.text);
}

function eachSegmentSpin()
{
  playSpinningSound()
}

let spinStartTime;

function playSpinningSound()
{
  if(!spinStartTime){
    spinStartTime = Date.now(); // this must start when spin starts
  }
  spinningAudio.pause();
  const spinEndTime = Date.now();
  const diffInSpinTime = spinEndTime - spinStartTime
  // do not play this sound if animation time is exceeded
  if(options?.animation?.duration === undefined || diffInSpinTime < ((options.animation.duration * 1000)/1.4)) { // if you observe wheel stop but tik sound continues to play increase value of 1.4 to gradually a higher digit number like 1.5, 1.6 what ever suites you, animation duration and spin setting effects it
    spinningAudio.currentTime = 0;
    spinningAudio.play();
  }
}

function playWinningSound()
{
  winnerAudio.pause();
  winnerAudio.currentTime = 0;
  winnerAudio.play();
}

const options = { // hollow_wheel
  'numSegments'   : 16,   // Specify number of segments.
  'outerRadius'   : 212,  // Set radius to so wheel fits the background.
  'innerRadius'   : 120,  // Set inner radius to make wheel hollow.
  'textFontSize'  : 16,   // Set font size accordingly.
  'textMargin'    : 0,    // Take out default margin.
  'segments'      :       // Define segments including colour and text.
      [
        {'fillStyle' : '#eae56f', 'text' : 'Prize 1'},
        {'fillStyle' : '#89f26e', 'text' : 'Prize 2'},
        {'fillStyle' : '#7de6ef', 'text' : 'Prize 3'},
        {'fillStyle' : '#e7706f', 'text' : 'Prize 4'},
        {'fillStyle' : '#eae56f', 'text' : 'Prize 5'},
        {'fillStyle' : '#89f26e', 'text' : 'Prize 6'},
        {'fillStyle' : '#7de6ef', 'text' : 'Prize 7'},
        {'fillStyle' : '#e7706f', 'text' : 'Prize 8'},
        {'fillStyle' : '#eae56f', 'text' : 'Prize 9'},
        {'fillStyle' : '#89f26e', 'text' : 'Prize 10'},
        {'fillStyle' : '#7de6ef', 'text' : 'Prize 11'},
        {'fillStyle' : '#e7706f', 'text' : 'Prize 12'},
        {'fillStyle' : '#eae56f', 'text' : 'Prize 13'},
        {'fillStyle' : '#89f26e', 'text' : 'Prize 14'},
        {'fillStyle' : '#7de6ef', 'text' : 'Prize 15'},
        {'fillStyle' : '#e7706f', 'text' : 'Prize 16'}
      ],
  'animation' :           // Define spin to stop animation.
      {
        'type'     : 'spinToStop',
        'duration' : 5,
        'spins'    : 8,
        'callbackFinished' : spinStopped
      }
};

const allOptions = {
  ...options,
  outerRadius: (canvasWidth / 2) - (options.lineWidth || 1)
};

onMounted(() => {
  allOptions.outerRadius = (canvasWidth / 2) - (options.lineWidth || 1);
});

</script>

<style scoped>
/* Define your css here inspect dom to see what ids and classes are available */
</style>

2 Part Wheel

<template>
  <VueWinWheel ref="winWheel" :options="allOptions" :canvasWidth="canvasWidth" :canvasHeight="canvasHeight" :stopAt="stopAt" />
  <br/>
  <br/>
  <br/>
  <button @click="spinWinWheel">Random Spin</button>
  <button @click="spinWinWheelStopAt">Defined Spin</button>
</template>

<script setup>
import {VueWinWheel} from '@zohaibtariq/vuewinwheel'
import '@zohaibtariq/vuewinwheel/dist/style.css';
import { ref, onMounted } from 'vue';

const winWheel = ref();

const spinWinWheel = () => {
  spinStartTime = Date.now() // if you miss this sound will not play after first run
  if(winWheel.value)
    winWheel.value.spin(winWheelInstances) // winWheelInstances is only required for the (2 part wheel)
};

const spinWinWheelStopAt = () => {
  spinStartTime = Date.now() // if you miss this sound will not play after first run
  if(winWheel.value)
    winWheel.value.spinAndStopAt(stopAt, winWheelInstances)
};

const canvasWidth = 500; // set custom canvas width
const canvasHeight = 500; // set custom canvas height
const stopAt = 3; // Segment at which you want to stop at

let spinningAudio = new Audio('./spinning.mp3'); // update this with your own tik sound
let winnerAudio = new Audio('./winner.mp3'); // update this with your own win sound

// Called when the animation has finished.
function spinStopped(indicatedSegment)
{
  playWinningSound()
  // Display different message if win/lose/bankrupt.
  // this must need to be updated according to your segment text
  if (indicatedSegment.text == 'LOOSE TURN')
    alert('Sorry but you loose a turn.');
  else if (indicatedSegment.text == 'BANKRUPT')
    alert('Oh no, you have gone BANKRUPT!');
  else
    alert("You have won " + indicatedSegment.text);
}

function eachSegmentSpin()
{
  playSpinningSound()
}

let spinStartTime;

function playSpinningSound()
{
  if(!spinStartTime){
    spinStartTime = Date.now(); // this must start when spin starts
  }
  spinningAudio.pause();
  const spinEndTime = Date.now();
  const diffInSpinTime = spinEndTime - spinStartTime
  // do not play this sound if animation time is exceeded
  if(options?.animation?.duration === undefined || diffInSpinTime < ((options.animation.duration * 1000)/1.4)) { // if you observe wheel stop but tik sound continues to play increase value of 1.4 to gradually a higher digit number like 1.5, 1.6 what ever suites you, animation duration and spin setting effects it
    spinningAudio.currentTime = 0;
    spinningAudio.play();
  }
}

function playWinningSound()
{
  winnerAudio.pause();
  winnerAudio.currentTime = 0;
  winnerAudio.play();
}

const innerWheelOptions = { // two_part_wheel
  'numSegments' : 4,
  'outerRadius' : 110,        // Set the outer radius to make the wheel smaller than the outer wheel.
  'segments': [
    {'fillStyle' : '#eae56f', 'text' : 'Inner 1'},
    {'fillStyle' : '#89f26e', 'text' : 'Inner 2'},
    {'fillStyle' : '#7de6ef', 'text' : 'Inner 3'},
    {'fillStyle' : '#e7706f', 'text' : 'Inner 4'}
  ]
};

const outerWheelOptions = {
  'numSegments': 8,
  'textMargin' : 0,
  'outerRadius' : 210,
  'innerRadius' : 110,    // Set inner radius to the size of the inner wheel since the inner part of the wheel
  'segments': [           //   is being drawn by the inner wheel we don't need to draw there.
    {'fillStyle' : '#8C8A42', 'text' : 'Outer 1'},
    {'fillStyle' : '#F2F0A8', 'text' : 'Outer 2'},
    {'fillStyle' : '#519142', 'text' : 'Outer 3'},
    {'fillStyle' : '#B7F7A8', 'text' : 'Outer 4'},
    {'fillStyle' : '#4B898F', 'text' : 'Outer 5'},
    {'fillStyle' : '#B1EFF5', 'text' : 'Outer 6'},
    {'fillStyle' : '#8A4342', 'text' : 'Outer 7'},
    {'fillStyle' : '#F0A9A8', 'text' : 'Outer 8'}
  ],
  'animation':
      {
        'type': 'spinToStop',                     // Define animation more or less as normal, except for the callbackAfter().
        'duration': 5,
        'spins': 5,
        'easing': 'Power3.easeOut',
        'callbackAfter' : drawInnerWheel,     // Call back after each frame of the animation a function we can draw the inner wheel from.
        'callbackFinished': alertPrize
      }
};

// This function is called after the outer wheel has drawn during the animation.
function drawInnerWheel()
{
  // Update the rotationAngle of the innerWheel to match that of the outer wheel - this is a big part of what
  // links them to appear as one 2-part wheel. Call the draw function passing false so the outer wheel is not wiped.
  innerWinWheelInstance.rotationAngle = outerWinWheelInstance.rotationAngle;
  innerWinWheelInstance.draw(false);
}

// Called when the animation has finished.
function alertPrize()
{
  // The indicated segments from the 2 wheels.
  let winningInnerSegment = innerWinWheelInstance.getIndicatedSegment();
  let winningOuterSegment = outerWinWheelInstance.getIndicatedSegment();

  // Alert the combination of prizes won.
  alert('You won ' + winningInnerSegment.text + ', ' + winningOuterSegment.text);

  // Set things so power and spin button can be clicked again.
  // wheelSpinning = false;

  // Remove all colours from the power level indicators.
  // document.getElementById('pw1').className = "";
  // document.getElementById('pw2').className = "";
  // document.getElementById('pw3').className = "";
}

const options = {
  ...outerWheelOptions,
  innerWheelOptions
};

// this instances code is required only for (2 part wheel)
let outerWinWheelInstance;
let innerWinWheelInstance;

const winWheelInstances = (outerWheelInstance, innerWheelInstance) => {
  if(outerWheelInstance) {
    outerWinWheelInstance = outerWheelInstance
    // Call draw on the outerWheel then the inner wheel to ensure that both are rendered on the canvas.
  }
  if(innerWheelInstance) {
    innerWinWheelInstance = innerWheelInstance
  }
  if(outerWheelInstance && innerWheelInstance) { // now tackled with drawInnerWheel
    // Update the rotationAngle of the innerWheel to match that of the outer wheel - this is a big part of what
    // links them to appear as one 2-part wheel. Call the draw function passing false so the outer wheel is not wiped.
    innerWheelInstance.rotationAngle = outerWheelInstance.rotationAngle;
    if(innerWheelInstance.draw)
      innerWheelInstance.draw(false);
  }
}

const allOptions = {
  ...options,
  outerRadius: (canvasWidth / 2) - (options.lineWidth || 1)
};

onMounted(() => {
  allOptions.outerRadius = (canvasWidth / 2) - (options.lineWidth || 1);
});

</script>

<style scoped>
/* Define your css here inspect dom to see what ids and classes are available */
</style>

DOCS WINWHEEL

Original Author

Douglas McKechie https://github.com/zarocknz

Maintainer

@zohaibtariq https://github.com/zohaibtariq

Please note

This wasn't created by me; It is just a fork of Winwheel.js that supports javascript esm (Ecma Script Modules)