qarl 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/types/Core.d.ts +196 -1
- package/types/Curve.d.ts +48 -0
- package/types/FromTo.d.ts +73 -0
- package/types/Loop.d.ts +47 -0
- package/types/Manager.d.ts +101 -0
- package/types/common.d.ts +226 -2
- package/types/defaults.d.ts +19 -0
- package/types/easings.d.ts +32 -0
- package/types/events.d.ts +19 -0
- package/types/index.d.ts +27 -0
- package/types/modes.d.ts +17 -0
- package/types/play.d.ts +24 -0
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var R=Object.create;var L=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var q=(t,s,e)=>s in t?L(t,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[s]=e;var N=(t,s)=>()=>(s||t((s={exports:{}}).exports,s),s.exports);var Y=(t,s,e,i)=>{if(s&&typeof s=="object"||typeof s=="function")for(let r of V(s))!G.call(t,r)&&r!==e&&L(t,r,{get:()=>s[r],enumerable:!(i=j(s,r))||i.enumerable});return t};var z=(t,s,e)=>(e=t!=null?R(B(t)):{},Y(s||!t||!t.__esModule?L(e,"default",{value:t,enumerable:!0}):e,t));var y=(t,s,e)=>(q(t,typeof s!="symbol"?s+"":s,e),e);var k=N(($,b)=>{"use strict";var K=Object.prototype.hasOwnProperty,g="~";function T(){}Object.create&&(T.prototype=Object.create(null),new T().__proto__||(g=!1));function H(t,s,e){this.fn=t,this.context=s,this.once=e||!1}function F(t,s,e,i,r){if(typeof e!="function")throw new TypeError("The listener must be a function");var n=new H(e,i||t,r),a=g?g+s:s;return t._events[a]?t._events[a].fn?t._events[a]=[t._events[a],n]:t._events[a].push(n):(t._events[a]=n,t._eventsCount++),t}function D(t,s){--t._eventsCount===0?t._events=new T:delete t._events[s]}function f(){this._events=new T,this._eventsCount=0}f.prototype.eventNames=function(){var s=[],e,i;if(this._eventsCount===0)return s;for(i in e=this._events)K.call(e,i)&&s.push(g?i.slice(1):i);return Object.getOwnPropertySymbols?s.concat(Object.getOwnPropertySymbols(e)):s};f.prototype.listeners=function(s){var e=g?g+s:s,i=this._events[e];if(!i)return[];if(i.fn)return[i.fn];for(var r=0,n=i.length,a=new Array(n);r<n;r++)a[r]=i[r].fn;return a};f.prototype.listenerCount=function(s){var e=g?g+s:s,i=this._events[e];return i?i.fn?1:i.length:0};f.prototype.emit=function(s,e,i,r,n,a){var p=g?g+s:s;if(!this._events[p])return!1;var o=this._events[p],l=arguments.length,m,h;if(o.fn){switch(o.once&&this.removeListener(s,o.fn,void 0,!0),l){case 1:return o.fn.call(o.context),!0;case 2:return o.fn.call(o.context,e),!0;case 3:return o.fn.call(o.context,e,i),!0;case 4:return o.fn.call(o.context,e,i,r),!0;case 5:return o.fn.call(o.context,e,i,r,n),!0;case 6:return o.fn.call(o.context,e,i,r,n,a),!0}for(h=1,m=new Array(l-1);h<l;h++)m[h-1]=arguments[h];o.fn.apply(o.context,m)}else{var I=o.length,c;for(h=0;h<I;h++)switch(o[h].once&&this.removeListener(s,o[h].fn,void 0,!0),l){case 1:o[h].fn.call(o[h].context);break;case 2:o[h].fn.call(o[h].context,e);break;case 3:o[h].fn.call(o[h].context,e,i);break;case 4:o[h].fn.call(o[h].context,e,i,r);break;default:if(!m)for(c=1,m=new Array(l-1);c<l;c++)m[c-1]=arguments[c];o[h].fn.apply(o[h].context,m)}}return!0};f.prototype.on=function(s,e,i){return F(this,s,e,i,!1)};f.prototype.once=function(s,e,i){return F(this,s,e,i,!0)};f.prototype.removeListener=function(s,e,i,r){var n=g?g+s:s;if(!this._events[n])return this;if(!e)return D(this,n),this;var a=this._events[n];if(a.fn)a.fn===e&&(!r||a.once)&&(!i||a.context===i)&&D(this,n);else{for(var p=0,o=[],l=a.length;p<l;p++)(a[p].fn!==e||r&&!a[p].once||i&&a[p].context!==i)&&o.push(a[p]);o.length?this._events[n]=o.length===1?o[0]:o:D(this,n)}return this};f.prototype.removeAllListeners=function(s){var e;return s?(e=g?g+s:s,this._events[e]&&D(this,e)):(this._events=new T,this._eventsCount=0),this};f.prototype.off=f.prototype.removeListener;f.prototype.addListener=f.prototype.on;f.prefixed=g;f.EventEmitter=f;typeof b<"u"&&(b.exports=f)});var U=z(k(),1);var Q=U.default;var C={processors:[],time:0,loop:!1,mode:null,delay:0,repeat:0,target:null,easing:t=>t,reversed:!1,repeatDelay:0,autoApplyProcessors:!0};var _={PLAY:"play",STOP:"stop",BEGIN:"begin",UPDATE:"update",REPEAT:"repeat",COMPLETE:"complete"};var x=Math.PI*2,v=Math.pow,E={reverse:t=>1-t,linear:t=>t,yoyo:t=>1-Math.abs(1-t*2),inQuad:t=>v(t,2),outQuad:t=>1-(1-t)*(1-t),inOutQuad:t=>t<.5?2*t*t:-1+(4-2*t)*t,inCubic:t=>v(t,3),outCubic:t=>--t*t*t+1,inOutCubic:t=>t<.5?4*v(t,3):(t-1)*(2*t-2)*(2*t-2)+1,inQuart:t=>v(t,4),outQuart:t=>1- --t*v(t,3),inOutQuart:t=>t<.5?8*v(t,4):1-8*--t*t*t*t,inQuint:t=>v(t,5),outQuint:t=>1+--t*v(t,4),inOutQuint:t=>t<.5?16*v(t,5):1+16*--t*t*t*t*t,inSine:t=>1-Math.cos(t*Math.PI/2),outSine:t=>Math.sin(t*Math.PI/2),inOutSine:t=>-(Math.cos(Math.PI*t)-1)/2,inBack:(t,s=1.70158)=>t*t*((s+1)*t-s),outBack:(t,s=1.70158)=>(t-=1)*t*((s+1)*t+s)+1,inOutBack:(t,s=1.70158)=>(t*=2)<1?.5*(t*t*((s*1.525+1)*t-s*1.525)):.5*((t-=2)*t*((s*1.525+1)*t+s*1.525)+2),inExpo:t=>t===0?0:Math.pow(2,10*(t-1)),outExpo:t=>t===1?1:1-Math.pow(2,-10*t),inOutExpo:t=>t===0?0:t===1?1:t<.5?.5*Math.pow(2,20*t-10):1-.5*Math.pow(2,-20*t+10),inElastic:(t,s=1,e=.5)=>t===0?0:t===1?1:-s*Math.pow(2,10*(t-1))*Math.sin((t-1-e/x*Math.asin(1/s))*x/e),outElastic:(t,s=1,e=.5)=>t===0?0:t===1?1:s*Math.pow(2,-10*t)*Math.sin((t-e/x*Math.asin(1/s))*x/e)+1,inOutElastic:(t,s=1,e=.5)=>t===0?0:t===1?1:t<.5?-.5*s*Math.pow(2,20*t-10)*Math.sin((20*t-11.125)*x/e):.5*s*Math.pow(2,-20*t+10)*Math.sin((20*t-11.125)*x/e)+1};var O={pingPong:function(t){return t<=.5?this._easing(t*2):1-this._easing((t-.5)*2)},yoyo:function(t){return this._easing(E.yoyo(t))},bounce:function(t){return E.yoyo(this._easing(t))}};var J=0,d=class d extends Q{constructor(e={},i){super();y(this,"_reversedEasing",e=>this.settings.easing(1-e));y(this,"_stepDelay",e=>{this.remainingDelay-=e,this.lastDeltaTime=e,!(this.remainingDelay>0)&&(this.emit(_.BEGIN),this.step=this._stepTime,this.step(Math.abs(this.remainingDelay)),this.remainingDelay=this.settings.delay)});y(this,"_stepTime",(e=0)=>{this.elapsedTime+=e,this.lastDeltaTime=e,this.elapsedTime>=this.time?(this.elapsedTime=this.time,this._update(),this._complete()):this._update()});this.index=J++,this.overrides=e,this.settings={},this.reset(e),i&&(this.manager=i),this.lastDeltaTime=0}on(...e){return super.on(...e),this}off(...e){return super.off(...e),this}once(...e){return super.once(...e),this}onComplete(...e){return super.on(_.COMPLETE,...e),this}onUpdate(...e){return super.on(_.UPDATE,...e),this}onceComplete(...e){return super.once(_.COMPLETE,...e),this}static _noop(){}static mergeConfigs(e,i){e!==i&&Object.keys(i).forEach(r=>{typeof i[r]=="object"&&i[r]!==null?((!e[r]||typeof e[r]!="object")&&(e[r]={}),d.mergeConfigs(e[r],i[r])):e[r]=i[r]})}static lerp(e,i,r){return e+(i-e)*r}_processState(){this.step=d._noop,this.progress=0,this.easeValue=0,this.elapsedTime=0,this.promise=null,this._resolve=d._noop,this._refreshDynamicProps()}_refreshDynamicProps(){this.applyProcessors(this.settings);let{target:e,time:i,repeat:r,loop:n,reversed:a,delay:p}=this.settings;this.target=e,this.time=Math.max(i,0),this.repeat=r>0?r:n?1/0:0,this.reversed=a,this.remainingDelay=p,this._processEasing()}_processEasing(){let e=typeof this.settings.easing=="string"?E[this.settings.easing]||E.linear:this.settings.easing;this._easing=this.reversed?this._reversedEasing:e;let i=typeof this.settings.mode=="string"?O[this.settings.mode]:this.settings.mode;this._calculateEasing=i?i.bind(this):this._easing}_update(){this.progress=this.elapsedTime/this.time,this.easeValue=this._calculateEasing(this.progress),this.emit(_.UPDATE,this)}_complete(){this.repeat-- >0?this._repeat():(this._resolve(),this.stop(!1),this.emit(_.COMPLETE))}_repeat(e=!0){this.remainingDelay=this.settings.repeatDelay,this.elapsedTime=0,this.remainingDelay>0&&(this.step=this._stepDelay),this._update(),e&&this.emit(_.REPEAT)}reset(e=this.constructor.DEFAULTS){return this.settings={...this.constructor.DEFAULTS,...e},this._processState(),this}applyProcessors(e=this.settings){e.processors.forEach(i=>{d.mergeConfigs(e,i.call(this,e)||{})})}tweak(e={}){return d.mergeConfigs(this.settings,e),this._refreshDynamicProps(),this}seek(e=0,i=!0){return this.elapsedTime=Math.min(Math.max(e,0),this.time),i&&this._update(),this}setProgress(e=0,i=!0){return this.seek(this.time*e,i)}reverse(e=!1){return this.reversed=!this.reversed,this.seek(this.time-this.elapsedTime,e),this._processEasing(),this}play(e=!0){return this.isPlaying?this:(this.settings.autoApplyProcessors&&this._refreshDynamicProps(),e&&this.emit(_.PLAY),this.remainingDelay>0?this.step=this._stepDelay:(this.step=this._stepTime,this.emit(_.BEGIN)),this.manager&&this.manager.addToActive(this),this)}playPromise(e=this.promise){return this.play(),this.promise=e||new Promise(i=>{this._resolve=i}),this.promise}stop(e=!0){return this._processState(),e&&this.emit(_.STOP),this.manager&&this.manager.removeFromActive(this),this}pause(){return this.step=d._noop,this.manager&&this.manager.removeFromActive(this),this}replay(e=!1){return this.stop(e),this.play(e),this}get isPlaying(){return this.step!==d._noop}remove(){this.stop(),this.manager.remove(this)}};y(d,"DEFAULTS",C);var u=d;var P=class extends u{_preparePropertySetters(){this.propertySetters=this.properties.map(s=>{let e=s.split("."),i=e.pop();return r=>{let n=this.target;for(let a=0;a<e.length;a++)n=n[e[a]];n[i]=r}})}_generatePath(){let s=this.settings.points,e=Math.max(this.settings.smoothing,1),i=[];this.totalLength=0;function r(n,a,p,o,l){let m=l*l,h=m*l;return n.map((I,c)=>.5*(2*a[c]+(-n[c]+p[c])*l+(2*n[c]-5*a[c]+4*p[c]-o[c])*m+(-n[c]+3*a[c]-3*p[c]+o[c])*h))}for(let n=0;n<s.length-1;n++){let a=s[n===0?n:n-1],p=s[n],o=s[n+1],l=s[n+2<s.length?n+2:n+1];for(let m=0;m<e;m++){let h=r(a,p,o,l,m/e);i.push(h),i.length>1&&(this.totalLength+=this._calculateDistance(i[i.length-2],h))}}return i.push(s[s.length-1]),i}_calculateDistance(s,e){return Math.sqrt(s.reduce((i,r,n)=>i+Math.pow(e[n]-s[n],2),0))}_refreshDynamicProps(){super._refreshDynamicProps(),this.path=this._generatePath(),!this.target||this.path.length===0?this._setTargetProperties=u._noop:(this._tryToSetupProperties(),this._preparePropertySetters())}_tryToSetupProperties(){if(this.settings.properties)this.properties=this.settings.properties;else if(this.path[0].length<=3){let s=[["position.x"],["position.x","position.y"],["position.x","position.y","position.z"]];this.properties=s[this.path[0].length-1]}else this.properties=[]}_setTargetProperties(s){for(let e=0;e<this.propertySetters.length;e++)this.propertySetters[e](s[e])}_clamp(s,e,i){return Math.max(e,Math.min(s,i))}_getInterpolatedPosition(){let s=this.path.length-1,e=this.easeValue*s,i=this._clamp(e,0,s),r=i>=s?s-1:Math.floor(i),n=Math.min(r+1,s),a=e-r,p=this.path[r],o=this.path[n];return p.map((l,m)=>u.lerp(l,o[m],a))}_update(){super._update(),this._setTargetProperties(this._getInterpolatedPosition())}};y(P,"DEFAULTS",{...u.DEFAULTS,properties:null,points:[],smoothing:20});var A=class extends u{_refreshDynamicProps(){super._refreshDynamicProps(),this._processFromTo()}_processFromTo(){this._lerps=[],this.target&&(this._setupStates(),this._createLerps())}_setupStates(){this._from=this.settings.from||this._createState(this.settings.to||{},this.target),this._to=this.settings.to||this._createState(this.settings.from||{},this.target)}_createState(s={},e={},i={}){let r=(n,a,p)=>{for(let o in n)typeof n[o]=="object"?(p[o]={},r(n[o],a[o],p[o])):p[o]=a[o]};return r(s,e,i),i}_createLerpStep(s,e,i,r){if(this.settings.dynamic)return()=>{s[r]=u.lerp(e[r],i[r],this.easeValue)};{let n=e[r],a=i[r]-n;return()=>{s[r]=n+a*this.easeValue}}}_createLerps(s=this.target,e=this._from,i=this._to){for(let r in i)typeof i[r]=="object"?this._createLerps(s[r],e[r],i[r]):this._lerps.push(this._createLerpStep(s,e,i,r))}_update(){super._update();for(let s of this._lerps)s()}from(s={}){return this.tweak({from:s}),this}to(s={}){return this.tweak({to:s}),this}swap(){return this.tweak({from:this.settings.to,to:this.settings.from}),this}};y(A,"DEFAULTS",{...u.DEFAULTS,dynamic:!1,from:null,to:null});function w(t){return t.target?t.creator?t.creator instanceof u?t.creator:(console.error("Invalid creator provided. Using default creator."),u):t.points?P:t.from||t.to?A:u:u}var S=class{constructor(){y(this,"update",s=>{this.activeAnimations.forEach(e=>{e.step(s)})});this.activeAnimations=new Map,this.allAnimations=new Map}create({on:s={},once:e={},...i}){let r=w(i),n=new r(i,this);return Object.keys(s).forEach(a=>{n.on(a,s[a])}),Object.keys(e).forEach(a=>{n.once(a,e[a])}),this.add(n),n}getActiveAnimations(){return Array.from(this.activeAnimations.values())}getAllAnimations(){return Array.from(this.allAnimations.values())}remove({index:s}={}){s&&(this.activeAnimations.delete(s),this.allAnimations.delete(s))}add(s){this.allAnimations.set(s.index,s)}addToActive(s){this.activeAnimations.set(s.index,s)}removeFromActive(s){this.activeAnimations.delete(s.index)}stopAll(){this.activeAnimations.forEach(s=>{s.stop()})}removeAll(){this.stopAll(),this.activeAnimations.clear(),this.allAnimations.clear()}};var W=new S;var M=class t{constructor(s,e={}){this.callback=s,this.options={maxDeltaTime:100,...e},this.isRunning=!1,this.lastTime=0,this.animationId=null}static start(s,e={}){let i=new t(s,e);return i.start(),i}start(){if(this.isRunning)return;this.isRunning=!0;let s=e=>{if(!this.isRunning)return;let i=Math.min(e-this.lastTime,this.options.maxDeltaTime);this.lastTime=e,this.callback(i),this.isRunning&&(this.animationId=requestAnimationFrame(s))};requestAnimationFrame(e=>{this.lastTime=e,s(e)})}stop(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}get running(){return this.isRunning}};function X(t,s){let e=new w(t),i=new e(t);return M.start(i.step.bind(i)),s?i.playPromise():i.play()}export{u as Core,P as Curve,C as DEFAULTS,_ as EVENTS,A as FromTo,W as GlobalManager,M as Loop,S as Manager,E as easings,O as modes,X as play};
|
|
1
|
+
var R=Object.create;var L=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var q=(t,s,e)=>s in t?L(t,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[s]=e;var N=(t,s)=>()=>(s||t((s={exports:{}}).exports,s),s.exports);var Y=(t,s,e,i)=>{if(s&&typeof s=="object"||typeof s=="function")for(let r of V(s))!G.call(t,r)&&r!==e&&L(t,r,{get:()=>s[r],enumerable:!(i=j(s,r))||i.enumerable});return t};var z=(t,s,e)=>(e=t!=null?R(B(t)):{},Y(s||!t||!t.__esModule?L(e,"default",{value:t,enumerable:!0}):e,t));var y=(t,s,e)=>(q(t,typeof s!="symbol"?s+"":s,e),e);var k=N(($,b)=>{"use strict";var K=Object.prototype.hasOwnProperty,g="~";function T(){}Object.create&&(T.prototype=Object.create(null),new T().__proto__||(g=!1));function H(t,s,e){this.fn=t,this.context=s,this.once=e||!1}function F(t,s,e,i,r){if(typeof e!="function")throw new TypeError("The listener must be a function");var n=new H(e,i||t,r),a=g?g+s:s;return t._events[a]?t._events[a].fn?t._events[a]=[t._events[a],n]:t._events[a].push(n):(t._events[a]=n,t._eventsCount++),t}function D(t,s){--t._eventsCount===0?t._events=new T:delete t._events[s]}function f(){this._events=new T,this._eventsCount=0}f.prototype.eventNames=function(){var s=[],e,i;if(this._eventsCount===0)return s;for(i in e=this._events)K.call(e,i)&&s.push(g?i.slice(1):i);return Object.getOwnPropertySymbols?s.concat(Object.getOwnPropertySymbols(e)):s};f.prototype.listeners=function(s){var e=g?g+s:s,i=this._events[e];if(!i)return[];if(i.fn)return[i.fn];for(var r=0,n=i.length,a=new Array(n);r<n;r++)a[r]=i[r].fn;return a};f.prototype.listenerCount=function(s){var e=g?g+s:s,i=this._events[e];return i?i.fn?1:i.length:0};f.prototype.emit=function(s,e,i,r,n,a){var p=g?g+s:s;if(!this._events[p])return!1;var o=this._events[p],l=arguments.length,m,h;if(o.fn){switch(o.once&&this.removeListener(s,o.fn,void 0,!0),l){case 1:return o.fn.call(o.context),!0;case 2:return o.fn.call(o.context,e),!0;case 3:return o.fn.call(o.context,e,i),!0;case 4:return o.fn.call(o.context,e,i,r),!0;case 5:return o.fn.call(o.context,e,i,r,n),!0;case 6:return o.fn.call(o.context,e,i,r,n,a),!0}for(h=1,m=new Array(l-1);h<l;h++)m[h-1]=arguments[h];o.fn.apply(o.context,m)}else{var I=o.length,c;for(h=0;h<I;h++)switch(o[h].once&&this.removeListener(s,o[h].fn,void 0,!0),l){case 1:o[h].fn.call(o[h].context);break;case 2:o[h].fn.call(o[h].context,e);break;case 3:o[h].fn.call(o[h].context,e,i);break;case 4:o[h].fn.call(o[h].context,e,i,r);break;default:if(!m)for(c=1,m=new Array(l-1);c<l;c++)m[c-1]=arguments[c];o[h].fn.apply(o[h].context,m)}}return!0};f.prototype.on=function(s,e,i){return F(this,s,e,i,!1)};f.prototype.once=function(s,e,i){return F(this,s,e,i,!0)};f.prototype.removeListener=function(s,e,i,r){var n=g?g+s:s;if(!this._events[n])return this;if(!e)return D(this,n),this;var a=this._events[n];if(a.fn)a.fn===e&&(!r||a.once)&&(!i||a.context===i)&&D(this,n);else{for(var p=0,o=[],l=a.length;p<l;p++)(a[p].fn!==e||r&&!a[p].once||i&&a[p].context!==i)&&o.push(a[p]);o.length?this._events[n]=o.length===1?o[0]:o:D(this,n)}return this};f.prototype.removeAllListeners=function(s){var e;return s?(e=g?g+s:s,this._events[e]&&D(this,e)):(this._events=new T,this._eventsCount=0),this};f.prototype.off=f.prototype.removeListener;f.prototype.addListener=f.prototype.on;f.prefixed=g;f.EventEmitter=f;typeof b<"u"&&(b.exports=f)});var U=z(k(),1);var Q=U.default;var C={processors:[],time:0,loop:!1,mode:null,delay:0,repeat:0,target:null,easing:t=>t,reversed:!1,repeatDelay:0,autoApplyProcessors:!1};var _={PLAY:"play",STOP:"stop",BEGIN:"begin",UPDATE:"update",REPEAT:"repeat",COMPLETE:"complete"};var x=Math.PI*2,v=Math.pow,E={reverse:t=>1-t,linear:t=>t,yoyo:t=>1-Math.abs(1-t*2),inQuad:t=>v(t,2),outQuad:t=>1-(1-t)*(1-t),inOutQuad:t=>t<.5?2*t*t:-1+(4-2*t)*t,inCubic:t=>v(t,3),outCubic:t=>--t*t*t+1,inOutCubic:t=>t<.5?4*v(t,3):(t-1)*(2*t-2)*(2*t-2)+1,inQuart:t=>v(t,4),outQuart:t=>1- --t*v(t,3),inOutQuart:t=>t<.5?8*v(t,4):1-8*--t*t*t*t,inQuint:t=>v(t,5),outQuint:t=>1+--t*v(t,4),inOutQuint:t=>t<.5?16*v(t,5):1+16*--t*t*t*t*t,inSine:t=>1-Math.cos(t*Math.PI/2),outSine:t=>Math.sin(t*Math.PI/2),inOutSine:t=>-(Math.cos(Math.PI*t)-1)/2,inBack:(t,s=1.70158)=>t*t*((s+1)*t-s),outBack:(t,s=1.70158)=>(t-=1)*t*((s+1)*t+s)+1,inOutBack:(t,s=1.70158)=>(t*=2)<1?.5*(t*t*((s*1.525+1)*t-s*1.525)):.5*((t-=2)*t*((s*1.525+1)*t+s*1.525)+2),inExpo:t=>t===0?0:Math.pow(2,10*(t-1)),outExpo:t=>t===1?1:1-Math.pow(2,-10*t),inOutExpo:t=>t===0?0:t===1?1:t<.5?.5*Math.pow(2,20*t-10):1-.5*Math.pow(2,-20*t+10),inElastic:(t,s=1,e=.5)=>t===0?0:t===1?1:-s*Math.pow(2,10*(t-1))*Math.sin((t-1-e/x*Math.asin(1/s))*x/e),outElastic:(t,s=1,e=.5)=>t===0?0:t===1?1:s*Math.pow(2,-10*t)*Math.sin((t-e/x*Math.asin(1/s))*x/e)+1,inOutElastic:(t,s=1,e=.5)=>t===0?0:t===1?1:t<.5?-.5*s*Math.pow(2,20*t-10)*Math.sin((20*t-11.125)*x/e):.5*s*Math.pow(2,-20*t+10)*Math.sin((20*t-11.125)*x/e)+1};var O={pingPong:function(t){return t<=.5?this._easing(t*2):1-this._easing((t-.5)*2)},yoyo:function(t){return this._easing(E.yoyo(t))},bounce:function(t){return E.yoyo(this._easing(t))}};var J=0,d=class d extends Q{constructor(e={},i){super();y(this,"_reversedEasing",e=>this.settings.easing(1-e));y(this,"_stepDelay",e=>{this.remainingDelay-=e,this.lastDeltaTime=e,!(this.remainingDelay>0)&&(this.emit(_.BEGIN),this.step=this._stepTime,this.step(Math.abs(this.remainingDelay)),this.remainingDelay=this.settings.delay)});y(this,"_stepTime",(e=0)=>{this.elapsedTime+=e,this.lastDeltaTime=e,this.elapsedTime>=this.time?(this.elapsedTime=this.time,this._update(),this._complete()):this._update()});this.index=J++,this.overrides=e,this.settings={},this.reset(e),i&&(this.manager=i),this.lastDeltaTime=0}on(...e){return super.on(...e),this}off(...e){return super.off(...e),this}once(...e){return super.once(...e),this}onComplete(...e){return super.on(_.COMPLETE,...e),this}onUpdate(...e){return super.on(_.UPDATE,...e),this}onceComplete(...e){return super.once(_.COMPLETE,...e),this}static _noop(){}static mergeConfigs(e,i){e!==i&&Object.keys(i).forEach(r=>{typeof i[r]=="object"&&i[r]!==null?((!e[r]||typeof e[r]!="object")&&(e[r]={}),d.mergeConfigs(e[r],i[r])):e[r]=i[r]})}static lerp(e,i,r){return e+(i-e)*r}_processState(){this.step=d._noop,this.progress=0,this.easeValue=0,this.elapsedTime=0,this.promise=null,this._resolve=d._noop,this._refreshDynamicProps()}_refreshDynamicProps(){this.applyProcessors(this.settings);let{target:e,time:i,repeat:r,loop:n,reversed:a,delay:p}=this.settings;this.target=e,this.time=Math.max(i,0),this.repeat=r>0?r:n?1/0:0,this.reversed=a,this.remainingDelay=p,this._processEasing()}_processEasing(){let e=typeof this.settings.easing=="string"?E[this.settings.easing]||E.linear:this.settings.easing;this._easing=this.reversed?this._reversedEasing:e;let i=typeof this.settings.mode=="string"?O[this.settings.mode]:this.settings.mode;this._calculateEasing=i?i.bind(this):this._easing}_update(){this.progress=this.elapsedTime/this.time,this.easeValue=this._calculateEasing(this.progress),this.emit(_.UPDATE,this)}_complete(){this.repeat-- >0?this._repeat():(this._resolve(),this.stop(!1),this.emit(_.COMPLETE))}_repeat(e=!0){this.remainingDelay=this.settings.repeatDelay,this.elapsedTime=0,this.remainingDelay>0&&(this.step=this._stepDelay),this._update(),e&&this.emit(_.REPEAT)}reset(e=this.constructor.DEFAULTS){return this.settings={...this.constructor.DEFAULTS,...e},this._processState(),this}applyProcessors(e=this.settings){e.processors.forEach(i=>{d.mergeConfigs(e,i.call(this,e)||{})})}tweak(e={}){return d.mergeConfigs(this.settings,e),this._refreshDynamicProps(),this}seek(e=0,i=!0){return this.elapsedTime=Math.min(Math.max(e,0),this.time),i&&this._update(),this}setProgress(e=0,i=!0){return this.seek(this.time*e,i)}reverse(e=!1){return this.reversed=!this.reversed,this.seek(this.time-this.elapsedTime,e),this._processEasing(),this}play(e=!0){return this.isPlaying?this:(this.settings.autoApplyProcessors&&this._refreshDynamicProps(),e&&this.emit(_.PLAY),this.remainingDelay>0?this.step=this._stepDelay:(this.step=this._stepTime,this.emit(_.BEGIN)),this.manager&&this.manager.addToActive(this),this)}playPromise(e=this.promise){return this.play(),this.promise=e||new Promise(i=>{this._resolve=i}),this.promise}stop(e=!0){return this._processState(),e&&this.emit(_.STOP),this.manager&&this.manager.removeFromActive(this),this}pause(){return this.step=d._noop,this.manager&&this.manager.removeFromActive(this),this}replay(e=!1){return this.stop(e),this.play(e),this}get isPlaying(){return this.step!==d._noop}remove(){this.stop(),this.manager.remove(this)}};y(d,"DEFAULTS",C);var u=d;var P=class extends u{_preparePropertySetters(){this.propertySetters=this.properties.map(s=>{let e=s.split("."),i=e.pop();return r=>{let n=this.target;for(let a=0;a<e.length;a++)n=n[e[a]];n[i]=r}})}_generatePath(){let s=this.settings.points,e=Math.max(this.settings.smoothing,1),i=[];this.totalLength=0;function r(n,a,p,o,l){let m=l*l,h=m*l;return n.map((I,c)=>.5*(2*a[c]+(-n[c]+p[c])*l+(2*n[c]-5*a[c]+4*p[c]-o[c])*m+(-n[c]+3*a[c]-3*p[c]+o[c])*h))}for(let n=0;n<s.length-1;n++){let a=s[n===0?n:n-1],p=s[n],o=s[n+1],l=s[n+2<s.length?n+2:n+1];for(let m=0;m<e;m++){let h=r(a,p,o,l,m/e);i.push(h),i.length>1&&(this.totalLength+=this._calculateDistance(i[i.length-2],h))}}return i.push(s[s.length-1]),i}_calculateDistance(s,e){return Math.sqrt(s.reduce((i,r,n)=>i+Math.pow(e[n]-s[n],2),0))}_refreshDynamicProps(){super._refreshDynamicProps(),this.path=this._generatePath(),!this.target||this.path.length===0?this._setTargetProperties=u._noop:(this._tryToSetupProperties(),this._preparePropertySetters())}_tryToSetupProperties(){if(this.settings.properties)this.properties=this.settings.properties;else if(this.path[0].length<=3){let s=[["position.x"],["position.x","position.y"],["position.x","position.y","position.z"]];this.properties=s[this.path[0].length-1]}else this.properties=[]}_setTargetProperties(s){for(let e=0;e<this.propertySetters.length;e++)this.propertySetters[e](s[e])}_clamp(s,e,i){return Math.max(e,Math.min(s,i))}_getInterpolatedPosition(){let s=this.path.length-1,e=this.easeValue*s,i=this._clamp(e,0,s),r=i>=s?s-1:Math.floor(i),n=Math.min(r+1,s),a=e-r,p=this.path[r],o=this.path[n];return p.map((l,m)=>u.lerp(l,o[m],a))}_update(){super._update(),this._setTargetProperties(this._getInterpolatedPosition())}};y(P,"DEFAULTS",{...u.DEFAULTS,properties:null,points:[],smoothing:20});var A=class extends u{_refreshDynamicProps(){super._refreshDynamicProps(),this._processFromTo()}_processFromTo(){this._lerps=[],this.target&&(this._setupStates(),this._createLerps())}_setupStates(){this._from=this.settings.from||this._createState(this.settings.to||{},this.target),this._to=this.settings.to||this._createState(this.settings.from||{},this.target)}_createState(s={},e={},i={}){let r=(n,a,p)=>{for(let o in n)typeof n[o]=="object"?(p[o]={},r(n[o],a[o],p[o])):p[o]=a[o]};return r(s,e,i),i}_createLerpStep(s,e,i,r){if(this.settings.dynamic)return()=>{s[r]=u.lerp(e[r],i[r],this.easeValue)};{let n=e[r],a=i[r]-n;return()=>{s[r]=n+a*this.easeValue}}}_createLerps(s=this.target,e=this._from,i=this._to){for(let r in i)typeof i[r]=="object"?this._createLerps(s[r],e[r],i[r]):this._lerps.push(this._createLerpStep(s,e,i,r))}_update(){super._update();for(let s of this._lerps)s()}from(s={}){return this.tweak({from:s}),this}to(s={}){return this.tweak({to:s}),this}swap(){return this.tweak({from:this.settings.to,to:this.settings.from}),this}};y(A,"DEFAULTS",{...u.DEFAULTS,dynamic:!1,from:null,to:null});function w(t){return t.target?t.creator?t.creator.prototype instanceof u?t.creator:(console.error("Invalid creator provided. Using default creator."),u):t.points?P:t.from||t.to?A:u:u}var S=class{constructor(){y(this,"update",s=>{this.activeAnimations.forEach(e=>{e.step(s)})});this.activeAnimations=new Map,this.allAnimations=new Map}create({on:s={},once:e={},...i}){let r=w(i),n=new r(i,this);return Object.keys(s).forEach(a=>{n.on(a,s[a])}),Object.keys(e).forEach(a=>{n.once(a,e[a])}),this.add(n),n}getActiveAnimations(){return Array.from(this.activeAnimations.values())}getAllAnimations(){return Array.from(this.allAnimations.values())}remove({index:s}={}){s&&(this.activeAnimations.delete(s),this.allAnimations.delete(s))}add(s){this.allAnimations.set(s.index,s)}addToActive(s){this.activeAnimations.set(s.index,s)}removeFromActive(s){this.activeAnimations.delete(s.index)}stopAll(){this.activeAnimations.forEach(s=>{s.stop()})}removeAll(){this.stopAll(),this.activeAnimations.clear(),this.allAnimations.clear()}};var W=new S;var M=class t{constructor(s,e={}){this.callback=s,this.options={maxDeltaTime:100,...e},this.isRunning=!1,this.lastTime=0,this.animationId=null}static start(s,e={}){let i=new t(s,e);return i.start(),i}start(){if(this.isRunning)return;this.isRunning=!0;let s=e=>{if(!this.isRunning)return;let i=Math.min(e-this.lastTime,this.options.maxDeltaTime);this.lastTime=e,this.callback(i),this.isRunning&&(this.animationId=requestAnimationFrame(s))};requestAnimationFrame(e=>{this.lastTime=e,s(e)})}stop(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}get running(){return this.isRunning}};function X(t,s){let e=new w(t),i=new e(t);return M.start(i.step.bind(i)),s?i.playPromise():i.play()}export{u as Core,P as Curve,C as DEFAULTS,_ as EVENTS,A as FromTo,W as GlobalManager,M as Loop,S as Manager,E as easings,O as modes,X as play};
|
package/package.json
CHANGED
package/types/Core.d.ts
CHANGED
|
@@ -1,48 +1,243 @@
|
|
|
1
1
|
import EventEmitter from 'eventemitter3';
|
|
2
|
-
import { CoreSettings } from './common';
|
|
2
|
+
import { CoreSettings, EasingFunction } from './common';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Core — base animation class built on EventEmitter3.
|
|
6
|
+
* Manages timing, easing, delays, repeats, and lifecycle events.
|
|
7
|
+
* Extended by FromTo (property interpolation) and Curve (spline animation).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const anim = new Core({ time: 1000, easing: 'outQuad', loop: true });
|
|
11
|
+
* anim.onUpdate((a) => console.log(a.progress, a.easeValue));
|
|
12
|
+
* anim.play();
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // With promise
|
|
16
|
+
* await anim.playPromise();
|
|
17
|
+
* console.log('animation complete');
|
|
18
|
+
*/
|
|
4
19
|
export class Core extends EventEmitter {
|
|
20
|
+
/** Default settings applied to every new instance. */
|
|
5
21
|
static DEFAULTS: CoreSettings;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Linear interpolation between two values.
|
|
25
|
+
* @param a - Start value
|
|
26
|
+
* @param b - End value
|
|
27
|
+
* @param t - Interpolation factor (0..1)
|
|
28
|
+
* @returns Interpolated value
|
|
29
|
+
*/
|
|
6
30
|
static lerp(a: number, b: number, t: number): number;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Deep-merge `source` into `target`, mutating `target` in place.
|
|
34
|
+
* Nested objects are merged recursively; primitives are overwritten.
|
|
35
|
+
*/
|
|
7
36
|
static mergeConfigs(target: object, source: object): void;
|
|
8
37
|
|
|
38
|
+
/** Unique numeric index assigned at construction. */
|
|
9
39
|
index: number;
|
|
40
|
+
|
|
41
|
+
/** Original overrides passed to the constructor. */
|
|
10
42
|
overrides: Partial<CoreSettings>;
|
|
43
|
+
|
|
44
|
+
/** Current resolved settings (defaults merged with overrides). */
|
|
11
45
|
settings: CoreSettings;
|
|
46
|
+
|
|
47
|
+
/** Current animation progress (0..1), before easing. */
|
|
12
48
|
progress: number;
|
|
49
|
+
|
|
50
|
+
/** Current eased value (0..1 for standard easings, can overshoot for elastic/back). */
|
|
13
51
|
easeValue: number;
|
|
52
|
+
|
|
53
|
+
/** Elapsed time in milliseconds since animation started. */
|
|
14
54
|
elapsedTime: number;
|
|
55
|
+
|
|
56
|
+
/** Reference to `settings.target`. */
|
|
15
57
|
target: any;
|
|
58
|
+
|
|
59
|
+
/** Resolved animation duration in milliseconds (≥ 0). */
|
|
16
60
|
time: number;
|
|
61
|
+
|
|
62
|
+
/** Remaining repetitions. */
|
|
17
63
|
repeat: number;
|
|
64
|
+
|
|
65
|
+
/** Whether the animation is currently playing in reverse. */
|
|
18
66
|
reversed: boolean;
|
|
67
|
+
|
|
68
|
+
/** Remaining delay before next step in milliseconds. */
|
|
19
69
|
remainingDelay: number;
|
|
70
|
+
|
|
71
|
+
/** Delta time from the most recent `step()` call. */
|
|
20
72
|
lastDeltaTime: number;
|
|
73
|
+
|
|
74
|
+
/** The Manager this animation belongs to, if any. */
|
|
21
75
|
manager?: import('./Manager').Manager;
|
|
22
76
|
|
|
77
|
+
/**
|
|
78
|
+
* @param overrides - Settings to merge on top of `Core.DEFAULTS`
|
|
79
|
+
* @param manager - Optional Manager instance to auto-register with
|
|
80
|
+
*/
|
|
23
81
|
constructor(overrides?: Partial<CoreSettings>, manager?: import('./Manager').Manager);
|
|
24
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Advance the animation by `deltaTime` milliseconds.
|
|
85
|
+
* Called by Manager or Loop each frame.
|
|
86
|
+
* Internally delegates to delay/time step based on current state.
|
|
87
|
+
*/
|
|
25
88
|
step(deltaTime: number): void;
|
|
26
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Subscribe to an event. Returns `this` for chaining.
|
|
92
|
+
* @param event - Event name: `'play'` | `'stop'` | `'begin'` | `'update'` | `'repeat'` | `'complete'`
|
|
93
|
+
* @param fn - Callback
|
|
94
|
+
* @param context - Optional `this` context for the callback
|
|
95
|
+
*/
|
|
27
96
|
on(event: string, fn: (...args: any[]) => void, context?: any): this;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Unsubscribe from an event. Returns `this` for chaining.
|
|
100
|
+
* @param event - Event name
|
|
101
|
+
* @param fn - The exact function reference that was passed to `.on()`
|
|
102
|
+
* @param context - The context that was passed to `.on()`
|
|
103
|
+
*/
|
|
28
104
|
off(event: string, fn: (...args: any[]) => void, context?: any): this;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Subscribe to an event, auto-removed after first fire. Returns `this` for chaining.
|
|
108
|
+
* @param event - Event name
|
|
109
|
+
* @param fn - Callback
|
|
110
|
+
* @param context - Optional `this` context for the callback
|
|
111
|
+
*/
|
|
29
112
|
once(event: string, fn: (...args: any[]) => void, context?: any): this;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Shorthand for `.on('complete', fn)`. Returns `this` for chaining.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* animation.onComplete(() => console.log('done')).play();
|
|
119
|
+
*/
|
|
30
120
|
onComplete(fn: (animation: this) => void, context?: any): this;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Shorthand for `.on('update', fn)`. Returns `this` for chaining.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* animation.onUpdate((a) => {
|
|
127
|
+
* console.log(a.progress, a.easeValue);
|
|
128
|
+
* });
|
|
129
|
+
*/
|
|
31
130
|
onUpdate(fn: (animation: this) => void, context?: any): this;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Shorthand for `.once('complete', fn)`. Returns `this` for chaining.
|
|
134
|
+
* Callback fires once on the next complete, then is removed.
|
|
135
|
+
*/
|
|
32
136
|
onceComplete(fn: (animation: this) => void, context?: any): this;
|
|
33
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Reset the animation to its initial state.
|
|
140
|
+
* Merges `newSettings` (or DEFAULTS) and re-initializes all internal state.
|
|
141
|
+
* @param newSettings - New settings to apply (defaults to `DEFAULTS`)
|
|
142
|
+
* @returns `this` for chaining
|
|
143
|
+
*/
|
|
34
144
|
reset(newSettings?: Partial<CoreSettings>): this;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Manually apply all processor functions to the current settings.
|
|
148
|
+
* Called automatically if `autoApplyProcessors` is `false`.
|
|
149
|
+
*/
|
|
35
150
|
applyProcessors(settings?: CoreSettings): void;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Modify settings on a live animation without resetting progress.
|
|
154
|
+
* Deep-merges `newSettings` into current `settings` and refreshes dynamic props.
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* animation.tweak({ time: 500, easing: 'inOutCubic' });
|
|
158
|
+
*
|
|
159
|
+
* @returns `this` for chaining
|
|
160
|
+
*/
|
|
36
161
|
tweak(newSettings?: Partial<CoreSettings>): this;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Jump to a specific time in the animation.
|
|
165
|
+
* @param time - Target time in milliseconds, clamped to [0, this.time]
|
|
166
|
+
* @param callUpdate - Whether to fire the UPDATE event (default: `true`)
|
|
167
|
+
* @returns `this` for chaining
|
|
168
|
+
*/
|
|
37
169
|
seek(time?: number, callUpdate?: boolean): this;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Jump to a specific progress value.
|
|
173
|
+
* @param progress - Target progress (0..1)
|
|
174
|
+
* @param callUpdate - Whether to fire the UPDATE event (default: `true`)
|
|
175
|
+
* @returns `this` for chaining
|
|
176
|
+
*/
|
|
38
177
|
setProgress(progress?: number, callUpdate?: boolean): this;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Toggle animation direction. Flips `reversed` and adjusts `elapsedTime`
|
|
181
|
+
* so the animation continues from the mirrored position.
|
|
182
|
+
* @param callUpdate - Whether to fire the UPDATE event (default: `false`)
|
|
183
|
+
* @returns `this` for chaining
|
|
184
|
+
*/
|
|
39
185
|
reverse(callUpdate?: boolean): this;
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Start the animation.
|
|
189
|
+
* If a delay is set, transitions to delay state first (PLAY fires immediately, BEGIN fires after delay).
|
|
190
|
+
* No-op if already playing.
|
|
191
|
+
* @param withEvent - Whether to emit the PLAY event (default: `true`)
|
|
192
|
+
* @returns `this` for chaining
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* animation.play();
|
|
196
|
+
*/
|
|
40
197
|
play(withEvent?: boolean): this;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Start the animation and return a Promise that resolves on complete.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* await animation.playPromise();
|
|
204
|
+
* // animation finished
|
|
205
|
+
*
|
|
206
|
+
* @param promise - Optional existing promise to reuse
|
|
207
|
+
* @returns Promise that resolves when the animation completes
|
|
208
|
+
*/
|
|
41
209
|
playPromise(promise?: Promise<void>): Promise<void>;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Stop the animation, reset internal state (`progress`, `elapsedTime`, etc.).
|
|
213
|
+
* Removes from Manager's active list.
|
|
214
|
+
* @param withEvent - Whether to emit the STOP event (default: `true`)
|
|
215
|
+
* @returns `this` for chaining
|
|
216
|
+
*/
|
|
42
217
|
stop(withEvent?: boolean): this;
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Pause the animation at its current position.
|
|
221
|
+
* Call `.play()` to resume from the paused point.
|
|
222
|
+
* @returns `this` for chaining
|
|
223
|
+
*/
|
|
43
224
|
pause(): this;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Stop and immediately play again from the beginning.
|
|
228
|
+
* @param withEvent - Whether to emit STOP/PLAY events (default: `false`)
|
|
229
|
+
* @returns `this` for chaining
|
|
230
|
+
*/
|
|
44
231
|
replay(withEvent?: boolean): this;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Remove this animation from its Manager (both active and all lists).
|
|
235
|
+
* Calls `.stop()` first.
|
|
236
|
+
*/
|
|
45
237
|
remove(): void;
|
|
46
238
|
|
|
239
|
+
/**
|
|
240
|
+
* `true` if the animation is currently advancing (not paused/stopped).
|
|
241
|
+
*/
|
|
47
242
|
get isPlaying(): boolean;
|
|
48
243
|
}
|
package/types/Curve.d.ts
CHANGED
|
@@ -1,13 +1,61 @@
|
|
|
1
1
|
import { Core } from './Core';
|
|
2
2
|
import { CurveSettings } from './common';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Curve — animates target properties along a Catmull-Rom spline defined by keypoints.
|
|
6
|
+
*
|
|
7
|
+
* Auto-detects property mapping for 1D–3D points (`position.x`, `.y`, `.z`).
|
|
8
|
+
* For higher dimensions or custom paths, provide `properties` explicitly.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // 3D path — properties auto-detected as position.x/y/z
|
|
12
|
+
* const anim = new Curve({
|
|
13
|
+
* target: mesh,
|
|
14
|
+
* time: 2000,
|
|
15
|
+
* points: [
|
|
16
|
+
* [0, 0, 0],
|
|
17
|
+
* [5, 10, 0],
|
|
18
|
+
* [10, 0, 5],
|
|
19
|
+
* [0, 0, 0],
|
|
20
|
+
* ],
|
|
21
|
+
* easing: 'inOutSine',
|
|
22
|
+
* loop: true,
|
|
23
|
+
* });
|
|
24
|
+
* anim.play();
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* // Custom properties — 6D points controlling position + scale
|
|
28
|
+
* const anim = new Curve({
|
|
29
|
+
* target: mesh,
|
|
30
|
+
* time: 3000,
|
|
31
|
+
* properties: ['position.x', 'position.y', 'position.z', 'scale.x', 'scale.y', 'scale.z'],
|
|
32
|
+
* points: [
|
|
33
|
+
* [0, 0, 0, 1, 1, 1],
|
|
34
|
+
* [5, 10, 0, 2, 0.5, 2],
|
|
35
|
+
* [0, 0, 0, 1, 1, 1],
|
|
36
|
+
* ],
|
|
37
|
+
* smoothing: 30,
|
|
38
|
+
* });
|
|
39
|
+
*/
|
|
4
40
|
export class Curve extends Core {
|
|
41
|
+
/** Default settings for Curve, extending Core.DEFAULTS with `points`, `properties`, `smoothing`. */
|
|
5
42
|
static DEFAULTS: CurveSettings;
|
|
6
43
|
|
|
44
|
+
/** Current resolved settings. */
|
|
7
45
|
settings: CurveSettings;
|
|
46
|
+
|
|
47
|
+
/** Generated spline path — array of interpolated points. */
|
|
8
48
|
path: number[][];
|
|
49
|
+
|
|
50
|
+
/** Total arc length of the generated path. */
|
|
9
51
|
totalLength: number;
|
|
52
|
+
|
|
53
|
+
/** Resolved property paths assigned from interpolated values each frame. */
|
|
10
54
|
properties: string[];
|
|
11
55
|
|
|
56
|
+
/**
|
|
57
|
+
* @param overrides - Settings to merge on top of `Curve.DEFAULTS`
|
|
58
|
+
* @param manager - Optional Manager instance to auto-register with
|
|
59
|
+
*/
|
|
12
60
|
constructor(overrides?: Partial<CurveSettings>, manager?: import('./Manager').Manager);
|
|
13
61
|
}
|
package/types/FromTo.d.ts
CHANGED
|
@@ -1,14 +1,87 @@
|
|
|
1
1
|
import { Core } from './Core';
|
|
2
2
|
import { FromToSettings } from './common';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* FromTo — animates target properties by interpolating between `from` and `to` values.
|
|
6
|
+
* Automatically detects numeric properties (including nested objects) and creates lerps.
|
|
7
|
+
*
|
|
8
|
+
* If only `from` is provided, current target values are used as `to` (and vice versa).
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const anim = new FromTo({
|
|
12
|
+
* target: mesh.position,
|
|
13
|
+
* from: { x: 0, y: 0 },
|
|
14
|
+
* to: { x: 100, y: 200 },
|
|
15
|
+
* time: 1000,
|
|
16
|
+
* easing: 'outQuad',
|
|
17
|
+
* });
|
|
18
|
+
* anim.play();
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Nested properties
|
|
22
|
+
* const anim = new FromTo({
|
|
23
|
+
* target: mesh,
|
|
24
|
+
* from: { position: { x: 0 }, scale: { x: 1 } },
|
|
25
|
+
* to: { position: { x: 10 }, scale: { x: 2 } },
|
|
26
|
+
* time: 500,
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* // Dynamic mode — from/to are re-read each frame
|
|
31
|
+
* const anim = new FromTo({
|
|
32
|
+
* target: obj,
|
|
33
|
+
* from: startValues,
|
|
34
|
+
* to: endValues,
|
|
35
|
+
* dynamic: true,
|
|
36
|
+
* time: 1000,
|
|
37
|
+
* });
|
|
38
|
+
* // Changing startValues/endValues during animation takes effect immediately
|
|
39
|
+
*/
|
|
4
40
|
export class FromTo extends Core {
|
|
41
|
+
/** Default settings for FromTo, extending Core.DEFAULTS with `from`, `to`, `dynamic`. */
|
|
5
42
|
static DEFAULTS: FromToSettings;
|
|
6
43
|
|
|
44
|
+
/** Current resolved settings. */
|
|
7
45
|
settings: FromToSettings;
|
|
8
46
|
|
|
47
|
+
/**
|
|
48
|
+
* @param overrides - Settings to merge on top of `FromTo.DEFAULTS`
|
|
49
|
+
* @param manager - Optional Manager instance to auto-register with
|
|
50
|
+
*/
|
|
9
51
|
constructor(overrides?: Partial<FromToSettings>, manager?: import('./Manager').Manager);
|
|
10
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Update `from` values on a live animation.
|
|
55
|
+
* Calls `.tweak()` internally and rebuilds interpolation.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* animation.from({ x: 50 }).play();
|
|
59
|
+
*
|
|
60
|
+
* @param from - New starting values
|
|
61
|
+
* @returns `this` for chaining
|
|
62
|
+
*/
|
|
11
63
|
from(from?: Record<string, any>): this;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Update `to` values on a live animation.
|
|
67
|
+
* Calls `.tweak()` internally and rebuilds interpolation.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* animation.to({ x: 200 }).play();
|
|
71
|
+
*
|
|
72
|
+
* @param to - New ending values
|
|
73
|
+
* @returns `this` for chaining
|
|
74
|
+
*/
|
|
12
75
|
to(to?: Record<string, any>): this;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Swap `from` and `to` values, effectively reversing the interpolation direction.
|
|
79
|
+
* Unlike `.reverse()`, this swaps the actual values rather than inverting the easing.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* animation.swap().replay();
|
|
83
|
+
*
|
|
84
|
+
* @returns `this` for chaining
|
|
85
|
+
*/
|
|
13
86
|
swap(): this;
|
|
14
87
|
}
|
package/types/Loop.d.ts
CHANGED
|
@@ -1,18 +1,65 @@
|
|
|
1
1
|
import { LoopOptions } from './common';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Loop — requestAnimationFrame wrapper with delta-time capping.
|
|
5
|
+
* Calls the provided callback every frame with `dt` in milliseconds.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // Static shorthand — create and start in one call
|
|
9
|
+
* const loop = Loop.start((dt) => {
|
|
10
|
+
* manager.update(dt);
|
|
11
|
+
* });
|
|
12
|
+
*
|
|
13
|
+
* // Stop later
|
|
14
|
+
* loop.stop();
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Manual lifecycle
|
|
18
|
+
* const loop = new Loop((dt) => console.log(dt), { maxDeltaTime: 50 });
|
|
19
|
+
* loop.start();
|
|
20
|
+
* // ...
|
|
21
|
+
* loop.stop();
|
|
22
|
+
*/
|
|
3
23
|
export class Loop {
|
|
24
|
+
/** The callback invoked each frame with `dt` (capped by `maxDeltaTime`). */
|
|
4
25
|
callback: (dt: number) => void;
|
|
26
|
+
|
|
27
|
+
/** Resolved options with defaults applied. */
|
|
5
28
|
options: Required<LoopOptions>;
|
|
29
|
+
|
|
30
|
+
/** Whether the loop is currently running. */
|
|
6
31
|
isRunning: boolean;
|
|
32
|
+
|
|
33
|
+
/** Timestamp of the previous frame (from `requestAnimationFrame`). */
|
|
7
34
|
lastTime: number;
|
|
35
|
+
|
|
36
|
+
/** Current `requestAnimationFrame` handle, or `null` if stopped. */
|
|
8
37
|
animationId: number | null;
|
|
9
38
|
|
|
39
|
+
/**
|
|
40
|
+
* @param callback - Function called every frame with delta time in ms
|
|
41
|
+
* @param options - Loop options
|
|
42
|
+
*/
|
|
10
43
|
constructor(callback: (dt: number) => void, options?: LoopOptions);
|
|
11
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Create a Loop and immediately start it.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* const loop = Loop.start(manager.update);
|
|
50
|
+
*
|
|
51
|
+
* @param callback - Function called every frame with delta time in ms
|
|
52
|
+
* @param options - Loop options
|
|
53
|
+
* @returns The running Loop instance
|
|
54
|
+
*/
|
|
12
55
|
static start(callback: (dt: number) => void, options?: LoopOptions): Loop;
|
|
13
56
|
|
|
57
|
+
/** Start the loop. No-op if already running. */
|
|
14
58
|
start(): void;
|
|
59
|
+
|
|
60
|
+
/** Stop the loop and cancel the next animation frame. */
|
|
15
61
|
stop(): void;
|
|
16
62
|
|
|
63
|
+
/** Alias for `isRunning`. */
|
|
17
64
|
get running(): boolean;
|
|
18
65
|
}
|
package/types/Manager.d.ts
CHANGED
|
@@ -1,20 +1,121 @@
|
|
|
1
1
|
import { Core } from './Core';
|
|
2
2
|
import { ManagerCreateConfig } from './common';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Manager — creates, stores, and batch-updates animations.
|
|
6
|
+
* Animations created via `.create()` are automatically registered in the Manager.
|
|
7
|
+
* Call `.update(dt)` each frame (typically from a Loop) to advance all active animations.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const manager = new Manager();
|
|
11
|
+
*
|
|
12
|
+
* const anim = manager.create({
|
|
13
|
+
* target: mesh.position,
|
|
14
|
+
* from: { x: 0 },
|
|
15
|
+
* to: { x: 100 },
|
|
16
|
+
* time: 1000,
|
|
17
|
+
* on: { complete: () => console.log('done') },
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* anim.play();
|
|
21
|
+
* Loop.start(manager.update);
|
|
22
|
+
*/
|
|
4
23
|
export class Manager {
|
|
24
|
+
/** Map of currently playing animations (index → animation). */
|
|
5
25
|
activeAnimations: Map<number, Core>;
|
|
26
|
+
|
|
27
|
+
/** Map of all registered animations, active or not (index → animation). */
|
|
6
28
|
allAnimations: Map<number, Core>;
|
|
7
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Create a new animation, auto-detecting the type (Core, FromTo, or Curve).
|
|
32
|
+
* The animation is registered in the Manager but not started — call `.play()`.
|
|
33
|
+
*
|
|
34
|
+
* Type detection:
|
|
35
|
+
* - `config.points` → Curve
|
|
36
|
+
* - `config.from` or `config.to` → FromTo
|
|
37
|
+
* - otherwise → Core
|
|
38
|
+
* - `config.creator` → custom class (must extend Core)
|
|
39
|
+
*
|
|
40
|
+
* Event binding shortcuts:
|
|
41
|
+
* - `config.on` — persistent listeners (`.on()`)
|
|
42
|
+
* - `config.once` — one-time listeners (`.once()`)
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* const anim = manager.create({
|
|
46
|
+
* target: obj,
|
|
47
|
+
* to: { x: 10 },
|
|
48
|
+
* time: 500,
|
|
49
|
+
* easing: 'outQuad',
|
|
50
|
+
* on: { update: (a) => render(a.target) },
|
|
51
|
+
* });
|
|
52
|
+
* anim.play();
|
|
53
|
+
*/
|
|
8
54
|
create(config: ManagerCreateConfig): Core;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Advance all active animations by `dt` milliseconds.
|
|
58
|
+
* Bound to the instance — safe to pass directly to `Loop.start()`.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* Loop.start(manager.update);
|
|
62
|
+
*/
|
|
9
63
|
update(dt: number): void;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get a snapshot array of all currently playing animations.
|
|
67
|
+
*/
|
|
10
68
|
getActiveAnimations(): Core[];
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get a snapshot array of all registered animations (active + inactive).
|
|
72
|
+
*/
|
|
11
73
|
getAllAnimations(): Core[];
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Remove an animation from both active and all lists by its index.
|
|
77
|
+
* @param animation - Object with an `index` property
|
|
78
|
+
*/
|
|
12
79
|
remove(animation: { index?: number }): void;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Register an animation in the `allAnimations` map.
|
|
83
|
+
* Called automatically by `.create()`.
|
|
84
|
+
*/
|
|
13
85
|
add(animation: Core): void;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Move an animation to the active list (it will receive `.update()` calls).
|
|
89
|
+
* Called automatically by `animation.play()` when a Manager is attached.
|
|
90
|
+
*/
|
|
14
91
|
addToActive(animation: Core): void;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Remove an animation from the active list (stops receiving updates).
|
|
95
|
+
* Called automatically by `animation.stop()` / `.pause()`.
|
|
96
|
+
*/
|
|
15
97
|
removeFromActive(animation: Core): void;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Stop all active animations (calls `.stop()` on each).
|
|
101
|
+
*/
|
|
16
102
|
stopAll(): void;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Stop all animations and clear both active and all lists.
|
|
106
|
+
*/
|
|
17
107
|
removeAll(): void;
|
|
18
108
|
}
|
|
19
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Pre-created global Manager singleton.
|
|
112
|
+
* Convenient when you don't need multiple independent animation groups.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* import { GlobalManager, Loop } from 'qarl';
|
|
116
|
+
*
|
|
117
|
+
* const anim = GlobalManager.create({ target: obj, to: { x: 10 }, time: 500 });
|
|
118
|
+
* anim.play();
|
|
119
|
+
* Loop.start(GlobalManager.update);
|
|
120
|
+
*/
|
|
20
121
|
export const GlobalManager: Manager;
|
package/types/common.d.ts
CHANGED
|
@@ -1,53 +1,261 @@
|
|
|
1
1
|
import { Core } from './Core';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Easing function that maps progress `t` (0..1) to an output value.
|
|
5
|
+
* Can accept additional parameters for parametric easings (e.g. `inBack(t, overshoot)`).
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const customEasing: EasingFunction = (t) => t * t;
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const parametric: EasingFunction = (t, strength = 1.5) => t * strength;
|
|
12
|
+
*/
|
|
3
13
|
export type EasingFunction = (t: number, ...args: number[]) => number;
|
|
4
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Mode function that wraps an easing to create composite effects (ping-pong, yoyo, etc.).
|
|
17
|
+
* Called with `this` bound to the Core instance, giving access to `this._easing`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* const customMode: ModeFunction = function(t) {
|
|
21
|
+
* return t <= 0.5
|
|
22
|
+
* ? this._easing(t * 2)
|
|
23
|
+
* : 1 - this._easing((t - 0.5) * 2);
|
|
24
|
+
* };
|
|
25
|
+
*/
|
|
5
26
|
export type ModeFunction = (this: Core, t: number) => number;
|
|
6
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Processor function — middleware that can modify animation settings before each play.
|
|
30
|
+
* Called with `this` bound to the Core instance.
|
|
31
|
+
* Return a partial settings object to merge, or void to modify `settings` in place.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* const randomDelay: ProcessorFunction = function(settings) {
|
|
35
|
+
* return { delay: Math.random() * 1000 };
|
|
36
|
+
* };
|
|
37
|
+
*/
|
|
7
38
|
export type ProcessorFunction = (this: Core, settings: CoreSettings) => Partial<CoreSettings> | void;
|
|
8
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Base configuration for all animations.
|
|
42
|
+
*/
|
|
9
43
|
export interface CoreSettings {
|
|
44
|
+
/**
|
|
45
|
+
* Array of processor functions applied before each play.
|
|
46
|
+
* Processors can dynamically modify settings (e.g. randomize delay, compute values).
|
|
47
|
+
* @default []
|
|
48
|
+
*/
|
|
10
49
|
processors: ProcessorFunction[];
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Duration of the animation in milliseconds.
|
|
53
|
+
* @default 0
|
|
54
|
+
*/
|
|
11
55
|
time: number;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* If `true`, the animation repeats indefinitely.
|
|
59
|
+
* Overrides `repeat` — sets it to `Infinity`.
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
12
62
|
loop: boolean;
|
|
13
|
-
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Animation mode that wraps the easing function.
|
|
66
|
+
* Pass a built-in name (`'pingPong'`, `'yoyo'`, `'bounce'`) or a custom `ModeFunction`.
|
|
67
|
+
* @default null
|
|
68
|
+
*/
|
|
69
|
+
mode: ModeName | ModeFunction | null;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Delay before the animation starts, in milliseconds.
|
|
73
|
+
* The `BEGIN` event fires after the delay; `PLAY` fires immediately.
|
|
74
|
+
* @default 0
|
|
75
|
+
*/
|
|
14
76
|
delay: number;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Number of times to repeat after the first play.
|
|
80
|
+
* `0` = play once, `1` = play twice, etc. Ignored if `loop` is `true`.
|
|
81
|
+
* @default 0
|
|
82
|
+
*/
|
|
15
83
|
repeat: number;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The object whose properties will be animated.
|
|
87
|
+
* For FromTo/Curve — the object receiving interpolated values.
|
|
88
|
+
* For bare Core — available via `this.target` in event handlers.
|
|
89
|
+
* @default null
|
|
90
|
+
*/
|
|
16
91
|
target: any;
|
|
17
|
-
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Easing function or a built-in easing name.
|
|
95
|
+
* Controls the animation curve (acceleration/deceleration).
|
|
96
|
+
*
|
|
97
|
+
* Built-in names: `'linear'`, `'inQuad'`, `'outQuad'`, `'inOutQuad'`,
|
|
98
|
+
* `'inCubic'`, `'outCubic'`, `'inOutCubic'`, `'inElastic'`, `'outElastic'`, etc.
|
|
99
|
+
*
|
|
100
|
+
* @default (t) => t // linear
|
|
101
|
+
*/
|
|
102
|
+
easing: EasingName | EasingFunction;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* If `true`, the easing is applied in reverse direction.
|
|
106
|
+
* @default false
|
|
107
|
+
*/
|
|
18
108
|
reversed: boolean;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Delay between repetitions in milliseconds.
|
|
112
|
+
* Only relevant when `repeat > 0` or `loop` is `true`.
|
|
113
|
+
* @default 0
|
|
114
|
+
*/
|
|
19
115
|
repeatDelay: number;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* If `true`, processors are re-applied automatically before each `play()`.
|
|
119
|
+
* If `false`, processors are only applied on `reset()`.
|
|
120
|
+
* @default true
|
|
121
|
+
*/
|
|
20
122
|
autoApplyProcessors: boolean;
|
|
21
123
|
}
|
|
22
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Configuration for FromTo animations.
|
|
127
|
+
* Extends CoreSettings with `from`/`to` value objects.
|
|
128
|
+
*/
|
|
23
129
|
export interface FromToSettings extends CoreSettings {
|
|
130
|
+
/**
|
|
131
|
+
* If `true`, `from` and `to` are re-read each frame, allowing external changes.
|
|
132
|
+
* If `false`, deltas are precomputed once for better performance.
|
|
133
|
+
* @default false
|
|
134
|
+
*/
|
|
24
135
|
dynamic: boolean;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Starting values. Shape must mirror the `target` object's structure.
|
|
139
|
+
* If omitted, current values of `target` matching `to` keys are used.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* { position: { x: 0, y: 0 }, scale: { x: 1 } }
|
|
143
|
+
* @default null
|
|
144
|
+
*/
|
|
25
145
|
from: Record<string, any> | null;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Ending values. Shape must mirror the `target` object's structure.
|
|
149
|
+
* If omitted, current values of `target` matching `from` keys are used.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* { position: { x: 100, y: 200 }, scale: { x: 2 } }
|
|
153
|
+
* @default null
|
|
154
|
+
*/
|
|
26
155
|
to: Record<string, any> | null;
|
|
27
156
|
}
|
|
28
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Configuration for Curve (Catmull-Rom spline) animations.
|
|
160
|
+
* Extends CoreSettings with keypoint arrays.
|
|
161
|
+
*/
|
|
29
162
|
export interface CurveSettings extends CoreSettings {
|
|
163
|
+
/**
|
|
164
|
+
* Property paths on `target` to assign interpolated values.
|
|
165
|
+
* Each string is a dot-separated path (e.g. `'position.x'`).
|
|
166
|
+
* If omitted and points have 1–3 dimensions, defaults to `position.x`, `.y`, `.z`.
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ['position.x', 'position.y', 'rotation.z']
|
|
170
|
+
* @default null
|
|
171
|
+
*/
|
|
30
172
|
properties: string[] | null;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Array of keypoints for the spline. Each point is a number array
|
|
176
|
+
* whose length must match `properties.length`.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* [[0, 0, 0], [5, 10, 0], [10, 0, 0]]
|
|
180
|
+
* @default []
|
|
181
|
+
*/
|
|
31
182
|
points: number[][];
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Number of interpolation steps between each pair of keypoints.
|
|
186
|
+
* Higher values produce smoother curves at the cost of memory.
|
|
187
|
+
* @default 20
|
|
188
|
+
*/
|
|
32
189
|
smoothing: number;
|
|
33
190
|
}
|
|
34
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Options for the animation loop.
|
|
194
|
+
*/
|
|
35
195
|
export interface LoopOptions {
|
|
196
|
+
/**
|
|
197
|
+
* Maximum allowed delta time per frame in milliseconds.
|
|
198
|
+
* Prevents large jumps when the tab is backgrounded.
|
|
199
|
+
* @default 100
|
|
200
|
+
*/
|
|
36
201
|
maxDeltaTime?: number;
|
|
37
202
|
}
|
|
38
203
|
|
|
204
|
+
/**
|
|
205
|
+
* Configuration for `Manager.create()`.
|
|
206
|
+
* Combines CoreSettings with FromTo/Curve fields and event binding shortcuts.
|
|
207
|
+
* The correct animation type (Core, FromTo, or Curve) is auto-detected.
|
|
208
|
+
*/
|
|
39
209
|
export interface ManagerCreateConfig extends Partial<CoreSettings> {
|
|
210
|
+
/**
|
|
211
|
+
* Event listeners attached via `.on()` (persistent).
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* { update: (anim) => console.log(anim.progress) }
|
|
215
|
+
*/
|
|
40
216
|
on?: Record<string, (...args: any[]) => void>;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Event listeners attached via `.once()` (fire once, then removed).
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* { complete: () => console.log('done') }
|
|
223
|
+
*/
|
|
41
224
|
once?: Record<string, (...args: any[]) => void>;
|
|
225
|
+
|
|
226
|
+
/** Starting values (triggers FromTo animation). */
|
|
42
227
|
from?: Record<string, any>;
|
|
228
|
+
|
|
229
|
+
/** Ending values (triggers FromTo animation). */
|
|
43
230
|
to?: Record<string, any>;
|
|
231
|
+
|
|
232
|
+
/** Keypoints (triggers Curve animation). */
|
|
44
233
|
points?: number[][];
|
|
234
|
+
|
|
235
|
+
/** Property paths for Curve animation. */
|
|
45
236
|
properties?: string[];
|
|
237
|
+
|
|
238
|
+
/** Smoothing for Curve animation. */
|
|
46
239
|
smoothing?: number;
|
|
240
|
+
|
|
241
|
+
/** Dynamic mode for FromTo animation. */
|
|
47
242
|
dynamic?: boolean;
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Custom animation class to use instead of auto-detection.
|
|
246
|
+
* Must be a subclass of Core (e.g. a custom controller).
|
|
247
|
+
*/
|
|
48
248
|
creator?: typeof Core;
|
|
49
249
|
}
|
|
50
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Built-in easing function names.
|
|
253
|
+
*
|
|
254
|
+
* Families: Quad, Cubic, Quart, Quint, Sine, Back, Expo, Elastic.
|
|
255
|
+
* Each family has `in`, `out`, and `inOut` variants.
|
|
256
|
+
*
|
|
257
|
+
* Special: `'linear'` (no easing), `'reverse'` (1 − t), `'yoyo'` (triangle wave).
|
|
258
|
+
*/
|
|
51
259
|
export type EasingName =
|
|
52
260
|
| 'linear' | 'reverse' | 'yoyo'
|
|
53
261
|
| 'inQuad' | 'outQuad' | 'inOutQuad'
|
|
@@ -59,13 +267,29 @@ export type EasingName =
|
|
|
59
267
|
| 'inExpo' | 'outExpo' | 'inOutExpo'
|
|
60
268
|
| 'inElastic' | 'outElastic' | 'inOutElastic';
|
|
61
269
|
|
|
270
|
+
/**
|
|
271
|
+
* Built-in animation mode names.
|
|
272
|
+
*
|
|
273
|
+
* - `'pingPong'` — forward then backward using the easing.
|
|
274
|
+
* - `'yoyo'` — easing applied to a triangle wave.
|
|
275
|
+
* - `'bounce'` — triangle wave applied after easing.
|
|
276
|
+
*/
|
|
62
277
|
export type ModeName = 'pingPong' | 'yoyo' | 'bounce';
|
|
63
278
|
|
|
279
|
+
/**
|
|
280
|
+
* Event name constants used with `.on()` / `.once()` / `.emit()`.
|
|
281
|
+
*/
|
|
64
282
|
export interface EventTypes {
|
|
283
|
+
/** Fires when `.play()` is called (before delay). */
|
|
65
284
|
PLAY: 'play';
|
|
285
|
+
/** Fires when `.stop()` is called. */
|
|
66
286
|
STOP: 'stop';
|
|
287
|
+
/** Fires when the animation actually begins (after delay). */
|
|
67
288
|
BEGIN: 'begin';
|
|
289
|
+
/** Fires every frame with updated `progress` and `easeValue`. */
|
|
68
290
|
UPDATE: 'update';
|
|
291
|
+
/** Fires on each repetition. */
|
|
69
292
|
REPEAT: 'repeat';
|
|
293
|
+
/** Fires when all repetitions are done. */
|
|
70
294
|
COMPLETE: 'complete';
|
|
71
295
|
}
|
package/types/defaults.d.ts
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
1
|
import { CoreSettings } from './common';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Default animation settings applied to every Core instance.
|
|
5
|
+
*
|
|
6
|
+
* ```
|
|
7
|
+
* {
|
|
8
|
+
* processors: [],
|
|
9
|
+
* time: 0,
|
|
10
|
+
* loop: false,
|
|
11
|
+
* mode: null,
|
|
12
|
+
* delay: 0,
|
|
13
|
+
* repeat: 0,
|
|
14
|
+
* target: null,
|
|
15
|
+
* easing: (t) => t, // linear
|
|
16
|
+
* reversed: false,
|
|
17
|
+
* repeatDelay: 0,
|
|
18
|
+
* autoApplyProcessors: false,
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
3
22
|
export const DEFAULTS: CoreSettings;
|
package/types/easings.d.ts
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
1
|
import { EasingFunction, EasingName } from './common';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Built-in easing functions.
|
|
5
|
+
* Each function maps progress `t` (0..1) to an eased output.
|
|
6
|
+
*
|
|
7
|
+
* | Family | In | Out | InOut |
|
|
8
|
+
* |----------|-------------|--------------|----------------|
|
|
9
|
+
* | Quad | `inQuad` | `outQuad` | `inOutQuad` |
|
|
10
|
+
* | Cubic | `inCubic` | `outCubic` | `inOutCubic` |
|
|
11
|
+
* | Quart | `inQuart` | `outQuart` | `inOutQuart` |
|
|
12
|
+
* | Quint | `inQuint` | `outQuint` | `inOutQuint` |
|
|
13
|
+
* | Sine | `inSine` | `outSine` | `inOutSine` |
|
|
14
|
+
* | Back | `inBack` | `outBack` | `inOutBack` |
|
|
15
|
+
* | Expo | `inExpo` | `outExpo` | `inOutExpo` |
|
|
16
|
+
* | Elastic | `inElastic` | `outElastic` | `inOutElastic` |
|
|
17
|
+
*
|
|
18
|
+
* Special:
|
|
19
|
+
* - `linear` — no easing (`t → t`)
|
|
20
|
+
* - `reverse` — inverted (`t → 1 − t`)
|
|
21
|
+
* - `yoyo` — triangle wave (`0 → 1 → 0`)
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* import { easings } from 'qarl';
|
|
25
|
+
*
|
|
26
|
+
* // Use as a function directly
|
|
27
|
+
* const value = easings.outElastic(0.5);
|
|
28
|
+
*
|
|
29
|
+
* // Pass by name in config
|
|
30
|
+
* { easing: 'outElastic' }
|
|
31
|
+
*
|
|
32
|
+
* // Or pass the function reference
|
|
33
|
+
* { easing: easings.outElastic }
|
|
34
|
+
*/
|
|
3
35
|
export const easings: Record<EasingName, EasingFunction>;
|
package/types/events.d.ts
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
1
|
import { EventTypes } from './common';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Animation lifecycle event name constants.
|
|
5
|
+
*
|
|
6
|
+
* | Constant | Value | When it fires |
|
|
7
|
+
* |------------|--------------|----------------------------------------------|
|
|
8
|
+
* | `PLAY` | `'play'` | `.play()` called (before delay) |
|
|
9
|
+
* | `STOP` | `'stop'` | `.stop()` called |
|
|
10
|
+
* | `BEGIN` | `'begin'` | Animation actually starts (after delay) |
|
|
11
|
+
* | `UPDATE` | `'update'` | Every frame, after progress/easing computed |
|
|
12
|
+
* | `REPEAT` | `'repeat'` | Each repetition starts |
|
|
13
|
+
* | `COMPLETE` | `'complete'` | All repetitions finished |
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* import { EVENTS } from 'qarl';
|
|
17
|
+
*
|
|
18
|
+
* animation.on(EVENTS.UPDATE, (anim) => {
|
|
19
|
+
* console.log(anim.progress);
|
|
20
|
+
* });
|
|
21
|
+
*/
|
|
3
22
|
export const EVENTS: EventTypes;
|
package/types/index.d.ts
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* qarl — simple animation library.
|
|
3
|
+
*
|
|
4
|
+
* Core concepts:
|
|
5
|
+
* - **Core** — base animation class (timing, easing, events)
|
|
6
|
+
* - **FromTo** — interpolates object properties between `from` and `to` values
|
|
7
|
+
* - **Curve** — animates along a Catmull-Rom spline
|
|
8
|
+
* - **Manager** — groups and batch-updates animations
|
|
9
|
+
* - **Loop** — requestAnimationFrame wrapper with delta-time capping
|
|
10
|
+
* - **play()** — quick-start: creates animation + Loop in one call
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* import { GlobalManager, Loop } from 'qarl';
|
|
14
|
+
*
|
|
15
|
+
* const anim = GlobalManager.create({
|
|
16
|
+
* target: mesh.position,
|
|
17
|
+
* to: { x: 10, y: 5 },
|
|
18
|
+
* time: 1000,
|
|
19
|
+
* easing: 'outQuad',
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* anim.play();
|
|
23
|
+
* Loop.start(GlobalManager.update);
|
|
24
|
+
*
|
|
25
|
+
* @packageDocumentation
|
|
26
|
+
*/
|
|
27
|
+
|
|
1
28
|
export { Core } from './Core';
|
|
2
29
|
export { Curve } from './Curve';
|
|
3
30
|
export { FromTo } from './FromTo';
|
package/types/modes.d.ts
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
1
|
import { ModeFunction, ModeName } from './common';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Built-in animation modes.
|
|
5
|
+
* Modes wrap the easing function to create composite effects.
|
|
6
|
+
*
|
|
7
|
+
* - `pingPong` — forward then backward: `easing(t*2)` for first half, `1 - easing((t-0.5)*2)` for second.
|
|
8
|
+
* - `yoyo` — easing applied to a triangle wave: `easing(1 - |1 - t*2|)`.
|
|
9
|
+
* - `bounce` — triangle wave applied after easing: `1 - |1 - easing(t)*2|`.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* import { modes } from 'qarl';
|
|
13
|
+
*
|
|
14
|
+
* // Pass by name
|
|
15
|
+
* { mode: 'pingPong', easing: 'outQuad' }
|
|
16
|
+
*
|
|
17
|
+
* // Or pass the function reference
|
|
18
|
+
* { mode: modes.pingPong, easing: 'outQuad' }
|
|
19
|
+
*/
|
|
3
20
|
export const modes: Record<ModeName, ModeFunction>;
|
package/types/play.d.ts
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
import { Core } from './Core';
|
|
2
2
|
import { CoreSettings, FromToSettings, CurveSettings } from './common';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Quick-start function — creates an animation, starts a Loop, and plays it.
|
|
6
|
+
* Auto-detects the animation type (Core, FromTo, or Curve) from the config.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // Synchronous — returns the animation instance
|
|
10
|
+
* const anim = play({
|
|
11
|
+
* target: mesh.position,
|
|
12
|
+
* to: { x: 10 },
|
|
13
|
+
* time: 1000,
|
|
14
|
+
* });
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Async — returns a Promise that resolves on complete
|
|
18
|
+
* await play({
|
|
19
|
+
* target: mesh.position,
|
|
20
|
+
* to: { x: 10 },
|
|
21
|
+
* time: 1000,
|
|
22
|
+
* }, true);
|
|
23
|
+
* console.log('animation finished');
|
|
24
|
+
*
|
|
25
|
+
* @param config - Animation settings (type is auto-detected)
|
|
26
|
+
* @param async - If `true`, returns a Promise instead of the animation
|
|
27
|
+
*/
|
|
4
28
|
export function play(config: Partial<CoreSettings | FromToSettings | CurveSettings>, async?: false): Core;
|
|
5
29
|
export function play(config: Partial<CoreSettings | FromToSettings | CurveSettings>, async: true): Promise<void>;
|