[Отредактировано, чтобы обеспечить основу анимации]
Вот основа стартер я создал, чтобы сделать вашу Keyframe анимацию
Я сохранил это просто, но вы, безусловно, можете построить на этой основе.
Вы можете определить 1 или более холст объектов для использования в ключевых кадров, как это:
// define a drawing function that will draw your object on the canvas
var drawFn1=function(context,x,y){
var radius=30;
context.strokeStyle="blue";
context.lineWidth=5;
context.fillStyle="green";
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.stroke();
context.fill();
}
// create a new displayobject
var displayObject1=new DisplayObject(200,100,drawFn1);
Затем добавить 1 или более объектов отображения на массив объектов. Вы можете разбить все эти объекты индивидуально - все объекты могут иметь отдельные анимации.
// create an array of DisplayObjects
var displayObjects=[];
// push our displayObject1 into displayObjects
displayObjects.push(displayObject1);
Затем вы добавляете действия, которые вы хотите, чтобы ваш объект выполнял (и длительность выполнения этих действий). Вы можете добавить столько действий в любую комбинацию, сколько вам нужно. Прямо сейчас, я закодировал всего 2 действия: «переместить» и «приостановить». Вы, безусловно, можете добавить дополнительные действия в структуру.
При необходимости вы можете добавлять действия, даже если текущие ключевые кадры воспроизводятся. Любые добавленные действия ставятся в очередь для выполнения после завершения текущих действий.
Код ниже будет вызывать объект:
- двигаться влево в течение 20 кадров,
- Пауза в течение 30 кадров,
- Перемещение вниз более 20 кадров.
Обратите внимание, что действия могут быть добавлены с помощью цепочки.
// add actions for the displayobject
displayObject1.moveBy(-75,0,20).pause(30).moveBy(0,75,20);
Вот код и Fiddle: http://jsfiddle.net/m1erickson/RjR9C/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:15px; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// defines an action to accomplish
function Action(type,msDuration){
var type=type;
var duration=msDuration;
var incrementalX;
var incrementalY;
}
function DisplayObject(X,Y,Drawfunction){
this.drawFunction=Drawfunction;
this.x=X;
this.y=Y;
this.actionStack=[];
this.currentAction=null;
this.IsActive=false;
}
DisplayObject.prototype.pause=function(duration){
var action=new Action();
action.type="pause";
action.duration=duration;
this.actionStack.push(action)
this.IsActive=true;
return(this);
}
DisplayObject.prototype.test=function(){
alert("test");
}
DisplayObject.prototype.moveBy=function(offsetX,offsetY,duration){
var action=new Action();
action.type="moveBy";
action.duration=duration;
action.incrementalX=offsetX/duration;
action.incrementalY=offsetY/duration;
this.actionStack.push(action)
this.IsActive=true;
return(this);
}
DisplayObject.prototype.tick=function(context){
// If we have nothing to do...outta here!
if(!this.IsActive){return;};
//
if(!this.currentAction){
this.currentAction=this.actionStack.shift();
}
// animate the current frame
this.doNextFrame(context);
// decrement the tick countdown on our current action
this.currentAction.duration--;
// if this action is done then load the next action
if(this.currentAction.duration<=0){
if(this.actionStack.length>0){
this.currentAction=this.actionStack.shift();
}else{
this.currentAction=null;
this.IsActive=false;
}
}
}
DisplayObject.prototype.doNextFrame=function(context){
// update based on currentAction
switch(this.currentAction.type){
case "pause":
break;
case "moveBy":
this.x+=this.currentAction.incrementalX;
this.y+=this.currentAction.incrementalY;
break;
default:
break;
}
// draw ourself
this.drawFunction(context,this.x,this.y);
}
// Here’s how you make use of this AnimationFrame framework
var drawFn1=function(context,x,y){
var radius=30;
context.strokeStyle="blue";
context.lineWidth=5;
context.fillStyle="green";
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.stroke();
context.fill();
}
// create a new displayobject
var displayObject1=new DisplayObject(200,100,drawFn1);
// add actions for the displayobject
displayObject1.moveBy(-75,0,20).pause(30).moveBy(0,75,20);
// create an array of DisplayObjects
var displayObjects=[];
// push our displayObject1 into displayObjects
displayObjects.push(displayObject1);
function runOneFrame(){
ctx.clearRect(0,0,canvas.width,canvas.height);
for(var i=0;i<displayObjects.length;i++){
displayObjects[i].tick(ctx);
}
}
var fps = 20;
function Ticker() {
setTimeout(function() {
requestAnimationFrame(Ticker);
runOneFrame();
}, 1000/fps);
}
$("#go").click(function() { Ticker(); $("#go").hide(); });
}); // end $(function(){});
</script>
</head>
<body>
<button id="go">Begin animation frames</button><br/>
<p>The display will go left, pause and go down.</p>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
Спасибо! Хотя я смущен тем, что wrapTimeout wrapping requestAnimationFrame будет поддерживать надлежащее время. Я думал, что это был весь смысл requestAnimationFrame для замены setTimeout, поскольку он не основан на близком приближении времени только на пузырьках событий в браузере. – tripdragon
Хорошее спасибо, спасибо, но на самом деле он не решает загадки. Я добавил некоторый вложенный код условных выражений выше, это единственное, что я могу понять, объединив файлы главы из анимации html5 в книге. Это действительно единственное решение без javascript? – tripdragon
ОК, см. Мой отредактированный ответ. Я закодировал фреймворк javascript, который будет делать ваши анимации в ключевом кадре. Не стесняйтесь использовать/добавлять к нему в соответствии с вашими потребностями. – markE