Я в основном рисую холст, затем перерисовываю его соответственно, здесь много манипуляций с изображениями, холст в настоящее время очень нервный при нажатии кнопки, я чувствую, что есть лучший способ добиться этогото, что у меня сейчас есть:
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";
}
Пока холст загружает изображения и выполняет несколько анимаций, как только браузер обнаруживает щелчок по одной из анимаций, холст перерисовывается и анимациянарисован там, где изначально было изображение.
Есть ли лучший способ сделать это, чем непрерывно перерисовывать весь холст?