252 lines
9.4 KiB
JavaScript
252 lines
9.4 KiB
JavaScript
import {
|
|
degToRads,
|
|
} from './common';
|
|
import {
|
|
extendPrototype,
|
|
} from './functionExtensions';
|
|
import DynamicPropertyContainer from './helpers/dynamicProperties';
|
|
import Matrix from '../3rd_party/transformation-matrix';
|
|
import PropertyFactory from './PropertyFactory';
|
|
|
|
const TransformPropertyFactory = (function () {
|
|
var defaultVector = [0, 0];
|
|
|
|
function applyToMatrix(mat) {
|
|
var _mdf = this._mdf;
|
|
this.iterateDynamicProperties();
|
|
this._mdf = this._mdf || _mdf;
|
|
if (this.a) {
|
|
mat.translate(-this.a.v[0], -this.a.v[1], this.a.v[2]);
|
|
}
|
|
if (this.s) {
|
|
mat.scale(this.s.v[0], this.s.v[1], this.s.v[2]);
|
|
}
|
|
if (this.sk) {
|
|
mat.skewFromAxis(-this.sk.v, this.sa.v);
|
|
}
|
|
if (this.r) {
|
|
mat.rotate(-this.r.v);
|
|
} else {
|
|
mat.rotateZ(-this.rz.v).rotateY(this.ry.v).rotateX(this.rx.v).rotateZ(-this.or.v[2])
|
|
.rotateY(this.or.v[1])
|
|
.rotateX(this.or.v[0]);
|
|
}
|
|
if (this.data.p.s) {
|
|
if (this.data.p.z) {
|
|
mat.translate(this.px.v, this.py.v, -this.pz.v);
|
|
} else {
|
|
mat.translate(this.px.v, this.py.v, 0);
|
|
}
|
|
} else {
|
|
mat.translate(this.p.v[0], this.p.v[1], -this.p.v[2]);
|
|
}
|
|
}
|
|
function processKeys(forceRender) {
|
|
if (this.elem.globalData.frameId === this.frameId) {
|
|
return;
|
|
}
|
|
if (this._isDirty) {
|
|
this.precalculateMatrix();
|
|
this._isDirty = false;
|
|
}
|
|
|
|
this.iterateDynamicProperties();
|
|
|
|
if (this._mdf || forceRender) {
|
|
var frameRate;
|
|
this.v.cloneFromProps(this.pre.props);
|
|
if (this.appliedTransformations < 1) {
|
|
this.v.translate(-this.a.v[0], -this.a.v[1], this.a.v[2]);
|
|
}
|
|
if (this.appliedTransformations < 2) {
|
|
this.v.scale(this.s.v[0], this.s.v[1], this.s.v[2]);
|
|
}
|
|
if (this.sk && this.appliedTransformations < 3) {
|
|
this.v.skewFromAxis(-this.sk.v, this.sa.v);
|
|
}
|
|
if (this.r && this.appliedTransformations < 4) {
|
|
this.v.rotate(-this.r.v);
|
|
} else if (!this.r && this.appliedTransformations < 4) {
|
|
this.v.rotateZ(-this.rz.v).rotateY(this.ry.v).rotateX(this.rx.v).rotateZ(-this.or.v[2])
|
|
.rotateY(this.or.v[1])
|
|
.rotateX(this.or.v[0]);
|
|
}
|
|
if (this.autoOriented) {
|
|
var v1;
|
|
var v2;
|
|
frameRate = this.elem.globalData.frameRate;
|
|
if (this.p && this.p.keyframes && this.p.getValueAtTime) {
|
|
if (this.p._caching.lastFrame + this.p.offsetTime <= this.p.keyframes[0].t) {
|
|
v1 = this.p.getValueAtTime((this.p.keyframes[0].t + 0.01) / frameRate, 0);
|
|
v2 = this.p.getValueAtTime(this.p.keyframes[0].t / frameRate, 0);
|
|
} else if (this.p._caching.lastFrame + this.p.offsetTime >= this.p.keyframes[this.p.keyframes.length - 1].t) {
|
|
v1 = this.p.getValueAtTime((this.p.keyframes[this.p.keyframes.length - 1].t / frameRate), 0);
|
|
v2 = this.p.getValueAtTime((this.p.keyframes[this.p.keyframes.length - 1].t - 0.05) / frameRate, 0);
|
|
} else {
|
|
v1 = this.p.pv;
|
|
v2 = this.p.getValueAtTime((this.p._caching.lastFrame + this.p.offsetTime - 0.01) / frameRate, this.p.offsetTime);
|
|
}
|
|
} else if (this.px && this.px.keyframes && this.py.keyframes && this.px.getValueAtTime && this.py.getValueAtTime) {
|
|
v1 = [];
|
|
v2 = [];
|
|
var px = this.px;
|
|
var py = this.py;
|
|
if (px._caching.lastFrame + px.offsetTime <= px.keyframes[0].t) {
|
|
v1[0] = px.getValueAtTime((px.keyframes[0].t + 0.01) / frameRate, 0);
|
|
v1[1] = py.getValueAtTime((py.keyframes[0].t + 0.01) / frameRate, 0);
|
|
v2[0] = px.getValueAtTime((px.keyframes[0].t) / frameRate, 0);
|
|
v2[1] = py.getValueAtTime((py.keyframes[0].t) / frameRate, 0);
|
|
} else if (px._caching.lastFrame + px.offsetTime >= px.keyframes[px.keyframes.length - 1].t) {
|
|
v1[0] = px.getValueAtTime((px.keyframes[px.keyframes.length - 1].t / frameRate), 0);
|
|
v1[1] = py.getValueAtTime((py.keyframes[py.keyframes.length - 1].t / frameRate), 0);
|
|
v2[0] = px.getValueAtTime((px.keyframes[px.keyframes.length - 1].t - 0.01) / frameRate, 0);
|
|
v2[1] = py.getValueAtTime((py.keyframes[py.keyframes.length - 1].t - 0.01) / frameRate, 0);
|
|
} else {
|
|
v1 = [px.pv, py.pv];
|
|
v2[0] = px.getValueAtTime((px._caching.lastFrame + px.offsetTime - 0.01) / frameRate, px.offsetTime);
|
|
v2[1] = py.getValueAtTime((py._caching.lastFrame + py.offsetTime - 0.01) / frameRate, py.offsetTime);
|
|
}
|
|
} else {
|
|
v2 = defaultVector;
|
|
v1 = v2;
|
|
}
|
|
this.v.rotate(-Math.atan2(v1[1] - v2[1], v1[0] - v2[0]));
|
|
}
|
|
if (this.data.p && this.data.p.s) {
|
|
if (this.data.p.z) {
|
|
this.v.translate(this.px.v, this.py.v, -this.pz.v);
|
|
} else {
|
|
this.v.translate(this.px.v, this.py.v, 0);
|
|
}
|
|
} else {
|
|
this.v.translate(this.p.v[0], this.p.v[1], -this.p.v[2]);
|
|
}
|
|
}
|
|
this.frameId = this.elem.globalData.frameId;
|
|
}
|
|
|
|
function precalculateMatrix() {
|
|
this.appliedTransformations = 0;
|
|
this.pre.reset();
|
|
|
|
if (!this.a.effectsSequence.length) {
|
|
this.pre.translate(-this.a.v[0], -this.a.v[1], this.a.v[2]);
|
|
this.appliedTransformations = 1;
|
|
} else {
|
|
return;
|
|
}
|
|
if (!this.s.effectsSequence.length) {
|
|
this.pre.scale(this.s.v[0], this.s.v[1], this.s.v[2]);
|
|
this.appliedTransformations = 2;
|
|
} else {
|
|
return;
|
|
}
|
|
if (this.sk) {
|
|
if (!this.sk.effectsSequence.length && !this.sa.effectsSequence.length) {
|
|
this.pre.skewFromAxis(-this.sk.v, this.sa.v);
|
|
this.appliedTransformations = 3;
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
if (this.r) {
|
|
if (!this.r.effectsSequence.length) {
|
|
this.pre.rotate(-this.r.v);
|
|
this.appliedTransformations = 4;
|
|
}
|
|
} else if (!this.rz.effectsSequence.length && !this.ry.effectsSequence.length && !this.rx.effectsSequence.length && !this.or.effectsSequence.length) {
|
|
this.pre.rotateZ(-this.rz.v).rotateY(this.ry.v).rotateX(this.rx.v).rotateZ(-this.or.v[2])
|
|
.rotateY(this.or.v[1])
|
|
.rotateX(this.or.v[0]);
|
|
this.appliedTransformations = 4;
|
|
}
|
|
}
|
|
|
|
function autoOrient() {
|
|
//
|
|
// var prevP = this.getValueAtTime();
|
|
}
|
|
|
|
function addDynamicProperty(prop) {
|
|
this._addDynamicProperty(prop);
|
|
this.elem.addDynamicProperty(prop);
|
|
this._isDirty = true;
|
|
}
|
|
|
|
function TransformProperty(elem, data, container) {
|
|
this.elem = elem;
|
|
this.frameId = -1;
|
|
this.propType = 'transform';
|
|
this.data = data;
|
|
this.v = new Matrix();
|
|
// Precalculated matrix with non animated properties
|
|
this.pre = new Matrix();
|
|
this.appliedTransformations = 0;
|
|
this.initDynamicPropertyContainer(container || elem);
|
|
if (data.p && data.p.s) {
|
|
this.px = PropertyFactory.getProp(elem, data.p.x, 0, 0, this);
|
|
this.py = PropertyFactory.getProp(elem, data.p.y, 0, 0, this);
|
|
if (data.p.z) {
|
|
this.pz = PropertyFactory.getProp(elem, data.p.z, 0, 0, this);
|
|
}
|
|
} else {
|
|
this.p = PropertyFactory.getProp(elem, data.p || { k: [0, 0, 0] }, 1, 0, this);
|
|
}
|
|
if (data.rx) {
|
|
this.rx = PropertyFactory.getProp(elem, data.rx, 0, degToRads, this);
|
|
this.ry = PropertyFactory.getProp(elem, data.ry, 0, degToRads, this);
|
|
this.rz = PropertyFactory.getProp(elem, data.rz, 0, degToRads, this);
|
|
if (data.or.k[0].ti) {
|
|
var i;
|
|
var len = data.or.k.length;
|
|
for (i = 0; i < len; i += 1) {
|
|
data.or.k[i].to = null;
|
|
data.or.k[i].ti = null;
|
|
}
|
|
}
|
|
this.or = PropertyFactory.getProp(elem, data.or, 1, degToRads, this);
|
|
// sh Indicates it needs to be capped between -180 and 180
|
|
this.or.sh = true;
|
|
} else {
|
|
this.r = PropertyFactory.getProp(elem, data.r || { k: 0 }, 0, degToRads, this);
|
|
}
|
|
if (data.sk) {
|
|
this.sk = PropertyFactory.getProp(elem, data.sk, 0, degToRads, this);
|
|
this.sa = PropertyFactory.getProp(elem, data.sa, 0, degToRads, this);
|
|
}
|
|
this.a = PropertyFactory.getProp(elem, data.a || { k: [0, 0, 0] }, 1, 0, this);
|
|
this.s = PropertyFactory.getProp(elem, data.s || { k: [100, 100, 100] }, 1, 0.01, this);
|
|
// Opacity is not part of the transform properties, that's why it won't use this.dynamicProperties. That way transforms won't get updated if opacity changes.
|
|
if (data.o) {
|
|
this.o = PropertyFactory.getProp(elem, data.o, 0, 0.01, elem);
|
|
} else {
|
|
this.o = { _mdf: false, v: 1 };
|
|
}
|
|
this._isDirty = true;
|
|
if (!this.dynamicProperties.length) {
|
|
this.getValue(true);
|
|
}
|
|
}
|
|
|
|
TransformProperty.prototype = {
|
|
applyToMatrix: applyToMatrix,
|
|
getValue: processKeys,
|
|
precalculateMatrix: precalculateMatrix,
|
|
autoOrient: autoOrient,
|
|
};
|
|
|
|
extendPrototype([DynamicPropertyContainer], TransformProperty);
|
|
TransformProperty.prototype.addDynamicProperty = addDynamicProperty;
|
|
TransformProperty.prototype._addDynamicProperty = DynamicPropertyContainer.prototype.addDynamicProperty;
|
|
|
|
function getTransformProperty(elem, data, container) {
|
|
return new TransformProperty(elem, data, container);
|
|
}
|
|
|
|
return {
|
|
getTransformProperty: getTransformProperty,
|
|
};
|
|
}());
|
|
|
|
export default TransformPropertyFactory;
|