Canvass' carousel draw

Canvass' carousel draw

 

1. Sorting

(1) the rotary table is mainly the product position

/ / sAngle start radian baseRadian product default radian [option.canvas / 2.25 large circle radius

                    let tranX = 0 + Math.cos(sAngle + _option.baseRadian / 2) * _option.canvasH / 2.25;
                    let tranY = 0 + Math.sin(sAngle + _option.baseRadian / 2) * _option.canvasH / 2.25;
                    context.translate(tranX, tranY);
                    context.rotate(sAngle + _option.baseRadian / 2 + Math.PI / 2);

(2) add return after clearnterval, or it will be executed several times more, which will cause inaccuracy

(3) there are two pictures loaded on the turntable, one is the outer frame and the other is the inner one. When clicking, the middle picture will flash,

Here we use a canvas to draw a picture in advance, and then draw the canvas every time we redraw it

(4) the first time Firefox records that the middle button is not displayed will appear. See the code in detail

2. Code

    <script>
        /* 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    1 Lottery steps - (1) create the initialization method initLucky() to declare all the parameters needed to obtain ajax (temporarily simulated with fake data)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (2)Draw the outermost border only once
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (3)Draw the middle sector and product information, beautify the information display
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (4)Draw start selection button only draws once
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (5)Bind the click method and determine whether the click range with the user is within the selection button,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                At the same time, you can pop up several times according to the demand selection (the selection times must be active), and calculate the product according to the background return result
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (6)Use setTimeOut or requestAnimationFrame (first used set)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Personal judgment stop is based on the rotation radian. If it exceeds this radian, it will stop. (judgment will have some errors, to be improved)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (7) Callback function, the product information will pop up after success 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    2 Problem - (1) button blinks when redrawing - Double cache try (OK)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (2) The first painting doesn't show any ghost... (adjust the painting order, and it turns out that sometimes there is, sometimes there is no)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (2.5) The problem is still because of the image loading... Firefox has a problem (gave up)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (3) Check that the judgment in the punishment area of the incident has not written
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     red  firstUpdate 2018/7/17 22:36  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          lastUpdate  2018/7/18 16:25      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        */

        function initLucky(options) {
            //Put all the required variables in one object
            // console.log(options.textlist)
            let defaultOption = initOption(options);
            drawBorder(defaultOption);
            //Initialization objects consider whether to use constructors or methods to write initialization (consider only saving variables or selecting methods)
            function initOption(_option) {
                var optionA = {
                    canvas: document.getElementById(`${_option.id}`), //object
                    canvasW: document.getElementById(`${_option.id}`).parentNode.offsetWidth, //Wide this refers to windows!!! I'm afraid there are mistakes in strict mode 
                    canvasH: document.getElementById(`${_option.id}`).parentNode.offsetHeight, //high
                    context: canvas.getContext("2d"), //Context object
                    productsList: _option.textlist, //Product list
                    // Lengthaa: "option. Textlist. Length, / / can't get this.productsList why? This points to windows!!!
                    baseRadian: Math.PI / 180 * 360 / _option.textlist.length, //Default radian
                    backgroundImg: _option.backgroundImg, // Background picture
                    clickImg: _option.clickImg, //Click button picture
                    alternateColor: _option.alternateColor, //Alternate colors
                    alternateColor2: _option.alternateColor2, //Alternate color 2
                    stratRadian: _option.stratRadian, //Enlightenment arc
                    wordSub: _option.wordSub, //Intercepts the length of the string (substring () I use)
                    timer: "", // Save setinterval
                    roateRadian: 0, // The angle of rotation
                    luckPosition: 0, //Winning position
                    successId: _option.successId, //Win pop-up message box
                    cacheImg: "",
                    frequency: _option.frequency, //Limit the number of sweepstakes
                    flagTimes: 0, //Set permissions can only be clicked once
                }
                //Set the width and height of canvas
                optionA.canvas.width = optionA.canvasW;
                optionA.canvas.height = optionA.canvasH;
                createCache(optionA);
                return optionA;
            } //end


            //Try to talk about double cache on the Internet due to picture flicker
            function createCache(_option) {
                if (!_option.cacheImg) {
                    let cacheCanvas = document.createElement("canvas");
                    let cacheContext = cacheCanvas.getContext("2d");
                    let img = new Image();
                    img.onload = function () {
                        cacheCanvas.width = _option.canvasH / 3.2 * (img.width / img.height);
                        cacheCanvas.height = _option.canvasH / 3.2;
                        cacheContext.drawImage(img, 0, 0,
                            _option.canvasH / 3.2 * (img.width / img.height),
                            _option.canvasH / 3.2);
                        // _option.cacheImg = cacheCanvas; / / if the image is loaded and the assignment is completed, an error will be reported
                    }
                    img.src = _option.clickImg;
                    _option.cacheImg = cacheCanvas; //This will not report an error, but the clicked image will disappear. Currently, it only appears in Firefox
                }
            } //end
            //Draw outermost border
            function drawBorder(_option) {
                //Because the plug-in's own prompt is context. For convenience, assign a value
                let context = _option.context;
                //Let the basic points of all figures be in the middle
                context.translate(_option.canvasW / 2, _option.canvasH / 2);
                //Preservation
                context.save();
                context.beginPath();
                let img = new Image();
                img.onload = function () {
                    if (_option.cacheImg) {
                        //Since the figure given is a rectangle, I have absolutely made the radius in units of height
                        context.drawImage(img, -_option.canvasH / 2, -_option.canvasH / 2, _option.canvasH,
                            _option
                            .canvasH);
                        //ps due to the first loading, the picture may not be recorded 
                        //It's a little stupid to do this. Who has a better way? Please contact me 578024797
                        let img2 = new Image();
                        img2.onload = function () {
                            //It was meant to be written outside, but because of the hierarchical order, it can only be written inside
                            drawProducts(_option);
                            //Click events
                            registeClick(_option);
                        }
                       img2.src= _option.clickImg;

                    }

                }
                img.src = _option.backgroundImg;

                //recovery
                context.restore();
            } //end

            //Product drawing
            function drawProducts(_option) {
                let context = _option.context;
                //Preservation
                for (let index = 0; index < _option.productsList.length; index++) {
                    let sAngle = _option.baseRadian * index + _option.stratRadian;
                    context.save();
                    context.beginPath();
                    context.rotate(_option.roateRadian * Math.PI / 180); //When setting out, just adjust the angle of the page, please watch
                    //Judge colors
                    if (index % 2 === 0) {
                        context.fillStyle = _option.alternateColor;
                        // context.fillStyle = "#000"; //test
                    } else {
                        context.fillStyle = _option.alternateColor2;
                    }

                    //There is a bit of error in the distance between the top and bottom of ps. how do I always feel that is the reason for the background map
                    //Draw the great circle
                    context.arc(0, 0, _option.canvasH / 2.25, sAngle, sAngle + _option.baseRadian, false);
                    //Draw small circles              
                    context.arc(0, 0, _option.canvasH / 6.5, sAngle + _option.baseRadian, sAngle, false);

                    context.fill();
                    //Product drawing               
                    context.fillStyle = "#fff";
                    let fontWeight = _option.canvasH / 100 * 5; //Text fit according to canvas width
                    let lineHeight = _option.canvasH / 15; //Row height
                    context.font = `${fontWeight}px Microsoft YaHei`;
                    let tranX = 0 + Math.cos(sAngle + _option.baseRadian / 2) * _option.canvasH / 2.25;
                    let tranY = 0 + Math.sin(sAngle + _option.baseRadian / 2) * _option.canvasH / 2.25;
                    context.translate(tranX, tranY);
                    context.rotate(sAngle + _option.baseRadian / 2 + Math.PI / 2);
                    let textTimes = Math.ceil(_option.productsList[index].length / _option.wordSub)
                    for (let j = 0; j < textTimes; j++) {
                        context.fillText(_option.productsList[index].substring(_option.wordSub * j, _option.wordSub *
                                (
                                    j + 1)), -context.measureText(
                                _option.productsList[index]
                                .substring(_option.wordSub * j, _option.wordSub * (j + 1))).width / 2,
                            lineHeight *
                            (j + 1));
                    }

                    context.restore();
                }
                //Draw click button F
                drawClick(_option);
            } //end

            //Draw click button
            function drawClick(_option) {
                _option.context.drawImage(_option.cacheImg, 0 - _option.cacheImg.width / 2, 0 - (_option.cacheImg
                    .height /
                    2) - ((1 - (_option.cacheImg.width / _option.cacheImg.height)) * _option.cacheImg.height /
                    2));
                //Old scheme deleted by mistake
                // let img = new Image();
                // img.onload = function () {
                //     //This code calculates the ratio of width to height of the picture so that the displayed picture is in the same proportion and then absolutely centered
                //     _option.context.drawImage(img, 0 - (_option.canvasH / 3.2 * (img.width / img.height)) / 2,
                //         0 - _option.canvasH / 6.4 - (1 - (img.width / img.height)) * _option.canvasH / 6.4,
                //         _option.canvasH / 3.2 * (img.width / img.height),
                //         _option.canvasH / 3.2);
                //     //Register after click time load 
                //registeClick(_option);
                // }
                // img.src = _option.clickImg;
            } //end



            //Register click event to judge that the trigger event is not in the coordinate range of clickImg (last write) 
            //Click and execute ajax to get the winning array first, then rotate to the winning position according to the data (fixed first)
            function registeClick(_option) {
                _option.canvas.onclick = function () {
                    console.log(_option.flagTimes);
                    if (_option.flagTimes < _option.frequency) {
                        _option.flagTimes++;
                        /* 
                            Execute ajax here to get the prize. I'll use fake data instead                    
                         */
                        let lucy = "Ha ha, just be happy"; //Simulated prize
                        let position = _option.productsList.indexOf(lucy) //Prize location
                        _option.luckPosition = position; //Bind Awards
                        console.log(_option.luckPosition); //test

                        // drawClick(_option);
                        _option.timer = setInterval(function () {
                            //Judgment formula ra angle * radian > = 360 radian * number of turns (since the starting angle of the pointer upward turntable starts from 90 clockwise) 
                            //-90 degrees - half the default angle - product position  
                            //The accuracy of the position is not verified, but it seems to be almost the same
                            // It's a bad speed change. It's time to update
                            if (_option.roateRadian * Math.PI / 180 <= Math.PI * 2 * 2 - Math.PI /
                                2 -
                                _option.baseRadian /
                                2 - _option.baseRadian * _option.luckPosition) {
                                _option.roateRadian += 5;
                            } else if (_option.roateRadian * Math.PI / 180 <= Math.PI * 2 * 2.5 -
                                Math.PI /
                                2 -
                                _option.baseRadian / 2 -
                                _option.baseRadian *
                                _option.luckPosition) {
                                _option.roateRadian += 3;
                            } else if (_option.roateRadian * Math.PI / 180 >= Math.PI * 2 * 3 -
                                Math.PI / 2 -
                                _option.baseRadian / 2 - _option.baseRadian *
                                _option.luckPosition) {
                                clearPromise(_option).then(function (result) {
                                    //Recovery angle
                                    _option.roateRadian = 0;
                                    //Delay 0.8 seconds to execute award winning method
                                    setTimeout(() => {
                                        console.log(result);
                                        success(_option)
                                    }, 800);

                                }).catch(function () {
                                    console.log("Wrong.")
                                });

                                return; //If you do not add return, you will execute it several times after clearing!!!
                            } else {
                                _option.roateRadian += 1;
                            }
                            drawProducts(_option);
                        }) //set end
                    }
                } //onclick end
            } // end

            //Used to clear interval
            function clearPromise(_option) {
                clearInterval(_option.timer);
                return new Promise(function (resolve, reject) {
                    resolve('OK');
                });
            } //end
            //Successfully pop up the message because the page didn't write first
            function success(_option) {
                if (_option.successId) {
                    let succ = document.getElementById(_option.successId);
                    succ.style.display = 'block';
                    $("#code").barcode("13756606900", "code128", {
                        barWidth: 2,
                        barHeight: 80,
                        moduleSize: 5,
                        showHRI: false,
                        addQuietZone: true,
                        marginHRI: 0,
                        bgColor: "",
                        color: "#000",
                        fontSize: 12,
                        output: "css",
                        posX: 0,
                        posY: 0
                    });
                }
            }//end
        }

        window.onload = function () {
            var option = {
                id: "canvas",
                textlist: ["Dad's here", "I'll give your father an orange", "Hold it,I'll leave you the oranges", "Ha ha, just be happy",
                    "Hello, I'm Hello, everyone", "Adasiva Kunis", "nihao", "ooo", "22", "333", "44", "55"
                ],
                backgroundImg: "./images/background.jpg",
                clickImg: "./images/turn.png",
                alternateColor: "#7575ff",
                alternateColor2: "#5f59ff",
                stratRadian: Math.PI / 180 * 0,
                wordSub: 3,
                successId: "okokok",
                frequency: 1,
            }
            initLucky(option);
        }
        //call
    </script>

    

3.github address https://github.com/a578024797/lucky finally file

Tags: Firefox Windows github

Posted on Fri, 31 Jan 2020 09:46:22 -0500 by leewad