什麽是贝兹曲线?它能创造一连串平滑的曲线,被应用在PS和AI中的钢笔、以及常见的CSS Animation,换句话说,你学会了贝兹曲线,就大概懂一半网页动画了,它厉害的地方在於,用一个很简单并直觉的方式来设定动画,加上其可视化的特性,在上述例子中都能很轻松的运用。
像是在这个网站用滑鼠拉动控制杆後,就可以轻易地拿到参数,把它复制到CSS Animation的设定中,就能轻松产生动画。
起初是没打算拿贝兹曲线来作文章的,CSS已经有框架可以用了,为什麽我们还要用JS从底层实作一遍呢?这个论点大致上没错,不过,昨晚睡前我不经意看到了这部影片:The Beauty of Bézier Curves
这部影片,是我目前为止看过讲的最简单易懂的贝兹曲线,包含很完整的纲要和学习步骤,当然,里面还是包含了一些数学,但重要的是,它有谈到如何透过简化的公式实现美丽的贝兹曲线,并且,我们的眼光可以不局限於CSS的框架,透过多条贝兹曲线的连接,可以轻松实现昨天所说的「寻路问题」,并打破原先的随机性和不可预测性。
虽然是推荐大家看原版英文的影片(有CC字幕),享受质感,不过还是提供大家英文苦手的选择:bilibibli的翻译版本
这边我们设计一个向量物件,来描述贝兹曲线的四个基本点,名称和教学中采用一致的(p0, p1, p2 ,p3)
function vector(x, y){
this.x = x;
this.y = y;
}
function bezierCurves(x0, y0, x1, y1, x2, y2, x3, y3){
this.p0 = new vector(x0, y0);
this.p1 = new vector(x1, y1);
this.p2 = new vector(x2, y2);
this.p3 = new vector(x3, y3);
this.timestamp = Date.now();
this.lifeTime = 2;
}
然後把路径的公式描绘出来,为了能清楚呈现多项式中的次方项,采用Math.pow的写法,而不是t x t x t,一样是在原型上添加方法
bezierCurves.prototype.Path = function(){
let P = function(a, b){
return Math.pow(a, b);
}
return {'x': x0 * (-1 * P(t ,3) + 3 * P(t ,2) - 3 * P(t ,1) + 1 )
+x1 * ( 3 * P(t ,3) - 6 * P(t ,2) + 3 * P(t ,1))
+x2 * (-3 * P(t ,3) + 3 * P(t ,2))
+x3 * ( 1 * P(t ,3)),
'y': y0 * (-1 * P(t ,3) + 3 * P(t ,2) - 3 * P(t ,1) + 1 )
+y1 * ( 3 * P(t ,3) - 6 * P(t ,2) + 3 * P(t ,1))
+y2 * (-3 * P(t ,3) + 3 * P(t ,2))
+y3 * ( 1 * P(t ,3))}
}
然後我们试着让一条新的贝兹曲线接上旧的,一样是设计animeList跑回圈时所呼叫的NextFrame方法:
bezierCurves.prototype.NextFrame = function(){
// 计算下一侦的位置(0~1)
let dT = (Date.now() - this.timestamp) / 1000 / this.lifeTime;
if(dT <= 1){
let point = bezierCurves.prototype.Path(dT);
context.save();
context.translate(pointX, pointY);
context.drawImage(mouseImg, -mouseImg.width/2, -mouseImg.height/2);
context.restore();
}
else{
// 制作一个闭环
let newObject = new bezierCurves(this.p3.x, this.p3.y,
this.p3.x * 2 - this.p2.x,
this.p3.y * 2 - this.p2.y,
this.p0.x * 2 - this.p1.x,
this.p0.y * 2 - this.p1.y,
this.p0.x, this.p0.y);
let index = animeList.indexOf(this);
delete animeList[index];
animeList[index] = newObject;
}
}
有点快睡着了,打code打到度估,今天就先这样了不好意思><,这几天有空再回来补demo吧!
其他:
bezierCurves.prototype.Velocity = function(){
let P = function(a, b){
return Math.pow(a, b);
}
return {'x': x0 * (-3 * P(t ,2) + 6 * P(t ,1) - 3 )
+x1 * ( 9 * P(t ,2) - 12 * P(t ,1) + 3 )
+x2 * (-9 * P(t ,2) + 6 * P(t ,1))
+x3 * ( 3 * P(t ,2)),
'y': y0 * (-3 * P(t ,2) + 6 * P(t ,1) - 3 )
+y1 * ( 9 * P(t ,2) - 12 * P(t ,1) + 3 )
+y2 * (-9 * P(t ,2) + 6 * P(t ,1))
+y3 * ( 3 * P(t ,2))}
}
bezierCurves.prototype.Acceleration = function(){
let P = function(a, b){
return Math.pow(a, b);
}
return {'x': x0 * ( -6 * P(t ,1) + 6 )
+x1 * ( 18 * P(t ,1) - 12 )
+x2 * (-18 * P(t ,1) + 6 )
+x3 * ( 6 * P(t ,1)),
'y': y0 * ( -6 * P(t ,1) + 6 )
+y1 * ( 18 * P(t ,1) - 12 )
+y2 * (-18 * P(t ,1) + 6 )
+y3 * ( 6 * P(t ,1))}
}
bezierCurves.prototype.Jerk = function(){
let P = function(a, b){
return Math.pow(a, b);
}
return {'x': x0 * ( -6 )
+x1 * ( 18 )
+x2 * (-18 )
+x3 * ( 6 ),
'y': y0 * ( -6 )
+y1 * ( 18 )
+y2 * (-18 )
+y3 * ( 6 )}
}
>>: 16 - Logs - 挖掘系统内部发生的状况 (4/4) - 透过 Filebeat 收集 Infrastructure 中各种服务的细节资讯
今天再举一个for回圈的例子,找出1~100的偶数。 Ans:从一开始所以一开始int i=1,然後...
700. Search in a Binary Search Tree 昨天提到链结串列(Link...
我的文章系列快要变成每天30分钟,学一点新的东西了。 一样是继续跟着教程走,Implement da...
RxJava2是一套处理非同步(asynchronous)事件的library,这个library是...
本篇的主角是Toast, 但这边的Toast并非吐司的意思, 而是显示讯息, 常用於提示或警示使用者...