问题
I am working on a square graph animation. The squares should grow from zero on the x/y axis(top left corner) to their determined percent size with ease. Can anyone provide me any hints to accomplish this? This is what I have so far: http://jsfiddle.net/2n6kduL4/3/
The progress is happening from left to right. But it has to fill from the left top corner to the right bottom corner.
var canvas = document.getElementById('myProgress');
var myPerc = 500;
ctx = canvas.getContext('2d');
ctx.fillStyle = "rgb(255, 0, 0)"; //red
ctx.fillRect(0, 0, myPerc, 100);
ctx.save();
for (var i = 0; i < (myPerc * 0.5); i++) {
ctx.fillStyle = "rgb(0, 255, 0)"; //greeen
(function(i) {
setTimeout(function() {
ctx.fillRect(0, 0, +i, 100);
}, 1000 * i);
})(i);
}
回答1:
You can achieve your animated + eased barchart using Penner's Easing functions and the requestAnimationFrame timing loop
Here's how:
Define each of your barchart bars in javascript objects:
// create some bar objects and put them in a bars[] array
var bars=[];
var bar1={x:0,y:20,width:1,height:50,fill:'red'};
var bar2={x:0,y:100,width:1,height:50,fill:'green'};
var bar3={x:0,y:180,width:1,height:50,fill:'blue'};
bars.push(bar1,bar2,bar3);
Then you can animate each bar to its ending width using Penner's Easing equations. Here are a few of the many Penner easing algorithms expressed as javascript functions. What you do is feed in the current elapsed time, beginning value, total time duration and total value change desired during the easing. The Penner functions return to you the current (eased) value based on the current time.
// t: elapsed time inside duration,
// b: beginning value,
// d: total duration
// c: total change from beginning value,
var easings={
linear:function(t,b,c,d){return(c*t/d+b);},
easeInQuint: function(t,b,c,d){return(c*(t/=d)*t*t*t*t+b);},
easeOutQuint: function (t,b,c,d){return(c*((t=t/d-1)*t*t*t*t+1)+b);},
}
Here is example code and a Demo
The code creates a reusable "Animation Class" that can be used to ease the property values of the bar objects you created above over the animation duration:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var Animation=( function(){
// easings
// t: elapsed time through duration,
// b: beginning value,
// d: total duration
// c: total change from beginning value,
var easings={
linear:function(t,b,c,d){return(c*t/d+b);},
easeInQuint: function(t,b,c,d){return(c*(t/=d)*t*t*t*t+b);},
easeOutQuint: function (t,b,c,d){return(c*((t=t/d-1)*t*t*t*t+1)+b);},
}
//
function Animation(target,property,endingValue,duration,easing){
this.target=target;
this.property=property;
this.endingValue=endingValue;
this.duration=duration;
this.easing=easing;
this.beginningValue=target[property];
this.totalChange=endingValue-target[property];
this.startTime=null;
this.isAnimating=false;
if(easings[this.easing]==undefined){this.easing='linear';}
};
//
Animation.prototype.animate=function(time){
if(time>this.startTime+this.duration){
this.target[this.property]=this.endingValue;
this.isAnimating=false;
}else{
this.target[this.property]=easings[this.easing](
time-this.startTime,this.beginningValue,this.totalChange,this.duration
);
}
};
//
Animation.prototype.run=function(){
this.target[this.property]=this.beginningValue;
this.startTime=performance.now();
this.isAnimating=true;
};
//
return(Animation);
})();
// create some bar objects and put them in a bars[] array
var bars=[];
var bar1={x:0,y:20,width:1,height:50,fill:'red'};
var bar2={x:0,y:100,width:1,height:50,fill:'green'};
var bar3={x:0,y:180,width:1,height:50,fill:'blue'};
bars.push(bar1,bar2,bar3);
// create some animations that widen the each bar to the desired
// width over 3000ms
var animations=[];
var bar1AnimateWidth=new Animation(bar1,'width',150,3000,'easeOutQuint');
var bar2AnimateWidth=new Animation(bar2,'width',85,3000,'easeOutQuint');
var bar3AnimateWidth=new Animation(bar3,'width',250,3000,'easeOutQuint');
animations.push(bar1AnimateWidth,bar2AnimateWidth,bar3AnimateWidth);
// start the requestAnimationFrame loop
requestAnimationFrame(animate);
// initialize each animation object and start each eased animation running
doAllAnimations();
function doAllAnimations(){
for(var i=0;i<animations.length;i++){ animations[i].run(); }
}
function animate(time){
// animate property values
for(var i=0;i<animations.length;i++){
var animation=animations[i];
if(animation.isAnimating){animation.animate(time);}
}
// redraw all bars with their newly animated properties
ctx.clearRect(0,0,cw,ch);
for(var i=0;i<bars.length;i++){
var bar=bars[i];
ctx.fillStyle=bar.fill;
ctx.fillRect(bar.x,bar.y,bar.width,bar.height);
}
// request another animation loop
requestAnimationFrame(animate);
}
$('#rerun').click(function(){ doAllAnimations(); });
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Animate with easeOutQuint easing</h4>
<button id=rerun>Rerun</button>
<br>
<canvas id="canvas" width=300 height=300></canvas>
来源:https://stackoverflow.com/questions/29857717/grow-square-div-with-color-based-on-the-percentage-value-provided