HTML5 Холст Jittery - PullRequest
       3

HTML5 Холст Jittery

0 голосов
/ 26 сентября 2019

Я в основном рисую холст, затем перерисовываю его соответственно, здесь много манипуляций с изображениями, холст в настоящее время очень нервный при нажатии кнопки, я чувствую, что есть лучший способ добиться этогото, что у меня сейчас есть:

var w = window.innerWidth
    || document.documentElement.clientWidth
    || document.body.clientWidth;

var h = window.innerHeight
    || document.documentElement.clientHeight
    || document.body.clientHeight;

var redrawCanvas = true;
var drawAnimatedDial = false;

// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// MIT license
(function () {

    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame']
            || window[vendors[x] + 'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function (callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function () { callback(currTime + timeToCall); },
                timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function (id) {
            clearTimeout(id);
        };
}());

if (w == 1920 && h > 900) {
    (function main() {

        //Image path variables.
        var imageSources = {
            backgroundPath: './graphics/background_safe_minigame.png',
            safePath: './graphics/safe_minigame.png',
            dialBackgroundPath: './graphics/support_safe_dial_minigame.png',
            safeDialPath: './graphics/safe_dial_minigame.png',
            safeScreenPath: './graphics/screen_safe_minigame.png',
            ledPath: './graphics/leds_safe_dial_minigame.png'
        };

        var animatedImages = [],
            canvas;

        function animationLoop() {
            var i;
            window.requestAnimationFrame(animationLoop);

            if (redrawCanvas = true) {
                drawCanvas();
                redrawCanvas = false;
            }

            for (i = 0; i < animatedImages.length; i++) {
                animatedImages[i].update();
                animatedImages[i].render();
            }
        }

        function animateImage(img) {

            var image = {},
                frameIndex = 0,
                tickCounter = 0,
                ticksPerFrame = img.ticksPerFrame || 0,
                numberOfFrames = img.numberOfFrames || 1;

            image.context = img.context;
            image.width = img.width;
            image.height = img.height;
            image.x = 0;
            image.y = 0;
            image.image = img.image;
            image.scaleRatio = 1;

            image.update = function () {

                tickCounter += 1;

                if (tickCounter > ticksPerFrame) {

                    tickCounter = 0;

                    // If the current frame index is in range
                    if (frameIndex < numberOfFrames - 1) {
                        // Go to the next frame
                        frameIndex += 1;
                    } else {
                        frameIndex = 0;
                    }
                }
            };

            image.render = function () {

                // Draw the animation
                image.context.drawImage(
                    image.image,
                    frameIndex * image.width / numberOfFrames,
                    0,
                    image.width / numberOfFrames,
                    image.height,
                    image.x,
                    image.y,
                    image.width / numberOfFrames * image.scaleRatio,
                    image.height * image.scaleRatio);
            };

            image.getFrameWidth = function () {
                return image.width / numberOfFrames;
            };
            return image;
        }

        function LEDAnimation(x, y, scale) {

            var ledIndex,
                ledImage;

            // Create sprite sheet
            ledImage = new Image();
            ledIndex = animatedImages.length;

            // Create sprite
            animatedImages[ledIndex] = animateImage({
                context: canvas.getContext("2d"),
                width: 354,
                height: 44,
                image: ledImage,
                numberOfFrames: 3,
                ticksPerFrame: 25
            });

            animatedImages[ledIndex].x = x;
            animatedImages[ledIndex].y = y;
            animatedImages[ledIndex].scaleRatio = scale;

            // Load sprite sheet
            ledImage.src = './graphics/leds_safe_dial_minigame.png';
        }

        function spinButtonAnimate(x, y, scale) {
            var spinButtonIndex,
                spinButtonImage;

            // Create sprite sheet
            spinButtonImage = new Image();
            spinButtonIndex = animatedImages.length;

            // Create sprite
            animatedImages[spinButtonIndex] = animateImage({
                context: canvas.getContext("2d"),
                width: 144,
                height: 61,
                image: spinButtonImage,
                numberOfFrames: 2,
                ticksPerFrame: 25
            });

            animatedImages[spinButtonIndex].x = x;
            animatedImages[spinButtonIndex].y = y;
            animatedImages[spinButtonIndex].scaleRatio = scale;

            // Load sprite sheet
            spinButtonImage.src = './graphics/text_spin_safe_dial_minigame.png';
        }

        function safeSparkAnimation(x, y, scale) {
            var safeSparkIndex,
                safeSparkImage;

            // Create sprite sheet
            safeSparkImage = new Image();
            safeSparkIndex = animatedImages.length;

            // Create sprite
            animatedImages[safeSparkIndex] = animateImage({
                context: canvas.getContext("2d"),
                width: 498,
                height: 249,
                image: safeSparkImage,
                numberOfFrames: 2,
                ticksPerFrame: 25
            });

            animatedImages[safeSparkIndex].x = x;
            animatedImages[safeSparkIndex].y = y;
            animatedImages[safeSparkIndex].scaleRatio = scale;

            // Load sprite sheet
            safeSparkImage.src = './graphics/spark_safe.png';
        }

        function safeSpinnerAnimation(x, y, scale) {

            var safeSpinnerIndex,
                safeSpinnerImage;

            // Create sprite sheet
            safeSpinnerImage = new Image();
            safeSpinnerIndex = animatedImages.length;

            // Create sprite
            animatedImages[safeSpinnerIndex] = animateImage({
                context: canvas.getContext("2d"),
                width: 550,
                height: 275,
                image: safeSpinnerImage,
                numberOfFrames: 2,
                ticksPerFrame: 50
            });

            animatedImages[safeSpinnerIndex].x = x;
            animatedImages[safeSpinnerIndex].y = y;
            animatedImages[safeSpinnerIndex].scaleRatio = scale;

            // Load sprite sheet
            safeSpinnerImage.src = './graphics/safe_dial_minigame.png';
        }

        function drawCanvas() {
            c = canvas.getContext("2d");

            /**
             * Draws initial Spin prompt text.
             */
            c.fillStyle = 'BLACK';
            c.font = '28px TitanOne';
            c.fillText('Match a pair of symbols for a safe busting multiplier!', 320, 105);
            c.font = '28px TitanOne';
            c.fillText('TOUCH THE DIAL TO SPIN YOUR 4 DIGIT COMBINATION', 335, 135);

            //Draws initial safe scren text.
            c.fillStyle = 'WHITE';
            c.font = '74px TitanOne';
            c.fillText('- - - -', 890, 285);

            //Safe variables.
            var safeXValue = 315,
                safeYValue = 220,
                numXValue = 385,
                numYValue = 305,
                safeNum = 1;

            c.font = '45px TitanOne';
            c.fillStyle = 'WHITE';

            //Images
            var backgroundImage = new Image(),
                safeImage = new Image(),
                dialBackground = new Image(),
                safeDial = new Image(),
                safeScreen = new Image();

            backgroundImage.onload = function () {
                c.drawImage(backgroundImage, canvas.width / 2 - backgroundImage.width / 2, canvas.height / 2 - backgroundImage.height / 2);
            }

            safeImage.onload = function () {
                for (i = 0; i < 3; i++) {
                    c.drawImage(safeImage, safeXValue, safeYValue);
                    c.fillText(safeNum, numXValue, numYValue);
                    safeNum += 1; safeXValue += 170; numXValue += 170;

                    c.drawImage(safeImage, safeXValue, safeYValue);
                    c.fillText(safeNum, numXValue, numYValue);
                    safeNum += 1; safeXValue += 170; numXValue += 170;

                    c.drawImage(safeImage, safeXValue, safeYValue);
                    c.fillText(safeNum, numXValue, numYValue);
                    safeNum += 1; safeXValue += 170; numXValue += 170;

                    safeXValue = 315; safeYValue += 140;
                    numXValue = 385; numYValue += 140;
                }
            }

            dialBackground.onload = function () {
                c.drawImage(dialBackground, 850, 315);
            }

            if (drawAnimatedDial == false) {
                safeDial.onload = function () {
                    c.drawImage(safeDial, 0, 0, 275, 275, 859, 353, 275, 275);
                }
            }

            safeScreen.onload = function () {
                c.drawImage(safeScreen, 838, 215);
            }

            backgroundImage.src = imageSources.backgroundPath;
            safeImage.src = imageSources.safePath;
            dialBackground.src = imageSources.dialBackgroundPath;
            safeDial.src = imageSources.safeDialPath;
            safeScreen.src = imageSources.safeScreenPath;
        }

        function getElementPosition(element) {

            var parentOffset,
                pos = {
                    x: element.offsetLeft,
                    y: element.offsetTop
                };

            if (element.offsetParent) {
                parentOffset = getElementPosition(element.offsetParent);
                pos.x += parentOffset.x;
                pos.y += parentOffset.y;
            }
            return pos;
        }

        function distance(p1, p2) {

            var dx = p1.x - p2.x,
                dy = p1.y - p2.y;

            return Math.sqrt(dx * dx + dy * dy);
        }

        function click(e) {

            var loc = {},
                tapDistance,
                canvasPosition = getElementPosition(canvas),
                tapX = e.targetTouches ? e.targetTouches[0].pageX : e.pageX,
                tapY = e.targetTouches ? e.targetTouches[0].pageY : e.pageY;

            loc.x = (tapX - canvasPosition.x);
            loc.y = (tapY - canvasPosition.y);

            // Distance between tap and spin button
            tapDistance = distance({
                x: (animatedImages[2].x + animatedImages[2].getFrameWidth() / 2 * animatedImages[2].scaleRatio),
                y: (animatedImages[2].y + animatedImages[2].getFrameWidth() / 2 * animatedImages[2].scaleRatio)
            }, {
                    x: loc.x,
                    y: loc.y
                });

            // Check for click of spin button.  
            if (tapDistance < animatedImages[2].getFrameWidth() / 2 * animatedImages[2].scaleRatio) {
                drawAnimatedDial = true;
                animatedImages = [];
                main();
                spin();
            }
        }

        // Get canvas
        canvas = document.getElementById("safeBusterCanvas");
        //Sets the Canvas Width.
        canvas.width = window.innerWidth * .75;
        //Sets the Canvas Height.
        canvas.height = window.innerHeight * .75;

        sparkX = [910, 845, 825, 855, 925, 1010, 1074, 1081, 1024];
        sparkY = [313, 365, 450, 530, 572, 564, 504, 394, 321];

        if (drawAnimatedDial == false) {
            LEDAnimation(850, 300, 1);
            LEDAnimation(1025, 300, 1);
            spinButtonAnimate(966, 462, .84);

            if (sparkX.length == sparkY.length) {
                for (i = 0; i < sparkX.length; i++) {
                    safeSparkAnimation(sparkX[i], sparkY[i], .4);
                }
            }
            animationLoop();
        }

        if (drawAnimatedDial == true) {
            LEDAnimation(850, 300, 1);
            LEDAnimation(1025, 300, 1);
            safeSpinnerAnimation(859, 353, 1);
            spinButtonAnimate(966, 462, .84);
            animationLoop();
        }

        canvas.addEventListener("touchstart", click);
        canvas.addEventListener("mousedown", click);

    }());

} else {
    var resMessage = document.getElementsByClassName("resolutionMessage");
    resMessage[0].style.display = "block";
    document.getElementById("safeBusterCanvas").style.display = "none";
}

Пока холст загружает изображения и выполняет несколько анимаций, как только браузер обнаруживает щелчок по одной из анимаций, холст перерисовывается и анимациянарисован там, где изначально было изображение.

Есть ли лучший способ сделать это, чем непрерывно перерисовывать весь холст?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...