tween24
Version:
Tween24.js is animation library that enables fast coding using method chains.
376 lines (320 loc) • 13.6 kB
text/typescript
import { ColorUtil } from "../../utils/ColorUtil";
import { StringUtil } from "../../utils/StringUtil";
import { ParamUpdater } from "./ParamUpdater";
export class MultiParamUpdater {
private static _chache:Map<HTMLElement, Map<string, StyleParam4>>;
private _target :HTMLElement;
private _key :string;
private _type :string;
private _params :StyleParam4;
private _updater :ParamUpdater4|null;
private _numParams :number;
private _chache :Map<string, StyleParam4>;
private _separator :string|null;
private _numParams2:number;
private _params2 :StyleParam4|null;
private _updater2 :ParamUpdater4|null;
private _useColor :boolean;
private _colorParams :StyleParam4|null;
private _colorUpdater:ParamUpdater4|null;
private _isUpdate :boolean;
constructor(target:HTMLElement, key:string, type:string, numParam:number, useColor:boolean = false, separator:string|null = null, numParam2:number = NaN) {
this._key = key;
this._target = target
this._type = type;
this._numParams = numParam;
this._useColor = useColor;
this._params = new StyleParam4();
this._updater = null;
this._separator = separator;
this._numParams2 = numParam2;
this._params2 = null;
this._updater2 = null;
this._colorParams = null;
this._colorUpdater = null;
this._isUpdate = false;
MultiParamUpdater._chache ||= new Map<HTMLElement, Map<string, StyleParam4>>();
const chache = MultiParamUpdater._chache.get(this._target);
if (chache) this._chache = chache;
else {
this._chache = new Map<string, StyleParam4>();
MultiParamUpdater._chache.set(this._target, this._chache);
}
}
init = (start:string) => {
this._setParams(start);
this._updater?.init(this._params);
if (this._params2) this._updater2?.init(this._params2);
if (this._colorParams) this._colorUpdater?.init(this._colorParams);
}
private _setParams = (paramValue:string) => {
if (this._useColor) {
const colorMatch = paramValue.match(String.raw`(rgb\().*?(\))`);
if (colorMatch) {
const color = colorMatch[0];
const rgb = color.split("rgb(")[1].split(")")[0];
this._colorParams ||= new StyleParam4();
this._colorParams.init(rgb.length ? rgb : "0,0,0", 3, ",");
paramValue = paramValue.replace(color, "");
}
}
let p1 = "";
let p2 = undefined;
if (paramValue.indexOf(this._type) > -1) {
const match = paramValue.split(`${this._type}(`)[1].split(")")[0];
if (match) {
let matchValue = match;
if (this._separator && matchValue.indexOf(this._separator) > -1) {
const matchList = matchValue.split(this._separator);
p1 = matchList[0];
p2 = matchList[1];
}
else {
p1 = matchValue;
}
}
}
this._params.init(p1, this._numParams);
if (this._updater2 || p2) {
this._params2 ||= new StyleParam4();
this._params2.init(p2 || "", this._numParams2);
}
}
addPropStr = (index:number, value:string) => {
this._updater ||= new ParamUpdater4(this._numParams);
this._updater.setUpdater(index, value);
this._isUpdate = true;
}
addPropStr2 = (index:number, value:string) => {
this._updater2 ||= new ParamUpdater4(this._numParams2);
this._updater2.setUpdater(index, value);
this._isUpdate = true;
}
addPropColor = (colorCode:string) => {
this._colorUpdater = new ParamUpdater4(3);
const color = ColorUtil.getRGBList(colorCode);
this._colorUpdater.setUpdater(0, color[0] + "");
this._colorUpdater.setUpdater(1, color[1] + "");
this._colorUpdater.setUpdater(2, color[2] + "");
this._isUpdate = true;
}
update = (progress:number):string => {
const chache1 = this._chache.get(this._type);
const chache2 = this._chache.get(this._type + this._separator);
const chache3 = this._chache.get(this._type + "rgb");
if (!chache1 || (this._updater2 && !chache2) || (this._colorUpdater && !chache3)) {
this._setParams(getComputedStyle(this._target).getPropertyValue(this._key));
}
else {
this._params.copy(chache1);
if (chache2) {
if (this._params2) this._params2.copy(chache2);
else this._params2 = chache2.clone();
}
if (chache3) {
if (this._colorParams) this._colorParams.copy(chache3);
else this._colorParams = chache3.clone();
}
}
// Param1
let result = this._type + "(";
this._updater?.update(this._params, progress);
result += this._params.param;
// Chache
if (progress != 1) this._chache.set(this._type, this._params);
else this._chache.delete(this._type);
// Param2
if (this._params2) {
if (this._updater2) {
this._updater2.update(this._params2, progress);
}
result += ` ${this._separator} ${this._params2.param}`;
// Chache
if (progress != 1) this._chache.set(this._type + this._separator, this._params2);
else this._chache.delete(this._type + this._separator);
}
// Color
if (this._colorParams) {
if (this._colorUpdater) {
this._colorUpdater.update(this._colorParams, progress);
}
result += ` rgb(${this._colorParams.param})`;
// Chache
if (progress != 1) this._chache.set(this._type + "rgb", this._colorParams);
else this._chache.delete(this._type + "rgb");
}
result += ")";
return result;
}
overwrite = (updater:MultiParamUpdater) => {
if (updater._target == this._target) {
if (updater._type == this._type) {
if (updater._updater ) this._updater ?.overwrite(updater._updater );
if (updater._updater2 ) this._updater2 ?.overwrite(updater._updater2 );
if (updater._colorUpdater) this._colorUpdater?.overwrite(updater._colorUpdater);
}
}
}
getDelta = ():number => {
const d0:number = this._updater ?.getDelta() || 1;
const d1:number = this._updater2?.getDelta() || 1;
return Math.max(d0, d1);
}
clone = (target:HTMLElement):MultiParamUpdater => {
const mpu = new MultiParamUpdater(target, this._key, this._type, this._numParams, this._useColor, this._separator, this._numParams2);
if (this._updater ) mpu._updater = this._updater .clone();
if (this._updater2 ) mpu._updater2 = this._updater2 .clone();
if (this._colorUpdater) mpu._colorUpdater = this._colorUpdater.clone();
return mpu;
}
toString = ():string => {
let result = `${this._type}(${this._updater?.toString() || "none"}`;
if (this._updater2) result += ` ${this._separator} ${this._updater2.toString()}`;
if (this._colorUpdater) result += ` rgb(${this._colorUpdater.toString()})`;
result += `)`;
return result;
}
get key():string {
return this._key;
}
get isUpdate():boolean {
return this._isUpdate;
}
}
class StyleParam4 {
value0:number = NaN;
value1:number = NaN;
value2:number = NaN;
value3:number = NaN;
unit0 :string = "";
unit1 :string = "";
unit2 :string = "";
unit3 :string = "";
private _spliter:string = " ";
constructor() {}
init = (param:string, numParams:number, spliter:string = " ") => {
let p0, p1, p2, p3;
const params = param.trim().split(spliter);
this._spliter = spliter;
p0 = params[0] || "0";
this.value0 = parseFloat(p0);
this.unit0 = StringUtil.getUnit(p0);
if (numParams > 1) {
p1 = params[1] || p0;
this.value1 = parseFloat(p1);
this.unit1 = StringUtil.getUnit(p1);
if (numParams > 2) {
p2 = params[2] || p0;
this.value2 = parseFloat(p2);
this.unit2 = StringUtil.getUnit(p2);
if (numParams > 3) {
p3 = params[3] || p1;
this.value3 = parseFloat(p3);
this.unit3 = StringUtil.getUnit(p3);
}
}
}
}
toString = ():string => {
let result = "";
if (isNaN(this.value0)) result = "none";
else {
result += this.value0 + this.unit0 + " ";
result += isNaN(this.value1) ? "none " : this.value1 + this.unit1 + this._spliter;
result += isNaN(this.value2) ? "none " : this.value2 + this.unit2 + this._spliter;
result += isNaN(this.value3) ? "none" : this.value3 + this.unit3;
}
return result;
}
copy = (from:StyleParam4) => {
this.value0 = from.value0;
this.value1 = from.value1;
this.value2 = from.value2;
this.value3 = from.value3;
this.unit0 = from.unit0;
this.unit1 = from.unit1;
this.unit2 = from.unit2;
this.unit3 = from.unit3;
return this;
}
clone = ():StyleParam4 => {
return new StyleParam4().copy(this);
}
get param():string {
let result = this.value0 + this.unit0;
if (!isNaN(this.value1)) result += this._spliter + this.value1 + this.unit1;
if (!isNaN(this.value2)) result += this._spliter + this.value2 + this.unit2;
if (!isNaN(this.value3)) result += this._spliter + this.value3 + this.unit3;
return result;
}
}
class ParamUpdater4 {
private _u0:ParamUpdater|null;
private _u1:ParamUpdater|null;
private _u2:ParamUpdater|null;
private _u3:ParamUpdater|null;
private _numParams:number;
constructor(numParams:number) {
this._u0 = null;
this._u1 = null;
this._u2 = null;
this._u3 = null;
this._numParams = numParams;
}
setUpdater = (index:number, value:string) => {
const u = new ParamUpdater("", parseFloat(value), value);
u.setUnit(StringUtil.getUnit(value));
switch (index) {
case 0 : this._u0 = u; break;
case 1 : this._u1 = u; break;
case 2 : this._u2 = u; break;
case 3 : this._u3 = u; break;
}
}
init = (param4:StyleParam4) => {
this._init(this._u0, param4.value0, param4.unit0);
this._init(this._u1, param4.value1, param4.unit1);
this._init(this._u2, param4.value2, param4.unit2);
this._init(this._u3, param4.value3, param4.unit3);
}
private _init = (u:ParamUpdater|null, v:number, ut:string) => {
if (u) {
u.init(v);
if (u.unit.length == 0) u.setUnit(ut);
}
}
update = (param4:StyleParam4, progress:number) => {
if (this._u0?.isActive) { param4.value0 = this._u0.update(progress); param4.unit0 = this._u0.unit; }
if (this._u1?.isActive) { param4.value1 = this._u1.update(progress); param4.unit1 = this._u1.unit; }
if (this._u2?.isActive) { param4.value2 = this._u2.update(progress); param4.unit2 = this._u2.unit; }
if (this._u3?.isActive) { param4.value3 = this._u3.update(progress); param4.unit3 = this._u3.unit; }
}
overwrite = (updater:ParamUpdater4) => {
if (updater._u0) this._u0?.unActive();
if (updater._u1) this._u1?.unActive();
if (updater._u2) this._u2?.unActive();
if (updater._u3) this._u3?.unActive();
}
getDelta = ():number => {
const d0:number = this._u0?.getDelta() || 1;
const d1:number = this._u1?.getDelta() || 1;
const d2:number = this._u2?.getDelta() || 1;
const d3:number = this._u3?.getDelta() || 1;
return Math.max(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2 + d3 * d3));
}
clone = ():ParamUpdater4 => {
const updater = new ParamUpdater4(this._numParams);
if (this._u0) updater._u0 = this._u0.clone();
if (this._u1) updater._u1 = this._u1.clone();
if (this._u2) updater._u2 = this._u2.clone();
if (this._u3) updater._u3 = this._u3.clone();
return updater;
}
toString = ():string => {
let result = this._u0 ? this._u0.targetParam + " " : "none ";
if (this._numParams > 1) result += this._u1 ? this._u1.targetParam + " " : "none ";
if (this._numParams > 2) result += this._u2 ? this._u2.targetParam + " " : "none ";
if (this._numParams > 3) result += this._u3 ? this._u3.targetParam : "none";
return result.trim();
}
}