使用画布使对象的尺寸在大小上振荡

时间:2014-03-10 14:39:03

标签: javascript math canvas html5-canvas

我正在玩帆布,我想制作一个正方形,当点击时获得最初的能量爆发(缺少一个更好的单词),这会导致它在X轴和Y轴上生长和收缩,这个在动画停止之前,能量会随着时间的推移而降低。

我可以使用Javascript位,但我需要的是一个可以计算我用来缩放对象尺寸的乘数的函数。

理想情况下,这里是我将使用的伪代码:

var scale = 1, previousScale = 1;

function draw() {
    previousScale = scale;
    scale = recalculateScale(); // I can't write this magic function

    var x = x * scale
      , y = y * scale;

    // draw code here

    // if the scale hasn't changed since last redraw then we're done
    if (scale === previousScale) {
        window.requestAnimationFrame(draw());
    }
}

draw();

如果您还可以告诉我您用来计算此值的方法的名称,我将非常感谢。

2 个答案:

答案 0 :(得分:2)

var now_value = new Number(); //this is a global var. 


function recalculateScale(indice) {

if (!indice) var index = 0;
else {var index = indice;}

var limit = (3/2)*(3.14); //this is when sin function is starting growing again (more or less when index is 3.14+1.57, so after it has been decreasing for some time, and i think this is where you should stop. But you are free to choose according to easing you 

scale = Math.sin(index);

now_value = scale;
console.log(now_value)

if (index < limit) {
setTimeout(function() {
recalculateScale(index+0.1) //you can change 0.1 to any value you want, according to how much linear you want your animation to be
}, 20) //you can change 20 to any values, these are milliseconds
}
else {console.log('animation finished'); now_value = 0;}

}

当您希望动画启动时,只需调用函数recalculateScale(),然后每次需要scale的值时,只需获取var now_value,这是全局的,并且在转换期间正在修改。当转换完成时,它将达到其原始值0。

请注意,在此示例中,now_value的值将在1/3的时间内从0到1,然后在2/3的时间内从1到-1。

无法测试,我希望它可以工作或帮助。

-edit-- 是的它有效,这些是解释输出:

0.09983341664682802 VM571:15
0.19866933079506113 VM571:15
0.29552020666133944 VM571:15
0.38941834230864997 VM571:15
0.47942553860420295 VM571:15
0.5646424733950346 VM571:15
0.6442176872376908 VM571:15
0.7173560908995221 VM571:15
0.7833269096274824 VM571:15
0.8414709848078963 VM571:15
0.8912073600614339 VM571:15
0.9320390859672261 VM571:15
0.9635581854171918 VM571:15
0.9854497299884593 VM571:15
0.9974949866040542 VM571:15
0.9995736030415037 VM571:15
0.9916648104524685 VM571:15
0.9738476308781938 VM571:15
0.9463000876874136 VM571:15
0.909297426825681 VM571:15
0.8632093666488722 VM571:15
0.8084964038195898 VM571:15
0.7457052121767187 VM571:15
0.67546318055115 VM571:15
0.5984721441039556 VM571:15
0.5155013718214626 VM571:15
0.4273798802338289 VM571:15
0.3349881501559032 VM571:15
0.23924932921398087 VM571:15
0.14112000805986563 VM571:15
0.04158066243328894 VM571:15
-0.05837414342758142 VM571:15
-0.15774569414324974 VM571:15
-0.2555411020268329 VM571:15
-0.35078322768962117 VM571:15
-0.4425204432948536 VM571:15
-0.5298361409084947 VM571:15
-0.6118578909427198 VM571:15
-0.6877661591839753 VM571:15
-0.7568024953079285 VM571:15
-0.8182771110644106 VM571:15
-0.8715757724135881 VM571:15
-0.916165936749454 VM571:15
-0.9516020738895161 VM571:15
-0.9775301176650958 VM571:15
-0.9936910036334636 VM571:15
-0.9999232575641003 VM571:15
-0.9961646088358395

第一个调用是index = 0.1,因此输出值为0.09983341664682802(sin(0)= 0)。当索引在pi / 2(1.57或更多)附近时,sin函数值为1,然后当索引值为3/2 * pi时开始减小到-1。总时间是:(限制你/你选择的间隔)*毫秒,在我们的情况下(((3/2)* pi)/(0.1))* 20。

你可以查看sin函数的图表来理解index和now_value是如何相关的。

pi是3.14。

答案 1 :(得分:1)

您可以结合使用requestAnimationFrame和easing来完成尺寸调整。

演示:http://jsfiddle.net/m1erickson/g48LR/

easing会在一段时间内改变一个值(比如你的比例因子)。

这是一个缓动函数的例子,它将在缓和周期中振荡该值:

发送到宽松的值是:

  • t ==自缓和开始以来经过的时间,
  • b ==开始值(例如,缩放将从1.00开始)
  • c ==在缓和过程中起始值将发生变化的量(例如,缩放将增加.25)
  • d ==宽松的持续时间

缓解振荡的功能:

function easeOutBounce(t, b, c, d){
    if ((t/=d) < (1/2.75)) {
      return c*(7.5625*t*t) + b;
    } else if (t < (2/2.75)) {
      return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
    } else if (t < (2.5/2.75)) {
      return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
    } else {
      return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
    }
}

以下是requestAnimationFrame + easing如何协同工作的一个很好的解释:

http://www.kirupa.com/html5/animating_with_easing_functions_in_javascript.htm

以下是Demo的代码:

<!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; }
    canvas{border:1px solid red;}
</style>
<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;

    var startTime
    var duration=1000;  // animate over 1000ms
    var totChange=.25;  // change the size by 25%

    var cx=150;
    var cy=150;
    var iw,ih;
    var img=new Image();
    img.isLoaded=false;
    img.onload=start;
    img.src="house100x100.png";
    function start(){
        iw=img.width;
        ih=img.height;
        this.isLoaded=true;
    }

    function animate(time){

        if(time<=endTime){ requestAnimationFrame(animate); }

        var elapsed=time-startTime;

        var value=easeOutBounce(elapsed,1.00,totChange,duration);

        var w=iw*value;
        var h=ih*value;
        var x=cx-w/2;
        var y=cy-h/2;

        ctx.clearRect(0,0,cw,ch);
        ctx.drawImage(img,0,0,iw,ih,x,y,w,h);

    }

    function easeOutBounce(t, b, c, d){
        if ((t/=d) < (1/2.75)) {
          return c*(7.5625*t*t) + b;
        } else if (t < (2/2.75)) {
          return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
        } else if (t < (2.5/2.75)) {
          return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
        } else {
          return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
        }
    }

    $("#test").click(function(){
        if(img.isLoaded){
            startTime=lastTime=performance.now();
            endTime=startTime+duration;
            animate(startTime);
        }
    });

}); // end $(function(){});
</script>
</head>
<body>
    <button id="test">Test</button><br>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>