代码调用cc.easeBezierAction 会直接对4个点进行计算;
动画编辑器时间曲线调用的贝塞尔方法为 bezier.js 中的
bezierByTime方法,该方法套用贝塞尔公式前对时间t进行了一系列的计算,代码调用和动画编辑器的曲线表现无法一致。参数按照动画编辑器对应曲线函数传的,[0,y1,y2,1],详细代码如下:
//代码调用方法
cc.easeBezierAction = function(a, b, c, d){
return {
easing: function(t){
return (Math.pow(1-t,3) * a + 3t(Math.pow(1-t,2))b + 3Math.pow(t,2)*(1-t)*c + Math.pow(t,3)*d);
},
reverse: function(){
return cc.easeBezierAction(d, c, b, a);
}
};
};
//动画编辑器调用方法
function bezierByTime (controlPoints, x) {
//这一步处理了时间x,用了controlPoints[0]、controlPoints[2]参数,无论这两个参数传多少都会改变t
var percent = cardano(controlPoints, x); // t
var p0y = 0; // a
var p1y = controlPoints[1]; // b
var p2y = controlPoints[3]; // c
var p3y = 1; // d
var t1 = 1 - percent;
return p0y * t1 * t1 * t1 +
p1y * 3 * percent * t1 * t1 +
p2y * 3 * percent * percent * t1 +
p3y * percent * percent * percent;
}
function cardano (curve, x) {
// align curve with the intersecting line:
//var line = {p1: {x: x, y: 0}, p2: {x: x, y: 1}};
//var aligned = align(curve, line);
//// and rewrite from [a(1-t)^3 + 3bt(1-t)^2 + 3c(1-t)t^2 + dt^3] form
// pa = aligned[0].y,
// pb = aligned[1].y,
// pc = aligned[2].y,
// pd = aligned[3].y;
////// curve = [{x:0, y:1}, {x: curve[0], y: 1-curve[1]}, {x: curve[2], y: 1-curve[3]}, {x:1, y:0}];
var pa = x - 0;
var pb = x - curve[0];
var pc = x - curve[2];
var pd = x - 1;
// to [t^3 + at^2 + bt + c] form:
var pa3 = pa * 3;
var pb3 = pb * 3;
var pc3 = pc * 3;
var d = (-pa + pb3 - pc3 + pd),
rd = 1 / d,
r3 = 1 / 3,
a = (pa3 - 6 * pb + pc3) * rd,
a3 = a * r3,
b = (-pa3 + pb3) * rd,
c = pa * rd,
// then, determine p and q:
p = (3 * b - a * a) * r3,
p3 = p * r3,
q = (2 * a * a * a - 9 * a * b + 27 * c) / 27,
q2 = q / 2,
// and determine the discriminant:
discriminant = q2 * q2 + p3 * p3 * p3,
// and some reserved variables
u1, v1, x1, x2, x3;
// If the discriminant is negative, use polar coordinates
// to get around square roots of negative numbers
if (discriminant < 0) {
var mp3 = -p * r3,
mp33 = mp3 * mp3 * mp3,
r = sqrt(mp33),
// compute cosphi corrected for IEEE float rounding:
t = -q / (2 * r),
cosphi = t < -1 ? -1 : t > 1 ? 1 : t,
phi = acos(cosphi),
crtr = crt(r),
t1 = 2 * crtr;
x1 = t1 * cos(phi * r3) - a3;
x2 = t1 * cos((phi + tau) * r3) - a3;
x3 = t1 * cos((phi + 2 * tau) * r3) - a3;
// choose best percentage
if (0 <= x1 && x1 <= 1) {
if (0 <= x2 && x2 <= 1) {
if (0 <= x3 && x3 <= 1) {
return max(x1, x2, x3);
}
else {
return max(x1, x2);
}
}
else if (0 <= x3 && x3 <= 1) {
return max(x1, x3);
}
else {
return x1;
}
}
else {
if (0 <= x2 && x2 <= 1) {
if (0 <= x3 && x3 <= 1) {
return max(x2, x3);
}
else {
return x2;
}
}
else {
return x3;
}
}
}
else if (discriminant === 0) {
u1 = q2 < 0 ? crt(-q2) : -crt(q2);
x1 = 2 * u1 - a3;
x2 = -u1 - a3;
// choose best percentage
if (0 <= x1 && x1 <= 1) {
if (0 <= x2 && x2 <= 1) {
return max(x1, x2);
}
else {
return x1;
}
}
else {
return x2;
}
}
// one real root, and two imaginary roots
else {
var sd = sqrt(discriminant);
u1 = crt(-q2 + sd);
v1 = crt(q2 + sd);
x1 = u1 - v1 - a3;
return x1;
}
}