缓动函数对象速度过快

3

我最近发现了一个包含一些缓动函数的网站:http://gizma.com/easing/

我尝试从这个网站上实现一个“二次缓动进出”的函数到我的脚本中,但是我的精灵似乎非常快地飞离了屏幕。我不确定我的逻辑错误在哪里,需要帮助理解我的错误。

我的缓动函数看起来像这样:

    //t = time, b = startvalue, c = change in value
     function ease(t, b, c, duration) {
         t /= duration/2; //duration is in milliseconds
         if (t < 1) return c/2*t*t + b;
         t--;
         return -c/2 * (t*(t-2) - 1) + b;
     };

我的代码用于动画运动是从一个 mousedown 监听器中触发的:

function animate(e){
    clearTimeout(timer);

    var duration  = 2000; //2 seconds

    var startX    = camera.x;
    var startY    = camera.y;

    var targetX   = e.offsetX - element.width/2  + camera.x; //world space
    var targetY   = e.offsetY - element.height/2 + camera.y; //world space

    var vectorX   = targetX - startX / duration;
    var vectorY   = targetY - startY / duration;

    var startTime = Date.now();

    function update(){
        var t   = Date.now() - startTime; //time elapsed so far
        var cX  = vectorX * t; //change in X
        var cY  = vectorY * t; //change in Y

        var amountX = ease(t,startX,cX,duration); // see function above
        var amountY = ease(t,startY,cY,duration);

        var difX    = startX - amountX; //get the difference
        var difY    = startY - amountY;

            camera.x += difX;
            camera.y += difY;

        if (t >= duration){
            clearTimeout(timer);
        } else {
            timer = setTimeout(update,0);               
        }
    }
    update();   
}

什么让动画运行如此之快并且移动距离那么远?
编辑:添加了jsfiddle链接以便参考:http://jsfiddle.net/a86m33nj/
2个回答

1

https://jsfiddle.net/pcconsolidated/xesnom2t/

你的问题其实很简单。二次渐变函数只是想知道起始坐标、移动距离、相对起始时间和总持续时间。此外,二次函数的输出是新的坐标,而不是物体移动的距离,所以只需用从函数得到的值替换坐标即可,四舍五入到最近的数字。

var element   = document.getElementById('background');
var output       = document.getElementById('output');
var camera=document.getElementById("camera");
var timer;
var targetX=0;
var targetY=0;
document.addEventListener('click', animate,true);
var duration  = 2000; //2 seconds
var startX    = 0;
var startY    = 0;
var startTime =0;


function animate(e){
 targetX   = e.clientX ;
    targetY   = e.clientY ;
 clearTimeout(timer);
     startX    = parseInt(camera.style.left.split("p")[0]);
  startY    = parseInt(camera.style.top.split("p")[0]);
  
 startTime = Date.now();
     
    
 
   
 
  updateLoc(); 
 }
 


 function updateLoc(){
   var t = (Date.now() - startTime);
   var cX  = targetX-startX; //change in X
   var cY  = targetY-startY; //change in Y
            
   var amountX = ease(t,startX,cX,duration);
   var amountY = ease(t,startY,cY,duration);
               
    newX=Math.floor(amountX);
    newY=Math.floor(amountY);
    camera.style.left = Math.floor(newX)+"px";
             camera.style.top = Math.floor(newY)+"px";
    output.innerHTML+=newX+","+newY+"___";
   if (Date.now() - startTime >= duration){
    clearTimeout(timer);
   } else {
    timer = setTimeout(updateLoc,0);    
   }
  }


 
 //t = time, b = startvalue, c = change in value
   function ease(t, b, c,duration) {
    t /= duration/2;
    if (t < 1) return c/2*t*t + b;
    t--;
    return -c/2 * (t*(t-2) - 1) + b;
   };


</script>
<canvas id="background" width="500" height="500">
    
    
    
</canvas><br/>
<div id="output"></div><div id="camera" style="background-color:green;top:250px;left:150px;position:absolute;height:30px;width:30px;"></div>

<script type="text/javascript">

这段代码有些粗糙,我的偏移量可能有问题,但我会在晚饭后继续调试,看看能否解决。这是我的代码,希望它对你有用。


为什么它没有工作?在我的屏幕上似乎是可以的。毕竟,如果有问题的话我会收到错误信息的。难道你没看JSFiddle吗? - Sir
等一下,我正在尝试使用你的版本编辑我的原始脚本,看看它是否有效。 - Sir
好的。我也已经修复了偏移问题。二次平滑处理的输出不应该被添加到现有位置,而是替换位置。我已经修改了代码并编辑了Fiddle。 - PC3TJ
有没有办法在我的主要代码每次更新相机时,从每个帧中获取差异,而不是将其设置为特定位置? - Sir
我的函数有效 :) 感谢您的帮助,也欢迎来到 SO! - Sir
显示剩余13条评论

0

好的,经过对您的代码的调试,我已经让它正常工作了。现在相机将跟随您单击的位置:

   function animate(e){
    clearTimeout(timer);

    var duration  = 2000; //2 seconds

    var startX    = camera.x;
    var startY    = camera.y;

    var targetX   = e.offsetX - element.width/2  + camera.x;
    var targetY   = e.offsetY - element.height/2 + camera.y;

    var startTime = Date.now();

    //t = time, b = startvalue, c = change in value
     function ease(t, b, c,duration) {
         t /= duration/2;
         if (t < 1) return c/2*t*t + b;
         t--;
         return -c/2 * (t*(t-2) - 1) + b;
     };

    function update(){
        var t   = (Date.now() - startTime);
        var cX  = -targetX; //change in X
        var cY  = -targetY; //change in Y

        camera.x = ease(t,startX,cX,duration);
        camera.y = ease(t,startY,cY,duration);

        if (Date.now() - startTime > duration){
            clearTimeout(timer);
        } else {
            timer = setTimeout(update,10);              
        }
    }    
    update();   
}

希望对你有所帮助。干杯!


我正在使用deltaTime,迭代速度应该是无关紧要的。 - Sir
@OddOrbStudio 这是问题的一部分,除此之外,需要将输出视为绝对而非相对,并且起始和目标的声明已更改。 - PC3TJ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接