Winwheel.js tutorial: #15 Getting the segment clicked


In this tutorial I will show you how to do something when the user clicks the wheel, such as getting the segment they clicked on and then performing some action as a result of this. There are two methods getSegmentAt() which returns a pointer to the segment object clicked and getSegmentNumberAt() which returns the number of the segment in the wheel's segments array which was clicked.


There are many uses of this if you want to make your wheel interactive. For example if using the wheel as a pie graph you could display more information in a div on the page when one of the segments is clicked, or changing the colour or text of the segment to indicate to the user it has been selected.



Getting the segment clicked - example


In this example I change the background colour of the segment clicked to yellow and also change the innerText of a span next to the "You Clicked:" on the page to contain the text of the segment. If you click on the canvas outside of the wheel then you will see that the span text is blanked.


The getSegmentAt() and getSegmentNumberAt() functions work as expected for hollow wheels (doughnuts) in that the user must click within the bounds of the segment for it to be returned; in a hollow wheel if they click on the blank canvas inside the wheel then no segment object or number is returned.


You clicked: <span id="clickedWhat"></span>

<script>
    let theWheel = new Winwheel({
        'numSegments'   : 8,
        'outerRadius'   : 170,
        'innerRadius'   : 50,
        'textFontSize'  : 14,
        'textMargin'    : 0,
        'segments'      :
        [
           {'fillStyle' : '#eae56f', 'text' : 'Segment 1'},
           {'fillStyle' : '#89f26e', 'text' : 'Segment 2'},
           {'fillStyle' : '#7de6ef', 'text' : 'Segment 3'},
           {'fillStyle' : '#e7706f', 'text' : 'Segment 4'},
           {'fillStyle' : '#eae56f', 'text' : 'Segment 5'},
           {'fillStyle' : '#89f26e', 'text' : 'Segment 6'},
           {'fillStyle' : '#7de6ef', 'text' : 'Segment 7'},
           {'fillStyle' : '#e7706f', 'text' : 'Segment 8'}
        ]
    });

    // Get canvas and span objects.
    let canvas = document.getElementById('canvas');
    let clickedWhat = document.getElementById('clickedWhat');

    // Specify click handler for canvas.
    canvas.onclick = function (e)
    {
        // Call function to reset the segment colours.
        resetSegmentColours();

        // Call the getSegmentAt function passing the mouse x and y from the event.
        let clickedSegment = theWheel.getSegmentAt(e.clientX, e.clientY);

        // A pointer to the segment clicked is returned if the user clicked inside the wheel.
        if (clickedSegment) {
            // Change background colour of the segment and update the wheel.
            clickedSegment.fillStyle = 'yellow';
            theWheel.draw();

            // Update span to say what was clicked.
            clickedWhat.innerText = clickedSegment.text;
        }
    }

    // Resets the segment colours.
    function resetSegmentColours()
    {
        // Reset all colours.
        theWheel.segments[1].fillStyle = '#eae56f';
        theWheel.segments[2].fillStyle = '#89f26e';
        theWheel.segments[3].fillStyle = '#7de6ef';
        theWheel.segments[4].fillStyle = '#e7706f';
        theWheel.segments[5].fillStyle = '#eae56f';
        theWheel.segments[6].fillStyle = '#89f26e';
        theWheel.segments[7].fillStyle = '#7de6ef';
        theWheel.segments[8].fillStyle = '#e7706f';

        // Render changes.
        theWheel.draw();

        // Also blank clicked what text.
        clickedWhat.innerText = "";
    }

</script>


Canvas not supported
Click wheel segments to see getSegmentAt() in action.
You clicked:

Note that you could use a click handler on the canvas as seen above to do other useful things, for example you could spin the wheel when the user clicks it rather than having a spin button off to the side, or pause and resume an animation (spinning) when the user clicks the wheel.


Known issue for this feature

I discovered that adding any padding, border, width or height to the canvas using CSS causes the getSegmentAt calculations to become incorrect meaning that in some cases nothing or the wrong segment is returned as the one clicked.


So don't add padding, borders, width, height to your canvas using CSS. You should always specify the width and height of the canvas on the canvas element itself in the page (otherwise it is scaled like and image and can look bad). If you do require the appearance of padding or border around the canvas then sit the canvas inside another element such as a div and give the div those CSS properties (which is what I do above).


Previous:
< #14 Setting the Prize to be won before spinning
Next:
#16: Creating Pie graphs >