在画布上创建弹跳框动画

时间:2014-10-14 10:41:23

标签: javascript animation canvas html5-canvas

我需要创建一个掉落框的动画,当它到达画布上的某个Y点时应该反弹10次,每次比前一次低两倍。所以我有下降框的动画,但我不能让弹跳工作。以下是我写的函数:

function dropBox(y, width, height) {
    var img_box = new Image();
    img_box.src = 'images/gift_box_small.png';

    var box_y_pos = y;
    if(y==0)
        box_y_pos = y-img_box.naturalHeight;


    img_box.onload = function(){
        ctx_overlay.save();
        ctx_overlay.clearRect(0,0,width,height);
        ctx_overlay.drawImage(img_box, (width/2)-(img_box.naturalWidth/2), box_y_pos);
        ctx_overlay.restore();
    }

    box_y_pos += 3;

    var box_bottom_position = box_y_pos - img_box.naturalHeight;

    if(box_y_pos+img_box.naturalHeight<height-25)
        var loopTimer = setTimeout(function() {dropBox(box_y_pos, width, height)},24);
    else
        bounceBox(img_box, box_y_pos, box_y_pos, (height/2)-(img_box.naturalHeight/2), "up");

}

function bounceBox(img, img_final_pos, y, midway_pos, direction){
    var midway = midway_pos;
    var direction = direction;
    var img_y_pos = y;

    img.onload = function(){
        ctx_overlay.save();
        ctx_overlay.clearRect(0,0,docWidth,docHeight);
        ctx_overlay.drawImage(img, (docWidth/2)-(img.naturalWidth/2), img_y_pos);
        ctx_overlay.restore();
    }

    for(var i = 0; i < 10; i++){
        if(direction=="up"){
            //going up
            if(img_y_pos>midway_){
                img_y_pos -= 3;
                var loopTimer = setTimeout(function() {bounceBox(img, img_final_pos, img_y_pos, midway_pos, "up")},24);
            } else {
                img_y_pos += 3;
                midway = Math.floor(midway /= 2);
                if(midway%2>0)
                    midway += 1;
                var loopTimer = setTimeout(function() {bounceBox(img, img_final_pos, img_y_pos, midway_pos, "down")},24);
            }
        } else {
            //going down
            if(img_y_pos < img_final_pos){
                img_y_pos += 3;
                var loopTimer = setTimeout(function() {bounceBox(img, img_final_pos, img_y_pos, midway_pos, "down")},24);
            } 
        }
    }
}

JSFiddle:http://jsfiddle.net/n2derqgw/3/

为什么它不起作用,我怎样才能使它工作?

1 个答案:

答案 0 :(得分:1)

为了避免让人头疼,您最好在使用setInterval调用的单个函数中处理动画 并将所有与动画相关的数据保存在一个对象中 所以下面的代码并不完全符合您的要求,但应该让您入门:

http://jsfiddle.net/n2derqgw/4/

设置:

var canvas_overlay, ctx_overlay, docWidth, docHeight;

var img_box = new Image();
img_box.src = 'http://corkeynet.com/test/images/gift_box_small.png';

var mustBeReadyCount = 2; // must load image and window

img_box.onload = launchWhenReady;
window.onload = launchWhenReady;

var animationStep = '';
var boxAnimationData = {
    animationStep: '',
    y: 0,
    maxY: 0,
    bounceCount: 6,
    direction: -1,
    bounceHeight: 0
};

function launchWhenReady() {
    mustBeReadyCount--;
    if (mustBeReadyCount) return;
    docWidth = window.innerWidth;
    docHeight = window.innerHeight;
    canvas_overlay = document.getElementById('canvas_overlay');
    ctx_overlay = canvas_overlay.getContext('2d');
    resizeCanvas(docWidth, docHeight);
    boxAnimationData.animationStep = 'falling';
    boxAnimationData.bounceHeight = docHeight / 2 - img_box.height;
    setInterval(animateBox, 30);
};

更有趣的代码在这里:

function animateBox() {
    if (boxAnimationData.animationStep == 'falling') dropBox();
    else if (boxAnimationData.animationStep == 'bouncing') bounceBox();
}

function dropBox() {
    ctx_overlay.clearRect(0, 0, docWidth, docHeight);
    boxAnimationData.y += 3;
    if (boxAnimationData.y + img_box.height > docHeight) {
        boxAnimationData.animationStep = 'bouncing';
    }
    ctx_overlay.drawImage(img_box, (docWidth / 2) - (img_box.width / 2), boxAnimationData.y);
}


function bounceBox() {
    ctx_overlay.clearRect(0, 0, docWidth, docHeight);
    boxAnimationData.y += boxAnimationData.direction * 3;
    if (boxAnimationData.y + img_box.height > docHeight) {
        // reached floor ? swap direction
        boxAnimationData.direction *= -1;
        //  and reduce jump height
        boxAnimationData.bounceHeight *= 3 / 2;
        boxAnimationData.bounceCount--;
        if (!boxAnimationData.bounceCount) boxAnimationData.animationStep = '';

    } else if (boxAnimationData.y < boxAnimationData.bounceHeight) {
        boxAnimationData.direction *= -1;
    }
    ctx_overlay.drawImage(img_box, (docWidth / 2) - (img_box.width / 2), boxAnimationData.y);
}