使用带有canvas和javascript的if语句循环框架

时间:2016-10-06 06:01:55

标签: javascript function loops canvas requestanimationframe

我正在构建一个带有无限动画循环的相框。这是一个彩色矩形,每个边框都会打开。它是使用纯Javascript构建的,框架在画布上绘制。

如何永久重新创建效果?我希望这个框架能够永远地继续下去。

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');


 var objectSpeed = 8;

 var recTop = {
   x: -300,
    y: 0,
    width: 300,
    height: 20,
    isMoving: true

  };

 var recRight = {
     x: 480,
     y: -480,
    width: 20,
      height: 300,
    isMoving:false

 };

var recBottom = {
    x: 500,
   y: 480,
   width: 300,
    height: 20,
    isMoving:false

 };

 var recLeft = {
    x: 0,
    y: 500,
    width: 20,
    height: 300,
     isMoving:false

   };

 function drawRecTop(recTop, context) {
  context.beginPath();
   context.rect(recTop.x, recTop.y, recTop.width, recTop.height);
   context.fillStyle = '#FB0202';
   context.fill();

}


 function drawRecRight(recRight, context) {
     context.beginPath();
     context.rect(recRight.x , recRight.y , recRight.width, recRight.height);
      context.fillStyle = '#FB0202';
      context.fill();

    }

 function drawRecBottom(recBottom, context) {
     context.beginPath();
     context.rect(recBottom.x , recBottom.y , recBottom.width, recBottom.height);
     context.fillStyle = '#FB0202';
      context.fill();

}

  function drawRecLeft(recLeft, context) {
    context.beginPath();
    context.rect(recLeft.x , recLeft.y , recLeft.width, recLeft.height);
    context.fillStyle = '#FB0202';
     context.fill();

}


  var squareXSpeed = objectSpeed;
   var squareYSpeed = objectSpeed;


function animate(myRectangle, canvas, context, startTime) {


    if(recTop.x > canvas.width - recTop.width && !recRight.isMoving){
        //START RIGHT RECTANGLE MOVEMENT
       recRight.isMoving = true;
       recRight.y = - recRight.height + recRight.width;

    }



      if(recRight.y > canvas.height - recRight.height && !recBottom.isMoving){
        //START BOTTOM RECTANGLE MOVEMENT
       recBottom.isMoving = true;
       recBottom.x = canvas.width-recBottom.height;

     }



    if(recBottom.x < 0 && !recLeft.isMoving){
        //START LEFT RECTANGLE MOVEMENT
        // recLeft.y = - recLeft.width + recLeft.height;
          recLeft.isMoving = true;
         recLeft.y = canvas.height-recLeft.width;

      }


    if(recLeft.y < 0 && !recTop.isMoving){
        //START BOTTOM RECTANGLE MOVEMENT
       recTop.isMoving = true;
        recTop.x = -(canvas.width - recTop.width);
    }

    if(recTop.x > canvas.width && recLeft.isMoving){
       //TOP RECTANGLE HAS LEFT THE STAGE
       recTop.isMoving = false;

     }



    if(recTop.isMoving)recTop.x += objectSpeed;
     if(recRight.isMoving)recRight.y += objectSpeed;
     if(recBottom.isMoving)recBottom.x -= objectSpeed;
     if(recLeft.isMoving)recLeft.y -= objectSpeed;

// clear
context.clearRect(0, 0, canvas.width, canvas.height);

   drawRecTop(recTop, context);
   drawRecRight(recRight, context);
   drawRecBottom(recBottom, context);
    drawRecLeft(recLeft, context);


// request new frame
   requestAnimFrame(function() {
        animate(recLeft, canvas, context, startTime);
   });

}

这是我到目前为止所得到的: https://jsfiddle.net/jwp9ya5w/

1 个答案:

答案 0 :(得分:1)

在画布上链接动画。

查看代码,逻辑中存在问题。循环时必须重置所有动画。而不是指向需要修改的代码,我将为画布提供一种更灵活的动画制作方法。

使用事件将动画链接在一起

动画并不像刚刚开始结束那么简单,你需要根据屏幕大小,用户交互等来链接动画。为此,您可以创建检查特定条件的事件,并调用函数(如果为true)。

灵活的动画

此外,您从未真正了解动画的外观和感觉。很多时候这个概念与现实不符,你需要修改动画。如果您在代码中设置了太多逻辑,这可能会非常耗时。

为了更轻松地修改动画,您可以分离出所有各个部分。有渲染(特定动画项目的样子),然后是关键帧和定义关键帧的属性。定时功能,用于控制动画的当前状态并检查事件。

动画项目

动画项表示从头到尾的一个动画。它有一个开始和结束关键帧,具有一组动画属性。对所有动画通用的更新函数采用两个关键帧并计算当前帧。然后它调用事件列表中的项目并触发任何需要的项目。有一个绘制函数,它使用当前状态绘制所需的内容,以及一个启动函数,它通过设置开始时间和重置所有事件来启动动画。

这是一个动画项目

的示例
    {
        animate : ["x","y","w","h"],// what to animate
        draw : drawFunc,            // function to draw
        update : animateFunc,       // function to set current anim state
        start : startFunc,          // function to start the animation
        startTime : null,           // this item's start time
        length : timePerSide,       // how long in seconds this animation is
        events : [{                 // list of events
                fired : false,      // true if fired ( to stop it from repeating)
                callback : null,    // callback to call when event fires
                // this function determines when to fire the event
                check : function(owner,time){
                    if(owner.current.x >= canvas.width - owner.current.w){
                        this.fired = true;
                        this.callback(time);
                    }
                },
            }
        ],
        current : {}, // defined when running holds the current state
        startKey : {  // the key frame defining the start position
            x : -boxLength,
            y : 0,
            w : boxLength,
            h : boxHeight,
        },
        endKey : {   // keyframe for end
            x : canvas.width,
            y : 0,
            w : boxLength,
            h : boxHeight,
        }
    },

通过更改关键帧设置可以轻松更改动画。如果你需要更改渲染,你只需要更改绘制功能,如果你需要添加一个额外的可动画值,你只需将它添加到开始和结束关键帧,在animate数组中列出并更改绘制功能包括新属性。

事件是一个数组,因此可以很多,并且可以依赖于任何类型的条件。对于你的动画我有4个动画项目,沿着边缘移动一个框。每个项目都有一个事件,用于检查当前框是否已到达另一侧并调用下一个项目start。这将在当前结束之前开始下一个动画。

外部看起来可能比你的代码复杂一点,但使用这样的系统可以很容易地对动画进行更改。

该片段显示了用于创建动画的方法。它有很多评论,可以根据您的特定需求进行调整。

&#13;
&#13;
// create and add canvas
var createImage=function(w,h){var i=document.createElement("canvas");i.width=w;i.height=h;i.ctx=i.getContext("2d");return i;}
var canvas = createImage(200,200);
var ctx = canvas.ctx;
document.body.appendChild(canvas);




//==============================================================================
// common properties

const boxAnimProps = ["x","y","w","h"]; // List of keyframe properties to animate
const boxHeight = 10; // width of box if looking at it on the sides
const boxLength = 100; // length of box
const timePerSide = 2;  // time to animate each item


//==============================================================================
// common functions
// this function updates the time and check for events
const animateFunc = function(time){
    var i,prop;
    if(!this.started){
        return;
    }
    // set local (this item's) time 
    lTime = time - this.startTime;  // adjust to start time
    // set time clamped to start and end
    lTime = this.current.time = lTime < 0 ? 0 : lTime > this.length ? this.length: lTime;
    // normalise the time 0-1
    var nTime = lTime / this.length;
    for(i = 0; i < this.animate.length; i ++){
        prop = this.animate[i];
        this.current[prop] = (this.endKey[prop]-this.startKey[prop]) * nTime + this.startKey[prop];
    }
    // check for events
    for(i = 0; i < this.events.length; i ++){
        if(!this.events[i].fired){
            this.events[i].check(this,time);
        }
    }
};
// function starts an animtion item and resets any events it has
const startFunc = function(time){
    this.started = true;
    this.startTime = time;
    // reset events
    for(var i = 0;i < this.events.length; i ++){ 
        this.events[i].fired = false;
    }
}
// this function draws the item
const drawFunc = function(ctx){
    if(!this.started){
        return;
    }
    ctx.fillRect(this.current.x,this.current.y,this.current.w,this.current.h);
    
}



//==============================================================================
// the animation. Time is in seconds
// animation.start starts the animation
// animation.update(ctx,time) to update

var animation = {
    start : function(time){
        animation.items[0].start(time);
    },
    update : function(ctx,time){
        var i;
        var len = this.items.length;
        // update animation details
        for(i = 0; i < len; i ++){
            this.items[i].setTime(time);
        }
        // draw animation
        for(i = 0; i < len; i ++){
            this.items[i].draw(ctx);
        }        
    },
    items : [
        {
            animate : boxAnimProps,     // what to animate
            draw : drawFunc,            // function to draw
            setTime : animateFunc,      // function to update state
            start : startFunc,          // function to start the animation
            startTime : null,           // this items start time
            length : timePerSide,       // how long in seconds this animation is
            events : [{                 // list of events
                    fired : false,      // true if fired ( to stop it from repeating)
                    callback : null,    // callback to call when event fires
                    // this function determines when to fire the event
                    check : function(owner,time){
                        if(owner.current.x >= canvas.width - owner.current.w){
                            this.fired = true;
                            this.callback(time);
                        }
                    },
                }
            ],
            current : {}, // defined when running holds the current state
            startKey : {  // the key frame defining the start position
                x : -boxLength,
                y : 0,
                w : boxLength,
                h : boxHeight,
            },
            endKey : {   // keyframe for end
                x : canvas.width,
                y : 0,
                w : boxLength,
                h : boxHeight,
            }
        },{
            animate : boxAnimProps,
            draw : drawFunc, // function to draw
            setTime : animateFunc, // function to set current anim state
            start : startFunc, // function to start the animation
            startTime : null,
            length : timePerSide,
            events : [{
                    fired : false,
                    callback : null,
                    check : function(owner,time){
                        if(owner.current.y >= canvas.height - owner.current.h){
                            this.fired = true;
                            this.callback(time);
                        }
                    },
                }
            ],
            current : {}, // defined when running
            startKey : {
                x : canvas.width - boxHeight,
                y : -boxLength,
                w : boxHeight,
                h : boxLength,
            },
            endKey : {
                x : canvas.width - boxHeight,
                y : canvas.height,
                w : boxHeight,
                h : boxLength,
            }
        },{
            animate : boxAnimProps,
            draw : drawFunc, // function to draw
            setTime : animateFunc, // function to set current anim state
            start : startFunc, // function to start the animation
            startTime : null,
            length : timePerSide,
            events : [{
                    fired : false,
                    callback : null,
                    check : function(owner,time){
                        if(owner.current.x <= 0){
                            this.fired = true;
                            this.callback(time);
                        }
                    },
                }
            ],
            current : {}, // defined when running
            startKey : {
                x : canvas.width,
                y : canvas.height - boxHeight,
                w : boxLength,
                h : boxHeight,
            },
            endKey : {
                x : - boxLength,
                y : canvas.height - boxHeight,
                w : boxLength,
                h : boxHeight,
            }
        },{
            animate : boxAnimProps,
            draw : drawFunc, // function to draw
            setTime : animateFunc, // function to set current anim state
            start : startFunc, // function to start the animation
            startTime : null,
            length : timePerSide,
            events : [{
                    fired : false,
                    callback : null,
                    check : function(owner,time){
                        if(owner.current.y <= 0){
                            this.fired = true;
                            this.callback(time);
                        }
                    },
                }
            ],
            current : {}, // defined when running
            startKey : {
                x : 0,
                y : canvas.height,
                w : boxHeight,
                h : boxLength,
            },
            endKey : {
                x : 0,
                y : - boxLength,
                w : boxHeight,
                h : boxLength,
            }
        }
    ]
};
// set events. Item one calls item two and so on
animation.items[0].events[0].callback = animation.items[1].start.bind(animation.items[1]);
animation.items[1].events[0].callback = animation.items[2].start.bind(animation.items[2]);
animation.items[2].events[0].callback = animation.items[3].start.bind(animation.items[3]);
animation.items[3].events[0].callback = animation.items[0].start.bind(animation.items[0]);



// update the canvas
var firstFrame = true;
function update(time){
    if(firstFrame){
        firstFrame = false;
        animation.start(time / 1000); // set start time in seconds.
    }
    ctx.fillStyle = "#AAA";
    ctx.fillRect(0,0,canvas.width,canvas.height);
    ctx.fillStyle = "#F00";
    animation.update(ctx,time / 1000); // animate and convert time from ms to seconds
    requestAnimationFrame(update);
}
requestAnimationFrame(update);
&#13;
&#13;
&#13;