首先我们改写一下昨天的格式,还记得昨天我们用到的是这样的写法:
cursorX+= distanceX / period;
cursorY+= distanceY / period;
当时的想法也很简单,因为总共有90侦,因此将座标加上distance / period共90次,就会是完整的位移,那麽,换句话说,其实就是,每1侦加上1/90的距离,可以写成这样:
let linear = 1 / period;
cursorX+= linear * distanceX;
cursorY+= linear * distanceY;
// 位移 = 线性常数 * 距离
其实,这个线性常数linear等同时间函数的微分,将它积分後会刚好等於1
阿 突然讲了很难懂的话
在上面的公式中,输入值为距离和总侦数(distance, period),输出值则是每一侦要进行的位移,在这个例子中,因为共有90侦,linear * 90就好刚好会等於1,也就是说,实际上我们想控制这个参数,让它经过90侦後刚好等於1,因而从原点转移到目的地,所以我们要做的是便是「操纵0到1的过程」。
昨天留的思考题,不知道有没有人解出来了呢?有的扣个1留言一下XD,现在就让我们解答吧,首先我们先从简单的开始,以前国中学到一元二次方程序,最先学的那个不外乎就是Y=X^2吧?也就是最简单的,这个方程序有一个特性,就是当X在0~1之间时,Y也是0~1之间,刚才说我们希望「输出值的总和」等於1,因此只要控制X在0~1之间就可以了!
开始困惑的朋友们莫慌!让我们直接代数字进去看看,在第一侦的时候timer为90,随着timer的减少
period | timer | X | Y | 总位移量 |
---|---|---|---|---|
90 | 90 | 0 | 0 | 0 |
90 | 45 | 0.5 | 0.25 | 总距离的1/4倍 |
90 | 30 | 0.666 | 0.444 | 总距离的4/9倍 |
90 | 0 | 1 | 1 | 总距离的1倍 |
这样是不是就很好懂了呢?从一开始几乎不动,到後面越来越快,最後到达目标位置。
如果没看过这两个名词的话,可以参考这个里面的文件附图说明
其实,我们刚刚做的就是ease-in函数,不过跟典型的不太一样,只是很相似的地步,但也是最好理解的,不过,现在的问题是,我们已经拿到这个方程序,也会算总位移了,那要怎麽取得「每一侦的位移」呢?答案很简单,就是「拿下一侦的位移减这一侦的位移」:
写成程序码就是:
let easein = Math.pow(1 - (timer-1) / period, 2) - Math.pow(1 - timer / period, 2);
let cursorX+= easein * distanceX;
let cursorY+= easein * distanceY;
如何?换上这行代码後,动画效果是不是多了几番风味呢?
那反过来说ease-out要怎麽做呢?其实有个偷吃步的做法,就是把ease-in颠倒过来,慢的变快的,快的变慢的,拿1去减掉这个范围0~1的参数,就会从「0到1」反过来「1到0」,公式:
也就是:
let easeout = Math.pow(timer / period, 2) - Math.pow((timer-1) / period, 2);
let cursorX+= easeout * distanceX;
let cursorY+= easeout * distanceY;
那麽,我们就完成很基本的ease-in和ease-out拉!洒花~
接着我们可以进一步混和不同方程序,写成像这样的格式:
cursorX+= (0.5 * linear + 0.5 * easein) * distanceX;
cursorY+= (0.5 * linear + 0.5 * easein) * distanceY;
这样可以使得easein的效果比较缓和,看起来不会那麽做作,不过要注意参数总和必须为1
function MouseAnime(){
if(!isPathing){
if(timer > 0){
let linear = 1/period;
let easeout = Math.pow(timer / period, 2)
- Math.pow((timer-1) / period, 2);
let easein = Math.pow(1 - (timer-1) / period, 2)
- Math.pow(1 - timer / period, 2);
let a = input.linear;
let b = input.easein;
let c = input.easeout;
cursorX+= (a * linear + b * easein + c * easeout) * distanceX;
cursorY+= (a * linear + b * easein + c * easeout) * distanceY;
timer--;
}
else{
cursorX+= (mouseX - cursorX) / 5;
cursorY+= (mouseY - cursorY) / 5;
}
}
let size = WIDTH * 0.1;
if(MouseImg.complete) context.drawImage(MouseImg,
cursorX-size/2, cursorY-size/2,
size, size);
}
透过abc参数,给予不同的权重,设计上希望a+b+c=1,不过为了方便直接设计权重比例,最後共同除以(a+b+c)就可以了
这样混和的方法,也可以创造出新的方程序,比方说回弹机制等等的,
甚至XY可以分别采用不同的动画模式,例如:X是纯Linear、Y是纯Ease-in,玩起来还是有Ease-in的味道在,只是相比之下没有那麽浮夸;混合的方法则可以设计出回旋镖等等的骚操作。
我就把这份快乐留给大家试试看吧!可以拿这份架构去修改参数,或者加入更多其他的方程序
今天花了四个小时坐客运,时间被压缩了不少,文章也都是亲笔撰写,也花了点时间设计架构,故内容写少一点请见谅拉,但还是推荐大家可以去玩一下demo,会越来越精彩~明天要开始引入物件的观念!
在金融产业的ML 在algorithmia的2021 年企业机器学习趋势调查显示,关於客户体验跟流程...
在上一篇文章中提到碰撞(collision),让我突然想到!还有这个主题可以拿来撰写,就是:当你在 ...
现在我们会使用具有互动性的简单渐变效果了,接着要来试着让网页能增添更多活力,不需要我们操作,就会自...
输入:pip list 发现少了tensorflow-gpu 输入: pip install ten...
首先要庆祝一下~ 终於撑到30天了 今天要来练习的是利用switch 来做一个选择的模式 模式有三种...