rc-tween-one
Version:
tween-one anim component for react
517 lines (503 loc) • 15.3 kB
JavaScript
/* eslint-disable */
/**
* Created by jljsj on 15/12/22.
* The algorithm is GSAP BezierPlugin VERSION: beta 1.3.4
*/
import { checkStyleName, createMatrix } from 'style-utils';
var _RAD2DEG = 180 / Math.PI;
var _r1 = [];
var _r2 = [];
var _r3 = [];
var _corProps = {};
var _correlate = ',x,y,z,left,top,right,bottom,marginTop,marginLeft,marginRight,marginBottom,paddingLeft,paddingTop,paddingRight,paddingBottom,backgroundPosition,backgroundPosition_y,';
var GsapBezier = {
Segment: function Segment(a, b, c, d) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.da = d - a;
this.ca = c - a;
this.ba = b - a;
},
cubicToQuadratic: function cubicToQuadratic(a, b, c, d) {
var q1 = { a: a };
var q2 = {};
var q3 = {};
var q4 = { c: d };
var mab = (a + b) / 2;
var mbc = (b + c) / 2;
var mcd = (c + d) / 2;
var mabc = (mab + mbc) / 2;
var mbcd = (mbc + mcd) / 2;
var m8 = (mbcd - mabc) / 8;
q1.b = mab + (a - mab) / 4;
q2.b = mabc + m8;
q1.c = q2.a = (q1.b + q2.b) / 2;
q2.c = q3.a = (mabc + mbcd) / 2;
q3.b = mbcd - m8;
q4.b = mcd + (d - mcd) / 4;
q3.c = q4.a = (q3.b + q4.b) / 2;
return [q1, q2, q3, q4];
},
calculateControlPoints: function calculateControlPoints(a, curviness, quad, basic, correlate) {
var l = a.length - 1;
var i = void 0;
var ii = 0;
var p1 = void 0;
var p2 = void 0;
var p3 = void 0;
var seg = void 0;
var m1 = void 0;
var m2 = void 0;
var mm = void 0;
var cp2 = void 0;
var qb = void 0;
var r1 = void 0;
var r2 = void 0;
var tl = void 0;
var cp1 = a[0].a;
for (i = 0; i < l; i++) {
seg = a[ii];
p1 = seg.a;
p2 = seg.d;
p3 = a[ii + 1].d;
if (correlate) {
r1 = _r1[i];
r2 = _r2[i];
tl = (r2 + r1) * curviness * 0.25 / (basic ? 0.5 : _r3[i] || 0.5);
var _aa = r1 !== 0 ? tl / r1 : 0;
var _a = basic ? curviness * 0.5 : _aa;
m1 = p2 - (p2 - p1) * _a;
var bb = r2 !== 0 ? tl / r2 : 0;
var b = basic ? curviness * 0.5 : bb;
m2 = p2 + (p3 - p2) * b;
mm = p2 - (m1 + ((m2 - m1) * (r1 * 3 / (r1 + r2) + 0.5) / 4 || 0));
} else {
m1 = p2 - (p2 - p1) * curviness * 0.5;
m2 = p2 + (p3 - p2) * curviness * 0.5;
mm = p2 - (m1 + m2) / 2;
}
m1 += mm;
m2 += mm;
seg.c = cp2 = m1;
if (i !== 0) {
seg.b = cp1;
} else {
seg.b = cp1 = seg.a + (seg.c - seg.a) * 0.6;
}
seg.da = p2 - p1;
seg.ca = cp2 - p1;
seg.ba = cp1 - p1;
if (quad) {
qb = this.cubicToQuadratic(p1, cp1, cp2, p2);
a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]);
ii += 4;
} else {
ii++;
}
cp1 = m2;
}
seg = a[ii];
seg.b = cp1;
seg.c = cp1 + (seg.d - cp1) * 0.4;
seg.da = seg.d - seg.a;
seg.ca = seg.c - seg.a;
seg.ba = cp1 - seg.a;
if (quad) {
qb = this.cubicToQuadratic(seg.a, cp1, seg.c, seg.d);
a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]);
}
},
parseAnchors: function parseAnchors(_values, p, correlate, prepend) {
var a = [];
var l = void 0;
var i = void 0;
var p1 = void 0;
var p2 = void 0;
var p3 = void 0;
var tmp = void 0;
var values = _values;
if (prepend) {
values = [prepend].concat(values);
i = values.length;
while (--i > -1) {
tmp = values[i][p];
if (typeof tmp === 'string' && tmp.charAt(1) === '=') {
values[i][p] = prepend[p] + Number(tmp.charAt(0) + tmp.substr(2));
}
}
}
l = values.length - 2;
if (l < 0) {
a[0] = new this.Segment(values[0][p], 0, 0, values[l < -1 ? 0 : 1][p]);
return a;
}
for (i = 0; i < l; i++) {
p1 = values[i][p];
p2 = values[i + 1][p];
a[i] = new this.Segment(p1, 0, 0, p2);
if (correlate) {
p3 = values[i + 2][p];
_r1[i] = (_r1[i] || 0) + (p2 - p1) * (p2 - p1);
_r2[i] = (_r2[i] || 0) + (p3 - p2) * (p3 - p2);
}
}
a[i] = new this.Segment(values[i][p], 0, 0, values[i + 1][p]);
return a;
},
bezierThrough: function bezierThrough(_values, _curviness, quadratic, basic, __correlate, _prepend) {
var values = _values;
var curviness = _curviness;
var correlate = __correlate;
var prepend = _prepend;
var obj = {};
var props = [];
var first = prepend || values[0];
var i = void 0;
var p = void 0;
var a = void 0;
var j = void 0;
var r = void 0;
var l = void 0;
var seamless = void 0;
var last = void 0;
correlate = typeof correlate === 'string' ? ',' + correlate + ',' : _correlate;
if (curviness === null) {
curviness = 1;
}
Object.keys(values[0]).forEach(function (key) {
props.push(key);
});
if (values.length > 1) {
last = values[values.length - 1];
seamless = true;
i = props.length;
while (--i > -1) {
p = props[i];
if (Math.abs(first[p] - last[p]) > 0.05) {
seamless = false;
break;
}
}
if (seamless) {
values = values.concat();
if (prepend) {
values.unshift(prepend);
}
values.push(values[1]);
prepend = values[values.length - 3];
}
}
_r1.length = _r2.length = _r3.length = 0;
i = props.length;
while (--i > -1) {
p = props[i];
_corProps[p] = correlate.indexOf(',' + p + ',') !== -1;
obj[p] = this.parseAnchors(values, p, _corProps[p], prepend);
}
i = _r1.length;
while (--i > -1) {
_r1[i] = Math.sqrt(_r1[i]);
_r2[i] = Math.sqrt(_r2[i]);
}
if (!basic) {
i = props.length;
while (--i > -1) {
if (_corProps[p]) {
a = obj[props[i]];
l = a.length - 1;
for (j = 0; j < l; j++) {
r = a[j + 1].da / _r2[j] + a[j].da / _r1[j];
_r3[j] = (_r3[j] || 0) + r * r;
}
}
}
i = _r3.length;
while (--i > -1) {
_r3[i] = Math.sqrt(_r3[i]);
}
}
i = props.length;
j = quadratic ? 4 : 1;
while (--i > -1) {
p = props[i];
a = obj[p];
this.calculateControlPoints(a, curviness, quadratic, basic, _corProps[p]);
if (seamless) {
a.splice(0, j);
a.splice(a.length - j, j);
}
}
return obj;
},
parseBezierData: function parseBezierData(data) {
var values = data.vars.concat();
var type = data.type;
var prepend = data.startPoint;
var obj = {};
var inc = type === 'cubic' ? 3 : 2;
var soft = type === 'soft';
var a = void 0;
var b = void 0;
var c = void 0;
var d = void 0;
var cur = void 0;
var l = void 0;
var p = void 0;
var cnt = void 0;
var tmp = void 0;
if (soft) {
values.splice(0, 0, prepend);
}
if (values === null || values.length < inc + 1) {
return console.error('invalid Bezier data'); // eslint-disable-line
}
for (var i = 1; i >= 0; i--) {
p = i ? 'x' : 'y';
obj[p] = cur = [];
cnt = 0;
for (var j = 0; j < values.length; j++) {
tmp = values[j][p];
var _a = typeof tmp === 'string' && tmp.charAt(1) === '=' ? prepend[p] + Number(tmp.charAt(0) + tmp.substr(2)) : Number(tmp);
a = prepend === null ? values[j][p] : _a;
if (soft && j > 1 && j < values.length - 1) {
cur[cnt++] = (a + cur[cnt - 2]) / 2;
}
cur[cnt++] = a;
}
l = cnt - inc + 1;
cnt = 0;
for (var jj = 0; jj < l; jj += inc) {
a = cur[jj];
b = cur[jj + 1];
c = cur[jj + 2];
d = inc === 2 ? 0 : cur[jj + 3];
cur[cnt++] = tmp = inc === 3 ? new this.Segment(a, b, c, d) : new this.Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c);
}
cur.length = cnt;
}
return obj;
},
addCubicLengths: function addCubicLengths(a, steps, resolution) {
var inc = 1 / resolution;
var j = a.length;
var d = void 0;
var d1 = void 0;
var s = void 0;
var da = void 0;
var ca = void 0;
var ba = void 0;
var p = void 0;
var i = void 0;
var inv = void 0;
var bez = void 0;
var index = void 0;
while (--j > -1) {
bez = a[j];
s = bez.a;
da = bez.d - s;
ca = bez.c - s;
ba = bez.b - s;
d = d1 = 0;
for (i = 1; i <= resolution; i++) {
p = inc * i;
inv = 1 - p;
d = d1 - (d1 = (p * p * da + 3 * inv * (p * ca + inv * ba)) * p);
index = j * resolution + i - 1;
steps[index] = (steps[index] || 0) + d * d;
}
}
},
parseLengthData: function parseLengthData(obj, _resolution) {
var _this = this;
var resolution = _resolution || 6;
var a = [];
var lengths = [];
var threshold = resolution - 1;
var segments = [];
var d = 0;
var total = 0;
var curLS = [];
Object.keys(obj).forEach(function (key) {
_this.addCubicLengths(obj[key], a, resolution);
});
a.forEach(function (c, i) {
d += Math.sqrt(c);
var index = i % resolution;
curLS[index] = d;
if (index === threshold) {
total += d;
index = i / resolution >> 0;
segments[index] = curLS;
lengths[index] = total;
d = 0;
curLS = [];
}
});
return { length: total, lengths: lengths, segments: segments };
}
};
var Bezier = function Bezier(target, vars) {
this.vars = this.getDefaultData(vars);
this.target = target;
this.transform = checkStyleName('transform');
};
Bezier.prototype = {
name: 'bezier',
useStyle: 'transform',
getDefaultData: function getDefaultData(obj) {
return {
type: obj.type || 'soft',
autoRotate: obj.autoRotate || false,
vars: obj.vars || {},
startPoint: null
};
},
init: function init() {
var vars = this.vars;
var autoRotate = vars.autoRotate;
this._timeRes = !vars.timeResolution ? 6 : parseInt(vars.timeResolution, 10);
var a = autoRotate === true ? 0 : Number(autoRotate);
var b = autoRotate instanceof Array ? autoRotate : [['x', 'y', 'rotation', a || 0]];
this._autoRotate = autoRotate ? b : null;
this._beziers = vars.type !== 'cubic' && vars.type !== 'quadratic' && vars.type !== 'soft' ? GsapBezier.bezierThrough(vars.vars, isNaN(vars.curviness) ? 1 : vars.curviness, false, vars.type === 'thruBasic', vars.correlate, vars.startPoint) : GsapBezier.parseBezierData(vars);
this._segCount = this._beziers.x.length;
if (this._timeRes) {
var ld = GsapBezier.parseLengthData(this._beziers, this._timeRes);
this._length = ld.length;
this._lengths = ld.lengths;
this._segments = ld.segments;
this._l1 = this._li = this._s1 = this._si = 0;
this._l2 = this._lengths[0];
this._curSeg = this._segments[0];
this._s2 = this._curSeg[0];
this._prec = 1 / this._curSeg.length;
}
},
set: function set(v) {
var segments = this._segCount;
var XYobj = {};
var curIndex = void 0;
var inv = void 0;
var i = void 0;
var p = void 0;
var b = void 0;
var t = void 0;
var val = void 0;
var l = void 0;
var lengths = void 0;
var curSeg = void 0;
var value = void 0;
var rotate = void 0;
if (!this._timeRes) {
var _cur = v >= 1 ? segments - 1 : segments * v >> 0;
curIndex = v < 0 ? 0 : _cur;
t = (v - curIndex * (1 / segments)) * segments;
} else {
lengths = this._lengths;
curSeg = this._curSeg;
value = v * this._length;
i = this._li;
if (value > this._l2 && i < segments - 1) {
l = segments - 1;
while (i < l && (this._l2 = lengths[++i]) <= value) {}
this._l1 = lengths[i - 1];
this._li = i;
this._curSeg = curSeg = this._segments[i];
this._s2 = curSeg[this._s1 = this._si = 0];
} else if (value < this._l1 && i > 0) {
while (i > 0 && (this._l1 = lengths[--i]) >= value) {}
if (i === 0 && value < this._l1) {
this._l1 = 0;
} else {
i++;
}
this._l2 = lengths[i];
this._li = i;
this._curSeg = curSeg = this._segments[i];
this._s1 = curSeg[(this._si = curSeg.length - 1) - 1] || 0;
this._s2 = curSeg[this._si];
}
curIndex = i;
value -= this._l1;
i = this._si;
if (value > this._s2 && i < curSeg.length - 1) {
l = curSeg.length - 1;
while (i < l && (this._s2 = curSeg[++i]) <= value) {}
this._s1 = curSeg[i - 1];
this._si = i;
} else if (value < this._s1 && i > 0) {
while (i > 0 && (this._s1 = curSeg[--i]) >= value) {}
if (i === 0 && value < this._s1) {
this._s1 = 0;
} else {
i++;
}
this._s2 = curSeg[i];
this._si = i;
}
t = (i + (value - this._s1) / (this._s2 - this._s1)) * this._prec || 0;
}
inv = 1 - t;
for (i = 1; i >= 0; i--) {
p = i ? 'x' : 'y';
b = this._beziers[p][curIndex];
val = (t * t * b.da + 3 * inv * (t * b.ca + inv * b.ba)) * t + b.a;
XYobj[p] = val;
}
if (this._autoRotate) {
var ar = this._autoRotate;
var b2 = void 0;
var x1 = void 0;
var y1 = void 0;
var x2 = void 0;
var y2 = void 0;
var add = void 0;
var conv = void 0;
i = ar.length;
while (--i > -1) {
p = ar[i][2];
add = ar[i][3] || 0;
conv = ar[i][4] === true ? 1 : _RAD2DEG;
b = this._beziers[ar[i][0]];
b2 = this._beziers[ar[i][1]];
if (b && b2) {
b = b[curIndex];
b2 = b2[curIndex];
x1 = b.a + (b.b - b.a) * t;
x2 = b.b + (b.c - b.b) * t;
x1 += (x2 - x1) * t;
x2 += (b.c + (b.d - b.c) * t - x2) * t;
y1 = b2.a + (b2.b - b2.a) * t;
y2 = b2.b + (b2.c - b2.b) * t;
y1 += (y2 - y1) * t;
y2 += (b2.c + (b2.d - b2.c) * t - y2) * t;
var _r = Math.atan2(y2 - y1, x2 - x1) * conv;
rotate = _r + add;
}
}
}
return rotate ? 'translate(' + XYobj.x + 'px,' + XYobj.y + 'px) rotate(' + rotate + 'deg)' : 'translate(' + XYobj.x + 'px,' + XYobj.y + 'px)';
},
getAnimStart: function getAnimStart(computedStyle, isSvg) {
var transform = computedStyle[isSvg ? 'transformSVG' : this.transform];
transform = transform === 'none' ? '' : transform;
var matrix = createMatrix(transform);
// this.startRotate = parseFloat((-Math.atan2(matrix.m21, matrix.m11) * _RAD2DEG).toFixed(2));
this.vars.startPoint = { x: matrix.e, y: matrix.f };
this.init();
},
setRatio: function setRatio(r, t, computedStyle) {
t.style.transform = this.set(r);
if (computedStyle) {
computedStyle.transformSVG = createMatrix(t.style.transform).toString();
}
}
};
Bezier.bezierThrough = GsapBezier.bezierThrough;
Bezier.cubicToQuadratic = GsapBezier.cubicToQuadratic;
Bezier.quadraticToCubic = function (a, b, c) {
return new GsapBezier.Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c);
};
export default Bezier;