zarocknz / javascript-winwheel Goto Github PK
View Code? Open in Web Editor NEWCreate spinning prize wheels on HTML canvas with Winwheel.js
Home Page: http://dougtesting.net
License: MIT License
Create spinning prize wheels on HTML canvas with Winwheel.js
Home Page: http://dougtesting.net
License: MIT License
Is it possible to rotate the outer wheel in clockwise direction while inner wheel into anti-clockwise direction? If yes, how? Thanks
Hey @zarocknz
This is not an issue but more of a pull request. I finished creating my own version of the winwheel and I was wondering if you can link it on your 'More Examples' section.
Here is the link to the live version: https://billh93.github.io/GrubDecider/
Here is the link to the repository: https://github.com/billh93/GrubDecider
var firstWheel=new Winwheel({
'canvasId' : 'firstcanvas',
'outerRadius' : 170,
'numSegments' : 10,
'innerRadius' : 5,
'textFontSize' : 55,
'textOrientation' : 'vertical',
'textFontFamily' : 'Courier',
'textAlignment' : 'outer',
'textFillStyle' :'#ffffff',
'strokeStyle' :'#ffff00',
'textMargin' : 5,
'segments' :
[
{'fillStyle' : '#ff0000', 'text' : '1'},
{'fillStyle' : '#000000', 'text' : '2'},
{'fillStyle' : '#ff0000', 'text' : '3'},
{'fillStyle' : '#000000', 'text' : '4'},
{'fillStyle' : '#ff0000', 'text' : '5'},
{'fillStyle' : '#000000', 'text' : '6'},
{'fillStyle' : '#ff0000', 'text' : '7'},
{'fillStyle' : '#000000', 'text' : '8'},
{'fillStyle' : '#ff0000', 'text' : '9'}
],
'lineWidth' : 3,
'animation' :
{
'type' : 'spinToStop',
'duration' : 45,
'spins' : 60,
'callbackFinished' :'calculatePrizeOnServer1()',
'callbackAfter' : 'drawTriangle()',
'callbackSound' : 'playSound2()',
'soundTrigger' : 'pin'
},
'pins' :
{
'number' : 20,
'outerRadius' : 5,
'margin' : 5,
'fillStyle' : '#00ff00',
'strokeStyle' : '#ffffff'
}
});
var xhr1 = new XMLHttpRequest();
xhr1.onreadystatechange = ajaxStateChange1;
function calculatePrizeOnServer1(){
xhr1.open('GET',"calculate_price_first_digit.php", true);
xhr1.send('');
}
function ajaxStateChange1(){
if (xhr1.readyState < 4){
return;
}
if (xhr1.status !== 200){
return;
}
if (xhr1.readyState === 4){
var segmentNumber1 = xhr1.responseText;
// segmentNumber1=4;
first_digit=segmentNumber1;
if (segmentNumber1){
segmentNumber1=parseInt(segmentNumber1);
var stopAt1 = firstWheel.getRandomForSegment(segmentNumber1);
firstWheel.animation.stopAngle = stopAt1;
firstWheel.startAnimation();
// highlight_segment(firstWheel,segmentNumber1);
}
else{
var stopAt1 = firstWheel.getRandomForSegment(10);
firstWheel.animation.stopAngle = stopAt1;
firstWheel.startAnimation();
// highlight_segment(firstWheel,10);
}
}
}
drawTriangle();
function drawTriangle(){
var ctx = firstWheel.ctx;
ctx.strokeStyle = 'navy';
ctx.fillStyle = 'aqua';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(190, 10);
ctx.lineTo(190, 70);
ctx.lineTo(200, 90);
ctx.lineTo(210, 70);
ctx.lineTo(210, 10);
ctx.lineTo(190, 10);
ctx.stroke();
ctx.fill();
}
var audio2 = new Audio('sound/Tick.mp3');
function playSound2(){
// audio2.pause();
audio2.currentTime = 0;
audio2.play();
}
the wheel reverse rotated. how to fix this problem. I need to spin only one direction and stop in the defined result segment. It stops in the correct segment but for finding segment it rotates reverse.
In many of the examples, when you press the "Reset wheel" button, this occurs:
theWheel.rotationAngle = 0;
Which unfortunately looks bad, as the wheel resets to its original rotation.
In order to maintain the current position of the wheel when reset, instead of changing the rotation value to "0", it should be like this instead:
theWheel.rotationAngle = theWheel.rotationAngle % 360;
This should allow it to continue animating properly, while maintaining the current rotation.
I need some help to know how can I make it responsive.
Thanks
Hi, Thanks for the awesome job you've done on this plugin. I have not come across another js plugin for a lucky spinning wheel better than this one yet. I'm having an issue with the getIndicatedSegment property when calling the alert prize(); function in an Ionic 3/Angular 2 application. I've followed this issue https://stackoverflow.com/questions/44306571/how-to-use-winwheel-js-callback-in-angular2 and have gotten it to work with the app and spinning quite well.
When the alert prize function is called, I get this error:
TypeError: Cannot read property 'getIndicatedSegment' of undefined
at alertPrize (http://localhost:8100/?ionicplatform=ios:51:41)
at eval (eval at winwheelStopAnimation (http://localhost:8100/build/vendor.js:137240:13), :1:1)
at n.winwheelStopAnimation (http://localhost:8100/build/vendor.js:137240:13)
at n.callback (http://localhost:8100/assets/scripts/TweenMax.min.js:16:22797)
at n..render (http://localhost:8100/assets/scripts/TweenMax.min.js:14:4905)
at Object.n.render (http://localhost:8100/assets/scripts/TweenMax.min.js:16:27269)
at Object.O._updateRoot.D.render (http://localhost:8100/assets/scripts/TweenMax.min.js:16:31859)
at Object.n.dispatchEvent (http://localhost:8100/assets/scripts/TweenMax.min.js:16:19594)
at g (http://localhost:8100/assets/scripts/TweenMax.min.js:16:20122)
I've followed the advice in that answer and added the prize function in my index.html file in order to get access to the Prize callback that is in my page.ts file and show the alert on the basic example to alert the prize. However, when I am trying to access the getIndicatedSegment variable, I get this issue.
Here is the code in my LuckySpinPage.ts file:
export class LuckySpinPage {
constructor(public navCtrl: NavController) { }
wheel;
wheelSpinning = false;
ngAfterViewInit() {
this.initWheel();
}
initWheel() {
this.wheel = new Winwheel({
'numSegments': 10, // Specify number of segments.
'outerRadius': 150, // Set radius to so wheel fits the background.
'innerRadius': 30, // Set inner radius to make wheel hollow.
'pointerAngle': 0,
'pointerGuide': false, // Turn pointer guide on.
'drawMode' : 'segmentImage',
'segments': [
{'image' : '../../assets/images/segment-winner.png'},
{'image' : '../../assets/images/segment-1.png'},
{'image' : '../../assets/images/segment-2.png'},
{'image' : '../../assets/images/segment-3.png'},
{'image' : '../../assets/images/segment-5.png'},
{'image' : '../../assets/images/segment-6.png'},
{'image' : '../../assets/images/segment-7.png'},
{'image' : '../../assets/images/segment-8.png'},
{'image' : '../../assets/images/segment-9.png'},
{'image' : '../../assets/images/segment-10.png'}
],
'animation': // Define spin to stop animation.
{
'type': 'spinToStop',
'duration': 5,
'spins': 10,
'callbackFinished': 'alertPrize()'
}
});
}
// -------------------------------------------------------
// Click handler for spin button.
// -------------------------------------------------------
startSpin() {
// Ensure that spinning can't be clicked again while already running.
if (this.wheelSpinning === false) {
this.wheel.startAnimation();
this.wheelSpinning = true;
}
}
}
The code in the index.html file:
<script> // This function called after the spin animation has stopped. function alertPrize(){ // Call getIndicatedSegment() function to return pointer to the segment pointed to on wheel. var winningSegment = this.wheel.getIndicatedSegment(); // Basic alert of the segment text which is the prize name. alert("You have won " + winningSegment.text + "!"); } </script>My aim is to get the prize on a specific segment e.g alert you've won, when it lands on segment 4, or alert not prize won when landing on any other segment.
Gsap isn't free for any paywalled site. An alternative more open solution would be preferable.
First of thanks for the amazing wheel library, it has everything anyone can imagine. ๐
I used this in ionic app for mobile. I am facing one issue. the animation is so laggy on android & on iOS its good at lest its feels like spinning.
android version i have tested is 4.4
Is there anyway we can improve this?
Hi, can i set default win when user click spin.
thanks
any ideas? I got the wheel responsive by using bootstrap, and a call to the resizeCanvas() function supplied by one of the commenters - but getting the pins to scale seems to be beyond me.
any help appreciated.
thanks
Can I use this js file in ReactJS?
Really loving the winwheel buddy; excellent script! One question, I have managed to completely customise the wheel and it looks great. I was just wandering if you could help with creating a custom modal instead of the AlertPrize{} function, and use the segment name as the model content?
Any help would be appreciated, as I am not an very good coder :)
Thanks!
i need to set like this when its stop spining then its wheel come on center like not any different engle
got this error while using it on vuejs, even the data, etc been mapped to vue format..
installed the winwheel from npm package:
https://www.npmjs.com/package/winwheel
`
<div class="wheel-wrapper">
<div>
<div class="power_controls">
<a href="#" @click.prevent="startSpin()">START</a>
<a href="#" @click.prevent="resetWheel()">Reset</a>
</div>
</div>
<div width="438" height="582" align="center" valign="center">
<canvas id="canvas" width="434" height="434">
<p style="{color: white}" align="center">Sorry, your browser doesn't support canvas. Please try
another.</p>
</canvas>
</div>
</div>
</section>
export default {
name: 'LuckySpin',
data() {
return {
theWheel: new Winwheel({
numSegments: 8, // Specify number of segments.
outerRadius: 212, // Set outer radius so wheel fits inside the background.
textFontSize: 28, // Set font size as desired.
// 'pointerAngle': 90,
// Define segments including colour and text.
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' }
],
// Specify the animation to use.
animation: {
type: 'spinToStop',
duration: 3, // Duration in seconds.
spins: 10, // Number of complete spins.
callbackFinished: this.onFinishSpin
}
}),
wheelPower: 1,
wheelSpinning: false
}
},
methods: {
startSpin() {
if (this.wheelSpinning == false) {
this.theWheel.animation.spins = 10
var stopAt = 46 + Math.floor(Math.random() * 43)
this.theWheel.animation.stopAngle = stopAt
this.theWheel.startAnimation()
this.wheelSpinning = true
}
},
resetWheel() {
this.theWheel.stopAnimation(false) // Stop the animation, false as param so does not call callback function.
this.theWheel.rotationAngle = 0 // Re-set the wheel angle to 0 degrees.
this.theWheel.draw() // Call draw to render changes to the wheel.
this.wheelSpinning = false // Reset to false to power buttons and spin can be clicked again.
},
onFinishSpin(indicatedSegment) {
console.log(indicatedSegment)
alert(indicatedSegment.text)
}
},
computed: {},
updated() {},
mounted() {},
created() {}
May I know how to make the 2 part wheel responsive together with the wheel background? I tried one of the suggestion on last issues but the inner wheel doesn't display when resizing, only theouter wheel is displayed. Thanks in advance.
Sorry, your browser doesn't support canvas. Please try another. |
],
'animation':
{
'type': 'spinToStop', // Define animation more or less as normal, except for the callbackAfter().
'duration': 6,
'spins': 15,
}
});
// Need to create the SECONDARY wheel first because on construct the variable which keeps track of the wheel to animate will
// be set to the last created wheel, and we want the outer one the primary with the animation etc.
var innerWheel = new Winwheel({
'numSegments' : 10,
'outerRadius' : 140, // Set the outer radius to make the wheel smaller than the outer wheel.
'innerRadius' : 20,
'textMargin' : 30,
'segments': [ // is being drawn by the inner wheel we don't need to draw there.
{'fillStyle' : '#8C8A42', 'text' : '0'},
{'fillStyle' : '#F2F0A8', 'text' : '1'},
{'fillStyle' : '#519142', 'text' : '2'},
{'fillStyle' : '#B7F7A8', 'text' : '3'},
{'fillStyle' : '#4B898F', 'text' : '4'},
{'fillStyle' : '#B1EFF5', 'text' : '5'},
{'fillStyle' : '#8A4342', 'text' : '6'},
{'fillStyle' : '#F0A9A8', 'text' : '7'},
{'fillStyle' : '#B1EFF5', 'text' : '8'},
{'fillStyle' : '#8A4342', 'text' : '9'},
],
'animation':
{
'type': 'spinToStop', // Define animation more or less as normal, except for the callbackAfter().
'duration': 8,
'callbackAfter' : drawOuterWheel,
'callbackBefore' : drawInnerMostAgain,
'spins': 15,
}
});
var innerMostWheel = new Winwheel({
'numSegments' : 10,
'outerRadius' : 70, // Set the outer radius to make the wheel smaller than the outer wheel.
'segments': [ // is being drawn by the inner wheel we don't need to draw there.
{'fillStyle' : '#8C8A42', 'text' : '0'},
{'fillStyle' : '#F2F0A8', 'text' : '1'},
{'fillStyle' : '#519142', 'text' : '2'},
{'fillStyle' : '#B7F7A8', 'text' : '3'},
{'fillStyle' : '#4B898F', 'text' : '4'},
{'fillStyle' : '#B1EFF5', 'text' : '5'},
{'fillStyle' : '#8A4342', 'text' : '6'},
{'fillStyle' : '#F0A9A8', 'text' : '7'},
{'fillStyle' : '#B1EFF5', 'text' : '8'},
{'fillStyle' : '#8A4342', 'text' : '9'},
],
'animation':
{
'type': 'spinToStop', // Define animation more or less as normal, except for the callbackAfter().
'duration': 10,
'callbackAfter' : drawOuterWheel,
'callbackBefore' : drawInnerAgain,
'callbackFinished' : alertPrize,
'spins': 15,
}
});
outerWheel.draw();
innerWheel.draw(false);
innerMostWheel.draw(false);
/* function CallInnerAnimation(){
innerWheel.startAnimation();
}
function CallInnerMostAnimation(){
innerMostWheel.startAnimation();
}*/
function drawOuterWheel(){
outerWheel.draw(false);
}
function drawInnerAgain(){
innerWheel.draw(false);
}
function drawInnerMostAgain(){
innerMostWheel.draw(false);
}
// Called when the animation has finished.
function alertPrize()
{
// The the indicated segments from the 2 wheels.
var winningInnerSegment = innerWheel.getIndicatedSegment();
var winningInnerMostSegment = innerMostWheel.getIndicatedSegment();
var winningOuterSegment = outerWheel.getIndicatedSegment();
alert('You won ' + ' Outer Segment : ' + winningOuterSegment.text + ', ' + 'Inner Segment : ' + winningInnerSegment.text + ',' + 'Inner Most Segment : ' + winningInnerMostSegment.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 = "";
}
// ================================================================================================================
// FUNCTIONS FOR power controls below (All this is not necessary to actually create and spin a wheel)....
// Vars used by the code in this page to do power controls.
var wheelPower = 0;
var wheelSpinning = false;
// -------------------------------------------------------
// Function to handle the onClick on the power buttons.
// -------------------------------------------------------
function powerSelected(powerLevel)
{
// Ensure that power can't be changed while wheel is spinning.
if (wheelSpinning == false)
{
// Reset all to grey incase this is not the first time the user has selected the power.
document.getElementById('pw1').className = "";
document.getElementById('pw2').className = "";
document.getElementById('pw3').className = "";
// Now light up all cells below-and-including the one selected by changing the class.
if (powerLevel >= 1)
{
document.getElementById('pw1').className = "pw1";
}
if (powerLevel >= 2)
{
document.getElementById('pw2').className = "pw2";
}
if (powerLevel >= 3)
{
document.getElementById('pw3').className = "pw3";
}
// Set wheelPower var used when spin button is clicked.
wheelPower = powerLevel;
// Light up the spin button by changing it's source image and adding a clickable class to it.
document.getElementById('spin_button').src = "spin_on.png";
document.getElementById('spin_button').className = "clickable";
}
}
function resetWheel()
{
outerWheel.stopAnimation(false); // Stop the animation, false as param so does not call callback function.
outerWheel.rotationAngle = 0; // Re-set the wheel angle to 0 degrees.
outerWheel.draw();
innerWheel.rotationAngle = outerWheel.rotationAngle; // Call draw to render changes to the wheel.
innerWheel.draw(false);
innerMostWheel.rotationAngle = innerWheel.rotationAngle;
innerMostWheel.draw(false);
document.getElementById('pw1').className = ""; // Remove all colours from the power level indicators.
document.getElementById('pw2').className = "";
document.getElementById('pw3').className = "";
wheelSpinning = false; // Reset to false to power buttons and spin can be clicked again.
}
// -------------------------------------------------------
// Click handler for spin button.
// -------------------------------------------------------
function startSpin()
{
if (wheelSpinning == false)
{
if (wheelPower == 1)
{
outerWheel.animation.spins = 3; // Number of spins and/or duration can be altered to make the wheel
}
else if (wheelPower == 2)
{
outerWheel.animation.spins = 8;
}
else if (wheelPower == 3)
{
outerWheel.animation.spins = 15;
}
// Disable the spin button so can't click again while wheel is spinning.
document.getElementById('spin_button').src = "spin_off.png";
document.getElementById('spin_button').className = "";
// Begin the spin animation by calling startAnimation on the wheel object.
outerWheel.startAnimation(0)
innerWheel.startAnimation(1);
innerMostWheel.startAnimation(2);
// Set to true so that power can't be changed and spin button re-enabled during
// the current animation. The user will have to reset before spinning again.
wheelSpinning = true;
}
}
</script>
</body>
It would be great to have html tags or at least text overflown to two lines.
It would wonderful if this could be wrapped in UMD so that you can use this as a script tag, a node module, or AMD/CommonJS require, or ES6/ES2015/Typescript Import.
How i can stop wheel on prize number what was generated from other var or server side?
example i want stopped on segment: Prize 1.
Thanks.
Hi,
You have done a great work with winwheel and I am working on something of similar nature, where I need to rotate the wheel and stop at a particular angle I can see you are uring TweenMax to achieve that. Is there a way it can be done without TweenMax or may be any other library.
While looking in to a query on the SpinOngoing animation I discovered that the defaults as stated in the documentation are not being applied.
Namely the repeat and easing expected are -1 and Linear.EaseNone but because in the constructor of the winwheel 0 is specified for the repeat and power3.easeOut is defined for the easing these are not null so the defaults for the SpinOngoing type of animation are not applied.
Solution is probably to ensure that these are null in the constructor and are only set by a check of the animation type to the default if not specified in the parameters.
How I can import winwheel to an angular 2 app?
A few people have contacted me about how to play a click sound when the edge of a segment passes the pointer, this is also what the pins are supposed to be for but I could never get it to sound right.
Re-look in to the audio thing and at the very least add some way for code to know when the edge of a segment or a pin has passed the pointer so - something - can be done with that, such as play a sound.
Figure out the sound thing later, perhaps leave it up to the developer as they may want to use the audio API or a canned audio file.
If get it working then add a tutorial on this.
Hello.
Would it be possible to make the segment images full size even if the passed in image is too small?
'segments' : // Define segments including image and text.
[
{'image' : 'images/img.png', 'text' : ''},
{'image' : 'images/img.png', 'text' : ''},
{'image' : 'images/img.png', 'text' : ''},
{'image' : 'images/img.png', 'text' : ''},
{'image' : 'images/img.png', 'text' : ''},
{'image' : 'images/img.png', 'text' : ''},
{'image' : 'images/img.png', 'text' : ''},
{'image' : 'images/img.png', 'text' : ''}
],
Maybe a flag would be nice, like: scaleSegmentImages ?
Basically make the segment images fill the containing canvas size.
Thank you :)
Hi Doug!
Thank you so much for building this and releasing it into the wild! I've gone through most of the tutorials and have adapted the winwheel into a faux-chat roulette video selector using images in the spin wheel. Landing on an image pops the alert which then shows 2 hidden divs that play a simulated video chat.
What I'm trying to do now is make sure a viewer doesn't land on the same combination twice - I want them to cycle through all the video stories. I have 7 "people" and 3 spin levels, so 21 combinations of 42 total videos.
Do you have some suggestions for 'turning off' an image segment after it's been used so that the wheel doesn't land on it again? I want to do this by spin level.
Here's a look at my current wheel. As an example, if a viewer chooses the Truth or Dare spin level and the selector lands on Ryan, when they spin again, I don't want Ryan to be available to land on again. If on the next spin they land on Alan, I want Ryan + Alan to no longer be available for the following spins, until all 7 people are finished and they viewer moves on the the next spin level (or they can shift back and forth but I want to maintain the exclusions while they are in current session).
Maybe I need to drop a cookie to keep track? I'm just not sure how to go about this in an efficient way, so any help or insight is greatly appreciated!
Thank you,
Chris
Hi, I first and foremost wanted to thank you for making this script and tutorial easy to comprehend and follow. I had one question about the segments: what I want to do with my wheel is to have each segment open up random pages that relates to each segment. So for example, I have 5 segments on my wheel, and I want my "lets play a game!" Segment to open up random html pages that have games on it, and I want my "lets eat!" Segment to open up random html pages that have recipes, etc. I would like to know how to assign each segment a certain array of pages, and have them correspond to each segment.
i used Outerwheel.animation.stopAngle = number
but in this is not getting complete center its come left and right on segment i need perfect center
There is an issue with the way the current animation loop is implemented where if there is more than one wheel on the page, starting the animation of the second wheel kills the animation of the first.
Need to allow a way for multiple wheels on the same canvas to be animated, and also preferably all wheels on any canvases on the screen.
Think the issue at the moment is just that there is a single variable on the page called winwheelToDrawDuring animation and this needs to change to an array of wheel objects.
The winwheelAnimationLoop() function then needs to loop though the array of wheels to draw and call the draw method in them along with any animation before and after callbacks for the wheel.
Might also need to change the way the winwheelAnimationLoop() function is added to the GreenSock ticker; have this happen outside any particular wheel. This might mean that the ticker is always running and the wheels always updating even when not animated. This could be a good or a bad thing. Might be able to add parameter to the wheel to keep track of the animation state and only re-draw the wheels when animating.
Also look to have at adding all wheels to the array of wheels to draw automatically at time of creation, rather than when animation start is called - unless use this array to add and remove wheels to be animated - i.e. add on animation start, remove on animation end - that might solve the issue above of not wanting to re-draw static wheels.
If this is all sorted also create a "Multiwheel" example for the examples folder and look to create tutorial for this on the site. Check existing animation tutorials too in case they need to be updated.
Thanks again for an amazing plugin!
Question, I have the lineWidth set to 10, and it applies the width correctly to the outer ring, but the inner segments are inconsistent stroke width wise (the center line segment is bigger than the others). Am I missing a setting? Just looking to have consistent stroke widths on all segments. I'm ok with the outer ring and the segments being different.
This plugin looks awesome but I have a few questions that I can't seem to figure out.
I'd like to use PHP to predetermine a winning segment, then have the wheel spin randomly and land on that winner. Would this be possible with this plugin?
I'd like to show little thumbnails of images instead of segment names. Would this be possible as well?
Thanks for the help ๐
Hi Bro,
In file 'calculate_prize.php' at tut14,
I want create one array contain something small prize for return.
What I have to do?
tks!
Make all wheel modes responsive especially the 2 image modes, ensure images both scale up (will probably look bad but oh well) and also scale down.
Consider what options could be included in the constructor to make the wheel responsive, also what code does a developer have to add in to make this work.
Do a full tutorial on this with an example of each drawType (code, image, segmentImage) to test out.
Hi @zarocknz ,
Can i highlight area of winner segment? Or does plugin have function / option to show where a winner segment?
Maybe like this picture :
I want WinWheel highlight winner segment to notify the user.
Thank you ๐
Hey this is not an issue with the code itself. It's more of a question on how to incorporate API's to show on the segments. I managed to insert the object within the array to the winwheel segments key:value pair but I still get errors as it does not load. I get Uncaught TypeError: Cannot read property 'fillStyle' of undefined
.
I have a repo with all of my work but the code is not pretty. It is somewhat short though 200+ lines of code so hopefully you can just tell me what am I doing wrong and how I can make the data load from my Google Places API.
Here is the link to my repo
Thanks!
It's either on
or off
canvasId: 'lumifish-wheel', numSegments: 24, outerRadius: outerRadius, innerRadius: innerRadius, textFontFamily: '\'Roboto\', sans-serif', textFontSize: 22, textFontWeight: '900', textAlignment: 'outer', fillStyle: '#fff', textFillStyle: '#fff', lineWidth: 15, // ain't doing nothin'
Now what's up with that?
Secondly, why can't I have just an outline around the wheel, but ignore the inner outline for the segments?
I kinda need the pins to be sitting out on the white outline around the wheel.
For example: 2 outer segments have 1 inner
Use dummy values to try : http://echoes.stargazer.co.in/events/encryption.php
Hi, first of all I want to thank you for your work, is really great, the documentation is fantastic!
Now, I created a wheel and set the pointerAngle equal to 90 to put it on the right side of the wheel, I use the pointerGuide helper to check it and everythings is ok.
The issue comes when i set an stopAngle using the getRandomForSegment() this stop the wheel in the segment i want but pointing to the top, so the getIndicatedSegment() shows me an incorrect information and the pointer is pointing the incorrect segment.
I've read all the documentation to check if there's an option to set the final direction of the selected segment to be at the same direction of the pointerAngle and I couldn't find a solution. Maybe I miss something.
If you can help me with this I would appreciate it greatly.
Thank you
Calling stop animation errors if the animation has not run before.
Issue is in WinwheelStopAnimation tries to kill the tween of the WinwheelToAnimate but if the animation has not run before the Winwheel to animate is null.
Add check that the wheel to animate exists before trying to make a call to kill the tween.
Once i spin the wheel then its sniping after display alert message i need to spin again without reset wheel its possible ?
<!-- Plus Minus button -->
<link rel="stylesheet" href="../js/plusminusbutton/style.css" />
<script src="../js/plusminusbutton/script.js"></script>
<!-- Wheel of fortune -->
<script src="../js/javascript-winwheel-2.7.0/Winwheel.js" ></script>
<script src="../js/javascript-winwheel-2.7.0/TweenMax.min.js"></script>
<!-- Toggle Switch -->
<link href="../css/bootstrap-toggle.min.css" rel="stylesheet">
<script src="../js/bootstrap-toggle.min.js"></script>
<!-- Datatable -->
<link rel="stylesheet" href="../css/dataTables.bootstrap4.min.css">
<script src="../js/jquery.dataTables.min.js" ></script>
<script src="../js/dataTables.bootstrap4.min.js" ></script>
<script src="../js/dom-text.js" ></script>
<style>
hr {
margin-top: 1rem;
margin-bottom: 1rem;
border: 0;
border-top: 2px solid rgba(0, 0, 0, 0.1);
}
#canvasContainer {
position: relative;
width: 300px;
height:0;
}
#canvas {
z-index: 1;
}
#prizePointer {
position: absolute;
left: 175px;
top: -12px;
z-index: 999;
}
#wheelSpinner {
position: absolute;
left: 150px;
top: 150px;
cursor:pointer;
background-color:#DAA520
}
#wheelSpinner{
display: inline-block;
text-decoration: none;
background: gold;
color: #FFF;
font-size:3em;
width: 120px;
height: 120px;
line-height: 120px;
border-radius: 50%;
text-align: center;
font-weight: bold;
vertical-align: middle;
overflow: hidden;
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.29);
border-bottom: solid 3px #bd6565;
transition: .4s;
}
#wheelSpinner:active{
-ms-transform: translateY(2px);
-webkit-transform: translateY(2px);
transform: translateY(2px);
box-shadow: 0 0 1px rgba(0, 0, 0, 0.15);
border-bottom: none;
}
#center {
position: absolute;
z-index: 15;
top: 50%;
left: 50%;
margin: -100px 0 0 -150px;
}
@media screen and (max-width: 600px) {
table.winner_list{
display:none;
}
table.winner_list{
background:gold;
position:fixed;
z-index:999;
}
table.winner_list td{
border-top:1px solid black;
}
}
@media only screen and (min-width:600px) {
.hide-on-desktop{
display: none;
}
}
.show_toggle:active table.winner_list{
display:block;
}
.show_toggle:active .hide-on-desktop{
display:none;
}
table.winner_list{
}
table.winner_list thead> tr >th{
background:gold;
color:black;
padding:20px;
letter-spacing: 3px;
}
table.winner_list tbody td {
border-bottom:2px solid gold;
color:green;
text-transform:uppercase;
font-style: oblique;
text-align:center;
}
body{
background: #d9a7c7; /* fallback for old browsers /
background: -webkit-linear-gradient(to right, #fffcdc, #d9a7c7); / Chrome 10-25, Safari 5.1-6 /
background: linear-gradient(to right, #fffcdc, #d9a7c7); / W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}
</style> <script> $(document).ready(function() { var theWheel=null;
var dataZ=null;
var table = $('#referalUserListTable').DataTable( {
"columnDefs": [
{
"targets": [3],
"orderDataType": "dom-text"
},{
"targets": [0],
"orderable": false
}
]
} );
updateWheel();
updateWinnerList();
$('.modal').on('hidden.bs.modal', function () {
// location.reload();
updateWheel();
updateWinnerList();
})
} );
function updateReferalTableWinner(userId_){
$.ajax({
type : 'GET',
url : '../phpfunctions/luckydraw.php?',
data : {updateReferalTableWinner:'true',userId:userId_},
success: function (data) {
},
error: function(xhr, status, error) {
console.log(error);
}
});
}
function updateReferalTable(userId_,str){
var qty_=str.value;
if(qty_>0)
$.ajax({
type : 'GET',
url : '../phpfunctions/luckydraw.php?',
data : {updateReferalTable:'true',userId:userId_,qty:qty_},
success: function (data) {
console.log(data);
},
error: function(xhr, status, error) {
console.log(error);
}
});
}
function updateWheel(){
$.ajax({
type : 'GET',
url : '../phpfunctions/luckydraw.php?',
data : {getEligleUserForContest:'true'},
success: function (data) {
//console.log(data);
if(data!='null' ){
data=JSON.parse(data);
// console.log(data);
var qty=data.length;
createWheel(data);
}
},
error: function(xhr, status, error) {
console.log(error);
}
});
}
function updateWinnerList(){
$.ajax({
type : 'GET',
url : '../phpfunctions/luckydraw.php?',
data : {getWinnerList:'true'},
success: function (data) {
if(data!=null){
data=JSON.parse(data);
$("table.winner_list tbody").empty();
var dataRow="";
$.each(data, function(index, obj){
dataRow+="<tr><td>"+obj.shortName+" ("+obj.memberId+")</td></tr>";
});
$("table.winner_list tbody").html(dataRow);
}
},
error: function(xhr, status, error) {
console.log(error);
}
});
}
Sorry, your browser doesn't support canvas. Please try another.
SPIN <img id="prizePointer" src="../js/javascript-winwheel-2.7.0/resources/basic_pointer.png" alt="V" />
</div>
</div>
<div class="show_toggle" >
<a class="btn hide-on-desktop" id="button-winner-list" style="background:gold;position:fixed;z-index:9999; border:1px solid blue;color:white;user-select: none; ">WINNERS</a>
<table class="winner_list" >
<thead>
<tr>
<th style="user-select: none; ">
TODAY's <i class="fa fa-trophy fa-3x" style="color:black" aria-hidden="true"></i> WINNER
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<?php
$eventDate = date('Y-m-d',strtotime('2018-12-28'));
$todayDate= date("Y-m-d");
if($todayDate==$eventDate){
echo '<img src="../resources/Merry-Christmas-Text-PNG-Clipart.png" style="z-index:-100;position:fixed;width:45%;height:50%;right:0px;top:25%;"/>';
}
?>
<script>
// Create new wheel object specifying the parameters at creation time.
/* function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
*/
function createWheel(data){
dataZ=data;
var qty=data.length;
var participants=[];
$.each(data, function(index, obj){
participants.push({'fillStyle' : obj.color,'text':obj.memberId});
});
theWheel = new Winwheel({
'numSegments' : qty, // Specify number of segments.
'outerRadius' : 200, // Set outer radius so wheel fits inside the background.
'centerX' : 200, // correctly position the wheel
'centerY' : 200, // over the background.
'textFontSize' : 28, // Set font size as desired.
'segments' : // Define segments including colour and text.
// [
participants,
// {'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' : '#7de6ef', 'text' : 'Prize 8'},
// {'fillStyle' : '#7de6ef', 'text' : 'Prize 9'},
// {'fillStyle' : '#e7706f', 'text' : 'Prize 10'}
//],
'pins' : {
'outerRadius' : 5,
'margin' : 10,
'fillStyle' : 'gold'
},
'animation' : // Specify the animation to use.
{
'type' : 'spinToStop',
'duration' : 10, // Duration in seconds.
'spins' : 10, // Number of complete spins.
'callbackSound' : playSound, // Specify function to call when sound is to be triggered
'soundTrigger' : 'pin', // Pins trigger the sound for this animation.
'callbackFinished' : alertPrize
}
});
}
var audio = new Audio('../js/javascript-winwheel-2.7.0/resources/tick.mp3'); // Create audio object and load desired file.
function playSound()
{
// Stop and rewind the sound (stops it if already playing).
audio.pause();
audio.currentTime = 0;
// Play the sound.
audio.play();
}
// Vars used by the code in this page to do power controls.
var wheelPower = 0;
var wheelSpinning = false;
// -------------------------------------------------------
// Function to handle the onClick on the power buttons.
// -------------------------------------------------------
function powerSelected(powerLevel)
{
// Ensure that power can't be changed while wheel is spinning.
if (wheelSpinning == false)
{
// Reset all to grey incase this is not the first time the user has selected the power.
document.getElementById('pw1').className = "";
document.getElementById('pw2').className = "";
document.getElementById('pw3').className = "";
// Now light up all cells below-and-including the one selected by changing the class.
if (powerLevel >= 1)
{
document.getElementById('pw1').className = "pw1";
}
if (powerLevel >= 2)
{
document.getElementById('pw2').className = "pw2";
}
if (powerLevel >= 3)
{
document.getElementById('pw3').className = "pw3";
}
// Set wheelPower var used when spin button is clicked.
wheelPower = powerLevel;
// Light up the spin button by changing it's source image and adding a clickable class to it.
//document.getElementById('spin_button').src = "spin_on.png";
// document.getElementById('spin_button').className = "clickable";
}
}
// -------------------------------------------------------
// Click handler for spin button.
// -------------------------------------------------------
function startSpin()
{
// Ensure that spinning can't be clicked again while already running.
if (wheelSpinning == false)
{
// Based on the power level selected adjust the number of spins for the wheel, the more times is has
// to rotate with the duration of the animation the quicker the wheel spins.
if (wheelPower == 1)
{
theWheel.animation.spins = 3;
}
else if (wheelPower == 2)
{
theWheel.animation.spins = 8;
}
else if (wheelPower == 3)
{
theWheel.animation.spins = 15;
}
// Disable the spin button so can't click again while wheel is spinning.
// document.getElementById('spin_button').src = "spin_off.png";
// document.getElementById('spin_button').className = "";
// Begin the spin animation by calling startAnimation on the wheel object.
theWheel.startAnimation();
// Set to true so that power can't be changed and spin button re-enabled during
// the current animation. The user will have to reset before spinning again.
wheelSpinning = true;
}
}
// -------------------------------------------------------
// Function for reset button.
// -------------------------------------------------------
function resetWheel()
{
theWheel.stopAnimation(false); // Stop the animation, false as param so does not call callback function.
theWheel.rotationAngle = 0; // Re-set the wheel angle to 0 degrees.
theWheel.draw(); // Call draw to render changes to the wheel.
// document.getElementById('pw1').className = ""; // Remove all colours from the power level indicators.
// document.getElementById('pw2').className = "";
// document.getElementById('pw3').className = "";
wheelSpinning = false; // Reset to false to power buttons and spin can be clicked again.
}
// -------------------------------------------------------
// Called when the spin animation has finished by the callback feature of the wheel because I specified callback in the parameters
// note the indicated segment is passed in as a parmeter as 99% of the time you will want to know this to inform the user of their prize.
// -------------------------------------------------------
function alertPrize(indicatedSegment)
{
$.each(dataZ, function(index, obj){
if(obj.memberId==indicatedSegment.text){
$("#winner_name").text(obj.name);
$("#winner_memberId").text(obj.memberId);
updateReferalTableWinner(obj.userId);
return false;
}
});
$("#winnerModal").modal();
wheelSpinning = false;
// Do basic alert of the segment text. You would probably want to do something more interesting with this information.
// alert("You have won " + indicatedSegment.text);
}
</script>
<div class="modal-body" >
<div style="text-align:center" >
<i class="fa fa-star" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
<i class="fa fa-star" aria-hidden="true"></i>
<br/>
<i class="fa fa-trophy fa-5x" style="color:gold" aria-hidden="true"></i>
<br/>
<h5 id="winner_memberId" class="display-5"><h5>
<hr/>
<h3 class="display-3" id="winner_name"></h3>
</table>
</div>
</div>
</div>
</div>
</div>
<!--WINNER modal END-->
<!--USER LIST UPDATE REFERAL modal START-->
<div class="modal fade " id="referalUserListModal" tabindex="-1" role="dialog" aria-labelledby="referalUserListModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-full" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="referalUserListModalLongTitle">UPDATE USERS REFERAL</h5>
</div>
<div class="modal-body">
<div class="table-responsive" >
<?php
echo referalUserListTable();
?>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary btn-block" data-dismiss="modal" >
CLOSE
</button>
</div>
</div>
</div>
</div>
<!--USER LIST UPDATE REFERAL modal END-->
https://gist.github.com/phazei/0c480197c778373cf8dd566f09a004dd
no longer needed, but for anyone else who might like
Hi,
I am using wineheel.js for my project and I would like to have the option that my clients may upload their company logo and it will be set at the center of the wheel (of course if it's a hollow wheel). Now, can anybody please guide me how can I modify this library in order to have this feature? Because I don't think for now this library have this feature.
Regards,
Junaid
Hi,
I am using two part wheel example. Here my goal is to pick the random winners (Multiple winners) based on were the outer and inner wheel segements stops, not based on the pointer .
So I am making inner wheel rotation angle to minus of outer wheel angle.
innerWheel.rotationAngle = -outerWheel.rotationAngle;
After making above change both inner and outer wheel animates in reverse order. Once the both wheel stops, the position or segments of the inner and outer wheel stops at little random place not in same line.
Can you please suggest How I can stops both wheel segments in same line or aligned. You can see the attached image how the inner wheel segments stops and outer wheel.
Also attached HTML as txt file for reference.
index.txt
Hello Doug!
This is the wheel I've been searching for days and finally found it. This is working great on every browser and almost all devices I've tested. One thing I'm looking forward to have in this is a probability value for each segment. So, that I can offer expensive gifts in a low probable segment and cheaper prices in high probable segments.
Is this doable with your WinWheel ?
Thanks again!
Tharindu
Is it possible to put one image on each sector?
@zarocknz first of all, I want to thank you for your work, is really great, the documentation is very good!
I referred "http://dougtesting.net/winwheel/docs/tut14_setting_the_prize" and tried to set the prize before the spin. I want to stop in first segments as always. But it didn't work. Am I missing anything?
// Spin JS Start
// Create new wheel object specifying the parameters at creation time.
var theWheel = new Winwheel({
'numSegments': 3, // Specify number of segments.
'outerRadius': 0, // Set outer radius so wheel fits inside the background.
'drawMode': 'image',
'segments': [{
'text': 'Prize 1'
}, {
'text': 'Prize 2'
}, {
'text': 'Prize 3'
}
],
'animation': // Specify the animation to use.
{
'type': 'spinToStop',
'duration': 5, // Duration in seconds.
'spins': 8, // Number of complete spins.
'callbackFinished': alertPrize,
'callbackSound': playSound
}
});
var audio = new Audio('./assets/img/tick.mp3');
function playSound() {
// Stop and rewind the sound (stops it if already playing).
audio.pause();
audio.currentTime = 0;
// Play the sound.
audio.play();
}
// Create new image object in memory.
var loadedImg = new Image();
// Create callback to execute once the image has finished loading.
loadedImg.onload = function () {
theWheel.wheelImage = loadedImg; // Make wheelImage equal the loaded image object.
theWheel.draw(); // Also call draw function to render the wheel.
}
// Set the image source, once complete this will trigger the onLoad callback (above).
loadedImg.src = "./assets/img/planes.png";
// Vars used by the code in this page to do power controls.
var wheelPower = 0;
var wheelSpinning = false;
// -------------------------------------------------------
// Click handler for spin button.
// -------------------------------------------------------
function startSpin() {
// Ensure that spinning can't be clicked again while already running.
if (wheelSpinning == false) {
theWheel.animation.spins = 5;
$("#spin-form input").prop('disabled', true);
// Begin the spin animation by calling startAnimation on the wheel object.
theWheel.startAnimation();
// Set to true so that power can't be changed and spin button re-enabled during
// the current animation. The user will have to reset before spinning again.
wheelSpinning = true;
}
}
// Function with the formula to work out stopAngle before spinning animation.
// Called from Click of the Spin button.
function calculatePrize() {
var stopAt = theWheel.getRandomForSegment(1);
theWheel.animation.stopAngle = stopAt;
theWheel.startAnimation();
}
// -------------------------------------------------------
// Called when the spin animation has finished by the callback feature of the wheel because I specified callback in the parameters.
// note the indicated segment is passed in as a parameter as 99% of the time you will want to know this to inform the user of their prize.
// -------------------------------------------------------
function alertPrize(indicatedSegment) {
// Do basic alert of the segment text. You would probably want to do something more interesting with this information.
alert("The wheel stopped on " + indicatedSegment.text);
$('#discode').val(indicatedSegment.text);
}
// Spin JS End
Actually i am using this wheel for a lottery event
so i want to stop the wheel on a specific segment where i want is that possible ?
Hi
Thanks for your hard work and helping us with Winwheel.js
Maybe you can help me with winwheel js.
I am using index.html code copied from http://dougtesting.net/winwheel/examples/wheel_of_fortune
Also included in the same directory Winwheel.js
But when i open index.html i am getting an error "WInwheel is not defined"
https://img.hurtom.com/i/2019/04/image1bdc2f3e7ea2f264.png
Coudl you please advise why it is so.
Thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.