Winwheel.js tutorial: #9 Creating a Wheel with an Image
In this tutorial we will cover how to create a wheel using a single graphically rich image, such as a png, where the entire circle of the wheel, segments, and perhaps even the text is just part of one image.
We will also cover how to use code-drawn text with image wheels if desired, and cover other important things like how to match up the segments in the image with where the code thinks the segments are - which is vital if the Prize Detection, Get Segment Clicked, and other features are going to be used.
The properties involved for creating a wheel using an image are:
- drawMode
- wheelImage
These can only be set globally for the whole wheel.
Explanation and Example
To create a wheel using an image, you must first create the image which you would like to be used for the face of the wheel in your favourite image editing program.
Normally this is a circle with a number of segments and in the segments are the details of the prizes etc. The wheel image can be as graphically rich as you desire, containing photos, text, artwork or whatever. PNG images with the same width and height and a transparent background work best.
To get the Winwheel code to use the image you need to set the drawMode property to 'image', then assign an image object to the wheelImage property.
It's only possible to draw the wheel using the image once the image has loaded and been assigned to the wheelImage property, trying to draw the wheel before this will not work. For this reason, you must call the draw() function of the wheel after setting the wheelImage.
The example code below shows how to create the wheel, then correctly draw it once the image has loaded using an onLoad callback on the image.
// Create the wheel let theWheel = new Winwheel({ 'drawMode' : 'image' // drawMode must be set to image. }); // Create new image object in memory. let 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 = "some_image.png";
In this example the image on the left is loaded the face of the wheel on the right. I have added some spin animation.
Matching code segments with image segments
If you plan to use code generated text with the image wheel, the Prize Detection, Get Segment Clicked, or any Pre-determined spin options (where the prize the user is to win is set before spinning) then you need to match up where the code thinks the segments are with where they are displayed in the image.
Tip: the easiest way I have found to make sure the segments in image wheels match code drawn segments is to use the default (code) draw method of the Winwheel, setting the size of the wheel and number of segments etc as desired then print screen the output and use this as a guide layer or start of your wheel image in your image editing software.
To check if where the code thinks the segments are match the image, set the imageOverlay property to true either in the parameters passed to the Winwheel constructor, or by using the dot operator after the wheel has been created and then calling the draw() method (to render the change).
Setting imageOverlay to true actually just tells the Winwheel class to code draw the outline of the segments over the top of the image, so you can control the line colour and width of the overlay by setting the strokeStyle and lineWidth properties of the wheel.
The next step is to set the numSegments property to the number of segments in the image. If things match then that is all there is to it, if not then then try setting the size property of each segment to the number of degrees that of arc the segment is to take up. Remember that the segments are drawn clockwise so setting the size of the first segment will cause the size of the other segments to automatically adjust if no size has been specifically set for them.
The following examples show turning the imageOverlay on, specifying the number of segments, and matching the segments to the images. In the first example the segments are all the same size so no segment specific parameters need to be entered, in the second a few of the segments are different sizes to the others, so in this case the size property of them needs to be specified.
// Create the first wheel, all segments the same size. let firstWheel = new Winwheel({ 'drawMode' : 'image', // drawMode must be set to image. 'numSegments' : 4, // The number of segments must be specified. 'imageOverlay' : true, // Set imageOverlay to true to display the overlay. 'lineWidth' : 4, // Overlay uses wheel line width and stroke style so can set these 'strokeStyle' : 'red' // as desired to change appearance of the overlay. }); // Create new image object in memory. let firstImg = new Image(); // Create callback to execute once the image has finished loading. firstImg.onload = function() { firstWheel.wheelImage = firstImg; // Make wheelImage equal the loaded image object. firstWheel.draw(); // Also call draw function to render the wheel. } // Set the image source, once complete this will trigger the onLoad callback (above). firstImg.src = "first_image.png"; // ----------------------------- // Create second wheel where some of the segments are different sizes to the others. let secondWheel = new Winwheel({ 'drawMode' : 'image', // drawMode must be set to image. 'numSegments' : 7, // The number of segments must be specified. 'imageOverlay' : true, // Set imageOverlay to true to display the overlay. 'segments' : // Pass in segment parameters (text is optional, not displayed). [ {'text' : '1'}, {'text' : '2', 'size' : 30}, // 30 degrees size. {'text' : '3'}, {'text' : '4', 'size' : 15}, // 15 degrees. {'text' : '5'}, {'text' : '6', 'size' : 30}, // 30 degrees size. {'text' : '7'} ] }); // Create new image object in memory. let secondImg = new Image(); // Create callback to execute once the image has finished loading. secondImg.onload = function() { secondWheel.wheelImage = secondImg; // Make wheelImage equal the loaded image object. secondWheel.draw(); // Also call draw function to render the wheel. } // Set the image source, once complete this will trigger the onLoad callback (above). secondImg.src = "second_image.png";
Example #1: segments same size | Example #2: different sized segments |
You might also need to alter the outerRadius and innerRadius properties of the wheel in order to make the overlay the same size as the image.
Using code-drawn text on an image wheel
If desired, you can use code-drawn text with image wheels. This gives you the best of both worlds as it allows you to create graphically rich wheels using images, but the flexibility of dynamic text rendered by code which can easily be changed.
To show code-drawn text simply set the text property of the segments as normal, but also set the drawText property of the wheel to true, either by passing it in as a parameter to the constructor or by using the dot operator to set it on the Winwheel object after has been created.
let theWheel = new Winwheel({ 'canvasId' : 'imageNtext', 'drawMode' : 'image', 'drawText' : true, // Set this to true for text to be rendered for image wheels. 'numSegments' : 4, 'textOrientation' : 'curved', // Set text properties. 'textAlignment' : 'outer', 'textMargin' : 5, 'textFontFamily' : 'courier', 'segments' : // Set segment text [ {'text' : 'Television'}, {'text' : 'Mobile Phone'}, {'text' : 'Old Radio'}, {'text' : 'Computer'} ] }); let wheelImg = new Image(); wheelImg.onload = function() { theWheel.wheelImage = wheelImg; theWheel.draw(); } wheelImg.src = "wheel_image.png";
Creating a Wheel with one Image per Segement
If you are interested in creating a wheel out of images you might also want to take a look at Winwheel Tutorial #17: Creating a Wheel with one Image per Segement which details how to do that.
Previous: < #8 Wheel Radius and Center Point |
Next: #10: Prize Pointers and Wheel Backgrounds > |