qarl 1.2.0 → 1.2.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/README.md CHANGED
@@ -61,7 +61,6 @@ const curveAnim = new QARL.Curve({
61
61
  mode: QARL.modes.yoyo,
62
62
  easing: QARL.easings.inOutBack,
63
63
  smoothing: 10,
64
-
65
64
  // position.x
66
65
  points: [
67
66
  [-2],
@@ -216,7 +215,6 @@ await QARL.play({ /*... config ...*/ }, true) // true for async
216
215
  ```js
217
216
  import { GlobalManager, Loop } from 'qarl';
218
217
 
219
- // Создаем объекты для анимации
220
218
  const cube = new THREE.Mesh(
221
219
  new THREE.BoxGeometry(),
222
220
  new THREE.MeshBasicMaterial({ color: 0xff6b6b })
@@ -227,7 +225,6 @@ const sphere = new THREE.Mesh(
227
225
  new THREE.MeshBasicMaterial({ color: 0x4ecdc4 })
228
226
  );
229
227
 
230
- // Анимация куба с поворотом
231
228
  const cubeAnimation = GlobalManager.create({
232
229
  target: cube,
233
230
  time: 2000,
@@ -238,7 +235,6 @@ const cubeAnimation = GlobalManager.create({
238
235
  mode: 'pingPong'
239
236
  });
240
237
 
241
- // Анимация сферы с движением и масштабированием
242
238
  const sphereAnimation = GlobalManager.create({
243
239
  target: sphere,
244
240
  time: 3000,
@@ -254,19 +250,10 @@ const sphereAnimation = GlobalManager.create({
254
250
  loop: true,
255
251
  });
256
252
 
257
- // Запускаем анимации
258
253
  cubeAnimation.play();
259
254
  sphereAnimation.play();
260
255
 
261
- // Создаем игровой цикл
262
- const gameLoop = Loop.start((dt) => {
263
- // Обновляем все анимации через GlobalManager
264
- GlobalManager.update(dt);
265
-
266
- // Ваша игровая логика здесь
267
- // renderer.render(scene, camera);
268
- });
256
+ const gameLoop = Loop.start(GlobalManager.update);
269
257
 
270
- // Остановка цикла (если нужно)
271
258
  // Loop.stop(gameLoop);
272
259
  ```
@@ -1 +1 @@
1
- var t={228:t=>{var e=Object.prototype.hasOwnProperty,s="~";function i(){}function n(t,e,s){this.fn=t,this.context=e,this.once=s||!1}function r(t,e,i,r,o){if("function"!=typeof i)throw new TypeError("The listener must be a function");var a=new n(i,r||t,o),h=s?s+e:e;return t._events[h]?t._events[h].fn?t._events[h]=[t._events[h],a]:t._events[h].push(a):(t._events[h]=a,t._eventsCount++),t}function o(t,e){0===--t._eventsCount?t._events=new i:delete t._events[e]}function a(){this._events=new i,this._eventsCount=0}Object.create&&(i.prototype=Object.create(null),(new i).__proto__||(s=!1)),a.prototype.eventNames=function(){var t,i,n=[];if(0===this._eventsCount)return n;for(i in t=this._events)e.call(t,i)&&n.push(s?i.slice(1):i);return Object.getOwnPropertySymbols?n.concat(Object.getOwnPropertySymbols(t)):n},a.prototype.listeners=function(t){var e=s?s+t:t,i=this._events[e];if(!i)return[];if(i.fn)return[i.fn];for(var n=0,r=i.length,o=new Array(r);n<r;n++)o[n]=i[n].fn;return o},a.prototype.listenerCount=function(t){var e=s?s+t:t,i=this._events[e];return i?i.fn?1:i.length:0},a.prototype.emit=function(t,e,i,n,r,o){var a=s?s+t:t;if(!this._events[a])return!1;var h,p,c=this._events[a],l=arguments.length;if(c.fn){switch(c.once&&this.removeListener(t,c.fn,void 0,!0),l){case 1:return c.fn.call(c.context),!0;case 2:return c.fn.call(c.context,e),!0;case 3:return c.fn.call(c.context,e,i),!0;case 4:return c.fn.call(c.context,e,i,n),!0;case 5:return c.fn.call(c.context,e,i,n,r),!0;case 6:return c.fn.call(c.context,e,i,n,r,o),!0}for(p=1,h=new Array(l-1);p<l;p++)h[p-1]=arguments[p];c.fn.apply(c.context,h)}else{var u,m=c.length;for(p=0;p<m;p++)switch(c[p].once&&this.removeListener(t,c[p].fn,void 0,!0),l){case 1:c[p].fn.call(c[p].context);break;case 2:c[p].fn.call(c[p].context,e);break;case 3:c[p].fn.call(c[p].context,e,i);break;case 4:c[p].fn.call(c[p].context,e,i,n);break;default:if(!h)for(u=1,h=new Array(l-1);u<l;u++)h[u-1]=arguments[u];c[p].fn.apply(c[p].context,h)}}return!0},a.prototype.on=function(t,e,s){return r(this,t,e,s,!1)},a.prototype.once=function(t,e,s){return r(this,t,e,s,!0)},a.prototype.removeListener=function(t,e,i,n){var r=s?s+t:t;if(!this._events[r])return this;if(!e)return o(this,r),this;var a=this._events[r];if(a.fn)a.fn!==e||n&&!a.once||i&&a.context!==i||o(this,r);else{for(var h=0,p=[],c=a.length;h<c;h++)(a[h].fn!==e||n&&!a[h].once||i&&a[h].context!==i)&&p.push(a[h]);p.length?this._events[r]=1===p.length?p[0]:p:o(this,r)}return this},a.prototype.removeAllListeners=function(t){var e;return t?(e=s?s+t:t,this._events[e]&&o(this,e)):(this._events=new i,this._eventsCount=0),this},a.prototype.off=a.prototype.removeListener,a.prototype.addListener=a.prototype.on,a.prefixed=s,a.EventEmitter=a,t.exports=a}},e={};function s(i){var n=e[i];if(void 0!==n)return n.exports;var r=e[i]={exports:{}};return t[i](r,r.exports,s),r.exports}s.d=(t,e)=>{for(var i in e)s.o(e,i)&&!s.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},s.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);const i=s(228),n={processors:[],time:0,loop:!1,mode:null,delay:0,repeat:0,target:null,easing:t=>t,reversed:!1,repeatDelay:0},r={PLAY:"play",STOP:"stop",BEGIN:"begin",UPDATE:"update",REPEAT:"repeat",COMPLETE:"complete"},o=2*Math.PI,a=Math.pow,h={reverse:t=>1-t,linear:t=>t,yoyo:t=>1-Math.abs(1-2*t),inQuad:t=>a(t,2),outQuad:t=>t*(2-t),inOutQuad:t=>t<.5?2*t*t:(4-2*t)*t-1,inCubic:t=>a(t,3),outCubic:t=>--t*t*t+1,inOutCubic:t=>t<.5?4*a(t,3):(t-1)*(2*t-2)*(2*t-2)+1,inQuart:t=>a(t,4),outQuart:t=>1- --t*a(t,3),inOutQuart:t=>t<.5?8*a(t,4):1-8*--t*t*t*t,inQuint:t=>a(t,5),outQuint:t=>1+--t*a(t,4),inOutQuint:t=>t<.5?16*a(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,e=1.70158)=>t*t*((e+1)*t-e),outBack:(t,e=1.70158)=>(t-=1)*t*((e+1)*t+e)+1,inOutBack:(t,e=1.70158)=>(t*=2)<1?t*t*((1.525*e+1)*t-1.525*e)*.5:.5*((t-=2)*t*((1.525*e+1)*t+1.525*e)+2),inExpo:t=>0===t?0:Math.pow(2,10*(t-1)),outExpo:t=>1===t?1:1-Math.pow(2,-10*t),inOutExpo:t=>0===t?0:1===t?1:t<.5?.5*Math.pow(2,20*t-10):1-.5*Math.pow(2,-20*t+10),inElastic:(t,e=1,s=.5)=>0===t?0:1===t?1:-e*Math.pow(2,10*(t-1))*Math.sin((t-1-s/o*Math.asin(1/e))*o/s),outElastic:(t,e=1,s=.5)=>0===t?0:1===t?1:e*Math.pow(2,-10*t)*Math.sin((t-s/o*Math.asin(1/e))*o/s)+1,inOutElastic:(t,e=1,s=.5)=>0===t?0:1===t?1:t<.5?-.5*e*Math.pow(2,20*t-10)*Math.sin((20*t-11.125)*o/s):.5*e*Math.pow(2,-20*t+10)*Math.sin((20*t-11.125)*o/s)+1},p={pingPong:function(t){return t<=.5?this._easing(2*t):1-this._easing(2*(t-.5))},yoyo:function(t){return this._easing(h.yoyo(t))},bounce:function(t){return h.yoyo(this._easing(t))}};let c=0;class l extends i{on(...t){return super.on(...t),this}off(...t){return super.off(...t),this}once(...t){return super.once(...t),this}onComplete(...t){return super.on(r.COMPLETE,...t),this}onUpdate(...t){return super.on(r.UPDATE,...t),this}static DEFAULTS=n;static _noop(){}static mergeConfigs(t,e){t!==e&&Object.keys(e).forEach(s=>{"object"==typeof e[s]&&null!==e[s]?(t[s]&&"object"==typeof t[s]||(t[s]={}),l.mergeConfigs(t[s],e[s])):t[s]=e[s]})}static lerp(t,e,s){return t+(e-t)*s}constructor(t={},e){super(),this.index=c++,this.overrides=t,this.settings={},this.reset(t),e&&(this.manager=e),this.lastDeltaTime=0}_processState(){this.step=l._noop,this.progress=0,this.easeValue=0,this.elapsedTime=0,this.promise=null,this._resolve=l._noop,this._refreshDynamicProps()}_refreshDynamicProps(){this.applyProcessors(this.settings);const{target:t,time:e,repeat:s,loop:i,reversed:n,delay:r}=this.settings;this.target=t,this.time=Math.max(e,0),this.repeat=s>0?s:i?1/0:0,this.reversed=n,this.remainingDelay=r,this._processEasing()}_processEasing(){const t="string"==typeof this.settings.easing?h[this.settings.easing]||h.linear:this.settings.easing;this._easing=this.reversed?this._reversedEasing:t;const e="string"==typeof this.settings.mode?p[this.settings.mode]:this.settings.mode;this._calculateEasing=e?e.bind(this):this._easing}_reversedEasing=t=>this.settings.easing(1-t);_update(){this.progress=this.elapsedTime/this.time,this.easeValue=this._calculateEasing(this.progress),this.emit(r.UPDATE,this)}_stepDelay=t=>{this.remainingDelay-=t,this.lastDeltaTime=t,this.remainingDelay>0||(this.step=this._stepTime,this.step(Math.abs(this.remainingDelay)),this.remainingDelay=this.settings.delay)};_stepTime=(t=0)=>{this.elapsedTime+=t,this.lastDeltaTime=t,this.elapsedTime>=this.time?(this.elapsedTime=this.time,this._update(),this._complete()):this._update()};_complete(){this.repeat-- >0?this._repeat():(this._resolve(),this.stop(!1),this.emit(r.COMPLETE))}_repeat(t=!0){this.remainingDelay=this.settings.repeatDelay,this.elapsedTime=0,this.remainingDelay>0&&(this.step=this._stepDelay),this._update(),t&&this.emit(r.REPEAT)}reset(t=this.constructor.DEFAULTS){return this.settings={...this.constructor.DEFAULTS,...t},this._processState(),this}applyProcessors(t=this.settings){t.processors.forEach(e=>{l.mergeConfigs(t,e.call(this,t)||{})})}tweak(t={}){return l.mergeConfigs(this.settings,t),this._refreshDynamicProps(),this}seek(t=0,e=!0){return this.elapsedTime=Math.min(Math.max(t,0),this.time),e&&this._update(),this}setProgress(t=0,e=!0){return this.seek(this.time*t,e)}reverse(t=!1){return this.reversed=!this.reversed,this.seek(this.time-this.elapsedTime,t),this._processEasing(),this}play(t=!0){return this.isPlaying||(t&&this.emit(r.PLAY),this.remainingDelay>0?this.step=this._stepDelay:(this.step=this._stepTime,this.emit(r.BEGIN)),this.manager&&this.manager.addToActive(this)),this}playPromise(t=this.promise){return this.play(),this.promise=t||new Promise(t=>{this._resolve=t}),this.promise}stop(t=!0){return this._processState(),t&&this.emit(r.STOP),this.manager&&this.manager.removeFromActive(this),this}pause(){return this.step=l._noop,this.manager&&this.manager.removeFromActive(this),this}replay(t=!1){return this.stop(t),this.play(t),this}get isPlaying(){return this.step!==l._noop}remove(){this.stop(),this.manager.remove(this)}}class u extends l{static DEFAULTS={...l.DEFAULTS,properties:null,points:[],smoothing:20};_preparePropertySetters(){this.propertySetters=this.properties.map(t=>{const e=t.split("."),s=e.pop();return t=>{let i=this.target;for(let t=0;t<e.length;t++)i=i[e[t]];i[s]=t}})}_generatePath(){const t=this.settings.points,e=Math.max(this.settings.smoothing,1),s=[];function i(t,e,s,i,n){const r=n*n,o=r*n;return t.map((a,h)=>.5*(2*e[h]+(-t[h]+s[h])*n+(2*t[h]-5*e[h]+4*s[h]-i[h])*r+(-t[h]+3*e[h]-3*s[h]+i[h])*o))}this.totalLength=0;for(let n=0;n<t.length-1;n++){const r=t[0===n?n:n-1],o=t[n],a=t[n+1],h=t[n+2<t.length?n+2:n+1];for(let t=0;t<e;t++){const n=i(r,o,a,h,t/e);s.push(n),s.length>1&&(this.totalLength+=this._calculateDistance(s[s.length-2],n))}}return s.push(t[t.length-1]),s}_calculateDistance(t,e){return Math.sqrt(t.reduce((s,i,n)=>s+Math.pow(e[n]-t[n],2),0))}_refreshDynamicProps(){super._refreshDynamicProps(),this.path=this._generatePath(),this.target&&0!==this.path.length?(this._tryToSetupProperties(),this._preparePropertySetters()):this._setTargetProperties=l._noop}_tryToSetupProperties(){if(this.settings.properties)this.properties=this.settings.properties;else if(this.path[0].length<=3){const t=[["position.x"],["position.x","position.y"],["position.x","position.y","position.z"]];this.properties=t[this.path[0].length-1]}else this.properties=[]}_setTargetProperties(t){for(let e=0;e<this.propertySetters.length;e++)this.propertySetters[e](t[e])}_clamp(t,e,s){return Math.max(e,Math.min(t,s))}_getInterpolatedPosition(){const t=this.path.length-1,e=this.easeValue*t,s=this._clamp(e,0,t),i=s>=t?t-1:Math.floor(s),n=Math.min(i+1,t),r=e-i,o=this.path[i],a=this.path[n];return o.map((t,e)=>l.lerp(t,a[e],r))}_update(){super._update(),this._setTargetProperties(this._getInterpolatedPosition())}}class m extends l{static DEFAULTS={...l.DEFAULTS,dynamic:!1,from:null,to:null};_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(t={},e={},s={}){const i=(t,e,s)=>{for(const n in t)"object"==typeof t[n]?(s[n]={},i(t[n],e[n],s[n])):s[n]=e[n]};return i(t,e,s),s}_createLerpStep(t,e,s,i){if(this.settings.dynamic)return()=>{t[i]=l.lerp(e[i],s[i],this.easeValue)};{const n=e[i],r=s[i]-n;return()=>{t[i]=n+r*this.easeValue}}}_createLerps(t=this.target,e=this._from,s=this._to){for(const i in s)"object"==typeof s[i]?this._createLerps(t[i],e[i],s[i]):this._lerps.push(this._createLerpStep(t,e,s,i))}_update(){super._update();for(const t of this._lerps)t()}from(t={}){return this.tweak({from:t}),this}to(t={}){return this.tweak({to:t}),this}swap(){return this.tweak({from:this.settings.to,to:this.settings.from}),this}}function g(t){return t.target?t.creator?t.creator instanceof l?t.creator:(console.error("Invalid creator provided. Using default creator."),l):t.points?u:t.from||t.to?m:l:l}class f{constructor(){this.activeAnimations=new Map,this.allAnimations=new Map}create({on:t={},once:e={},...s}){const i=new(g(s))(s,this);return Object.keys(t).forEach(e=>{i.on(e,t[e])}),Object.keys(e).forEach(t=>{i.once(t,e[t])}),this.add(i),i}update=t=>{this.activeAnimations.forEach(e=>{e.step(t)})};getActiveAnimations(){return Array.from(this.activeAnimations.values())}getAllAnimations(){return Array.from(this.allAnimations.values())}remove({index:t}={}){t&&(this.activeAnimations.delete(t),this.allAnimations.delete(t))}add(t){this.allAnimations.set(t.index,t)}addToActive(t){this.activeAnimations.set(t.index,t)}removeFromActive(t){this.activeAnimations.delete(t.index)}stopAll(){this.activeAnimations.forEach(t=>{t.stop()})}removeAll(){this.stopAll(),this.activeAnimations.clear(),this.allAnimations.clear()}}const _=new f;class y{constructor(t,e={}){this.callback=t,this.options={maxDeltaTime:100,...e},this.isRunning=!1,this.lastTime=0,this.animationId=null}static start(t,e={}){const s=new y(t,e);return s.start(),s}start(){if(this.isRunning)return;this.isRunning=!0;const t=e=>{if(!this.isRunning)return;const s=Math.min(e-this.lastTime,this.options.maxDeltaTime);this.lastTime=e,this.callback(s),this.isRunning&&(this.animationId=requestAnimationFrame(t))};requestAnimationFrame(e=>{this.lastTime=e,t(e)})}stop(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}get running(){return this.isRunning}}function v(t,e){const s=new new g(t)(t);return y.start(s.step.bind(s)),e?s.playPromise():s.play()}export{l as Core,u as Curve,n as DEFAULTS,r as EVENTS,m as FromTo,_ as GlobalManager,y as Loop,f as Manager,h as easings,p as modes,v as play};
1
+ var t={228:t=>{var e=Object.prototype.hasOwnProperty,s="~";function i(){}function n(t,e,s){this.fn=t,this.context=e,this.once=s||!1}function r(t,e,i,r,o){if("function"!=typeof i)throw new TypeError("The listener must be a function");var a=new n(i,r||t,o),h=s?s+e:e;return t._events[h]?t._events[h].fn?t._events[h]=[t._events[h],a]:t._events[h].push(a):(t._events[h]=a,t._eventsCount++),t}function o(t,e){0===--t._eventsCount?t._events=new i:delete t._events[e]}function a(){this._events=new i,this._eventsCount=0}Object.create&&(i.prototype=Object.create(null),(new i).__proto__||(s=!1)),a.prototype.eventNames=function(){var t,i,n=[];if(0===this._eventsCount)return n;for(i in t=this._events)e.call(t,i)&&n.push(s?i.slice(1):i);return Object.getOwnPropertySymbols?n.concat(Object.getOwnPropertySymbols(t)):n},a.prototype.listeners=function(t){var e=s?s+t:t,i=this._events[e];if(!i)return[];if(i.fn)return[i.fn];for(var n=0,r=i.length,o=new Array(r);n<r;n++)o[n]=i[n].fn;return o},a.prototype.listenerCount=function(t){var e=s?s+t:t,i=this._events[e];return i?i.fn?1:i.length:0},a.prototype.emit=function(t,e,i,n,r,o){var a=s?s+t:t;if(!this._events[a])return!1;var h,p,c=this._events[a],l=arguments.length;if(c.fn){switch(c.once&&this.removeListener(t,c.fn,void 0,!0),l){case 1:return c.fn.call(c.context),!0;case 2:return c.fn.call(c.context,e),!0;case 3:return c.fn.call(c.context,e,i),!0;case 4:return c.fn.call(c.context,e,i,n),!0;case 5:return c.fn.call(c.context,e,i,n,r),!0;case 6:return c.fn.call(c.context,e,i,n,r,o),!0}for(p=1,h=new Array(l-1);p<l;p++)h[p-1]=arguments[p];c.fn.apply(c.context,h)}else{var u,m=c.length;for(p=0;p<m;p++)switch(c[p].once&&this.removeListener(t,c[p].fn,void 0,!0),l){case 1:c[p].fn.call(c[p].context);break;case 2:c[p].fn.call(c[p].context,e);break;case 3:c[p].fn.call(c[p].context,e,i);break;case 4:c[p].fn.call(c[p].context,e,i,n);break;default:if(!h)for(u=1,h=new Array(l-1);u<l;u++)h[u-1]=arguments[u];c[p].fn.apply(c[p].context,h)}}return!0},a.prototype.on=function(t,e,s){return r(this,t,e,s,!1)},a.prototype.once=function(t,e,s){return r(this,t,e,s,!0)},a.prototype.removeListener=function(t,e,i,n){var r=s?s+t:t;if(!this._events[r])return this;if(!e)return o(this,r),this;var a=this._events[r];if(a.fn)a.fn!==e||n&&!a.once||i&&a.context!==i||o(this,r);else{for(var h=0,p=[],c=a.length;h<c;h++)(a[h].fn!==e||n&&!a[h].once||i&&a[h].context!==i)&&p.push(a[h]);p.length?this._events[r]=1===p.length?p[0]:p:o(this,r)}return this},a.prototype.removeAllListeners=function(t){var e;return t?(e=s?s+t:t,this._events[e]&&o(this,e)):(this._events=new i,this._eventsCount=0),this},a.prototype.off=a.prototype.removeListener,a.prototype.addListener=a.prototype.on,a.prefixed=s,a.EventEmitter=a,t.exports=a}},e={};function s(i){var n=e[i];if(void 0!==n)return n.exports;var r=e[i]={exports:{}};return t[i](r,r.exports,s),r.exports}s.d=(t,e)=>{for(var i in e)s.o(e,i)&&!s.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},s.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);const i=s(228),n={processors:[],time:0,loop:!1,mode:null,delay:0,repeat:0,target:null,easing:t=>t,reversed:!1,repeatDelay:0},r={PLAY:"play",STOP:"stop",BEGIN:"begin",UPDATE:"update",REPEAT:"repeat",COMPLETE:"complete"},o=2*Math.PI,a=Math.pow,h={reverse:t=>1-t,linear:t=>t,yoyo:t=>1-Math.abs(1-2*t),inQuad:t=>a(t,2),outQuad:t=>t*(2-t),inOutQuad:t=>t<.5?2*t*t:(4-2*t)*t-1,inCubic:t=>a(t,3),outCubic:t=>--t*t*t+1,inOutCubic:t=>t<.5?4*a(t,3):(t-1)*(2*t-2)*(2*t-2)+1,inQuart:t=>a(t,4),outQuart:t=>1- --t*a(t,3),inOutQuart:t=>t<.5?8*a(t,4):1-8*--t*t*t*t,inQuint:t=>a(t,5),outQuint:t=>1+--t*a(t,4),inOutQuint:t=>t<.5?16*a(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,e=1.70158)=>t*t*((e+1)*t-e),outBack:(t,e=1.70158)=>(t-=1)*t*((e+1)*t+e)+1,inOutBack:(t,e=1.70158)=>(t*=2)<1?t*t*((1.525*e+1)*t-1.525*e)*.5:.5*((t-=2)*t*((1.525*e+1)*t+1.525*e)+2),inExpo:t=>0===t?0:Math.pow(2,10*(t-1)),outExpo:t=>1===t?1:1-Math.pow(2,-10*t),inOutExpo:t=>0===t?0:1===t?1:t<.5?.5*Math.pow(2,20*t-10):1-.5*Math.pow(2,-20*t+10),inElastic:(t,e=1,s=.5)=>0===t?0:1===t?1:-e*Math.pow(2,10*(t-1))*Math.sin((t-1-s/o*Math.asin(1/e))*o/s),outElastic:(t,e=1,s=.5)=>0===t?0:1===t?1:e*Math.pow(2,-10*t)*Math.sin((t-s/o*Math.asin(1/e))*o/s)+1,inOutElastic:(t,e=1,s=.5)=>0===t?0:1===t?1:t<.5?-.5*e*Math.pow(2,20*t-10)*Math.sin((20*t-11.125)*o/s):.5*e*Math.pow(2,-20*t+10)*Math.sin((20*t-11.125)*o/s)+1},p={pingPong:function(t){return t<=.5?this._easing(2*t):1-this._easing(2*(t-.5))},yoyo:function(t){return this._easing(h.yoyo(t))},bounce:function(t){return h.yoyo(this._easing(t))}};let c=0;class l extends i{on(...t){return super.on(...t),this}off(...t){return super.off(...t),this}once(...t){return super.once(...t),this}onComplete(...t){return super.on(r.COMPLETE,...t),this}onUpdate(...t){return super.on(r.UPDATE,...t),this}onceComplete(...t){return super.once(r.COMPLETE,...t),this}static DEFAULTS=n;static _noop(){}static mergeConfigs(t,e){t!==e&&Object.keys(e).forEach(s=>{"object"==typeof e[s]&&null!==e[s]?(t[s]&&"object"==typeof t[s]||(t[s]={}),l.mergeConfigs(t[s],e[s])):t[s]=e[s]})}static lerp(t,e,s){return t+(e-t)*s}constructor(t={},e){super(),this.index=c++,this.overrides=t,this.settings={},this.reset(t),e&&(this.manager=e),this.lastDeltaTime=0}_processState(){this.step=l._noop,this.progress=0,this.easeValue=0,this.elapsedTime=0,this.promise=null,this._resolve=l._noop,this._refreshDynamicProps()}_refreshDynamicProps(){this.applyProcessors(this.settings);const{target:t,time:e,repeat:s,loop:i,reversed:n,delay:r}=this.settings;this.target=t,this.time=Math.max(e,0),this.repeat=s>0?s:i?1/0:0,this.reversed=n,this.remainingDelay=r,this._processEasing()}_processEasing(){const t="string"==typeof this.settings.easing?h[this.settings.easing]||h.linear:this.settings.easing;this._easing=this.reversed?this._reversedEasing:t;const e="string"==typeof this.settings.mode?p[this.settings.mode]:this.settings.mode;this._calculateEasing=e?e.bind(this):this._easing}_reversedEasing=t=>this.settings.easing(1-t);_update(){this.progress=this.elapsedTime/this.time,this.easeValue=this._calculateEasing(this.progress),this.emit(r.UPDATE,this)}_stepDelay=t=>{this.remainingDelay-=t,this.lastDeltaTime=t,this.remainingDelay>0||(this.emit(r.BEGIN),this.step=this._stepTime,this.step(Math.abs(this.remainingDelay)),this.remainingDelay=this.settings.delay)};_stepTime=(t=0)=>{this.elapsedTime+=t,this.lastDeltaTime=t,this.elapsedTime>=this.time?(this.elapsedTime=this.time,this._update(),this._complete()):this._update()};_complete(){this.repeat-- >0?this._repeat():(this._resolve(),this.stop(!1),this.emit(r.COMPLETE))}_repeat(t=!0){this.remainingDelay=this.settings.repeatDelay,this.elapsedTime=0,this.remainingDelay>0&&(this.step=this._stepDelay),this._update(),t&&this.emit(r.REPEAT)}reset(t=this.constructor.DEFAULTS){return this.settings={...this.constructor.DEFAULTS,...t},this._processState(),this}applyProcessors(t=this.settings){t.processors.forEach(e=>{l.mergeConfigs(t,e.call(this,t)||{})})}tweak(t={}){return l.mergeConfigs(this.settings,t),this._refreshDynamicProps(),this}seek(t=0,e=!0){return this.elapsedTime=Math.min(Math.max(t,0),this.time),e&&this._update(),this}setProgress(t=0,e=!0){return this.seek(this.time*t,e)}reverse(t=!1){return this.reversed=!this.reversed,this.seek(this.time-this.elapsedTime,t),this._processEasing(),this}play(t=!0){return this.isPlaying||(t&&this.emit(r.PLAY),this.remainingDelay>0?this.step=this._stepDelay:(this.step=this._stepTime,this.emit(r.BEGIN)),this.manager&&this.manager.addToActive(this)),this}playPromise(t=this.promise){return this.play(),this.promise=t||new Promise(t=>{this._resolve=t}),this.promise}stop(t=!0){return this._processState(),t&&this.emit(r.STOP),this.manager&&this.manager.removeFromActive(this),this}pause(){return this.step=l._noop,this.manager&&this.manager.removeFromActive(this),this}replay(t=!1){return this.stop(t),this.play(t),this}get isPlaying(){return this.step!==l._noop}remove(){this.stop(),this.manager.remove(this)}}class u extends l{static DEFAULTS={...l.DEFAULTS,properties:null,points:[],smoothing:20};_preparePropertySetters(){this.propertySetters=this.properties.map(t=>{const e=t.split("."),s=e.pop();return t=>{let i=this.target;for(let t=0;t<e.length;t++)i=i[e[t]];i[s]=t}})}_generatePath(){const t=this.settings.points,e=Math.max(this.settings.smoothing,1),s=[];function i(t,e,s,i,n){const r=n*n,o=r*n;return t.map((a,h)=>.5*(2*e[h]+(-t[h]+s[h])*n+(2*t[h]-5*e[h]+4*s[h]-i[h])*r+(-t[h]+3*e[h]-3*s[h]+i[h])*o))}this.totalLength=0;for(let n=0;n<t.length-1;n++){const r=t[0===n?n:n-1],o=t[n],a=t[n+1],h=t[n+2<t.length?n+2:n+1];for(let t=0;t<e;t++){const n=i(r,o,a,h,t/e);s.push(n),s.length>1&&(this.totalLength+=this._calculateDistance(s[s.length-2],n))}}return s.push(t[t.length-1]),s}_calculateDistance(t,e){return Math.sqrt(t.reduce((s,i,n)=>s+Math.pow(e[n]-t[n],2),0))}_refreshDynamicProps(){super._refreshDynamicProps(),this.path=this._generatePath(),this.target&&0!==this.path.length?(this._tryToSetupProperties(),this._preparePropertySetters()):this._setTargetProperties=l._noop}_tryToSetupProperties(){if(this.settings.properties)this.properties=this.settings.properties;else if(this.path[0].length<=3){const t=[["position.x"],["position.x","position.y"],["position.x","position.y","position.z"]];this.properties=t[this.path[0].length-1]}else this.properties=[]}_setTargetProperties(t){for(let e=0;e<this.propertySetters.length;e++)this.propertySetters[e](t[e])}_clamp(t,e,s){return Math.max(e,Math.min(t,s))}_getInterpolatedPosition(){const t=this.path.length-1,e=this.easeValue*t,s=this._clamp(e,0,t),i=s>=t?t-1:Math.floor(s),n=Math.min(i+1,t),r=e-i,o=this.path[i],a=this.path[n];return o.map((t,e)=>l.lerp(t,a[e],r))}_update(){super._update(),this._setTargetProperties(this._getInterpolatedPosition())}}class m extends l{static DEFAULTS={...l.DEFAULTS,dynamic:!1,from:null,to:null};_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(t={},e={},s={}){const i=(t,e,s)=>{for(const n in t)"object"==typeof t[n]?(s[n]={},i(t[n],e[n],s[n])):s[n]=e[n]};return i(t,e,s),s}_createLerpStep(t,e,s,i){if(this.settings.dynamic)return()=>{t[i]=l.lerp(e[i],s[i],this.easeValue)};{const n=e[i],r=s[i]-n;return()=>{t[i]=n+r*this.easeValue}}}_createLerps(t=this.target,e=this._from,s=this._to){for(const i in s)"object"==typeof s[i]?this._createLerps(t[i],e[i],s[i]):this._lerps.push(this._createLerpStep(t,e,s,i))}_update(){super._update();for(const t of this._lerps)t()}from(t={}){return this.tweak({from:t}),this}to(t={}){return this.tweak({to:t}),this}swap(){return this.tweak({from:this.settings.to,to:this.settings.from}),this}}function g(t){return t.target?t.creator?t.creator instanceof l?t.creator:(console.error("Invalid creator provided. Using default creator."),l):t.points?u:t.from||t.to?m:l:l}class f{constructor(){this.activeAnimations=new Map,this.allAnimations=new Map}create({on:t={},once:e={},...s}){const i=new(g(s))(s,this);return Object.keys(t).forEach(e=>{i.on(e,t[e])}),Object.keys(e).forEach(t=>{i.once(t,e[t])}),this.add(i),i}update=t=>{this.activeAnimations.forEach(e=>{e.step(t)})};getActiveAnimations(){return Array.from(this.activeAnimations.values())}getAllAnimations(){return Array.from(this.allAnimations.values())}remove({index:t}={}){t&&(this.activeAnimations.delete(t),this.allAnimations.delete(t))}add(t){this.allAnimations.set(t.index,t)}addToActive(t){this.activeAnimations.set(t.index,t)}removeFromActive(t){this.activeAnimations.delete(t.index)}stopAll(){this.activeAnimations.forEach(t=>{t.stop()})}removeAll(){this.stopAll(),this.activeAnimations.clear(),this.allAnimations.clear()}}const _=new f;class y{constructor(t,e={}){this.callback=t,this.options={maxDeltaTime:100,...e},this.isRunning=!1,this.lastTime=0,this.animationId=null}static start(t,e={}){const s=new y(t,e);return s.start(),s}start(){if(this.isRunning)return;this.isRunning=!0;const t=e=>{if(!this.isRunning)return;const s=Math.min(e-this.lastTime,this.options.maxDeltaTime);this.lastTime=e,this.callback(s),this.isRunning&&(this.animationId=requestAnimationFrame(t))};requestAnimationFrame(e=>{this.lastTime=e,t(e)})}stop(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}get running(){return this.isRunning}}function v(t,e){const s=new new g(t)(t);return y.start(s.step.bind(s)),e?s.playPromise():s.play()}export{l as Core,u as Curve,n as DEFAULTS,r as EVENTS,m as FromTo,_ as GlobalManager,y as Loop,f as Manager,h as easings,p as modes,v as play};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qarl",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "simple animation library",
5
5
  "main": "dist/qarl.es.min.js",
6
6
  "module": "dist/qarl.es.min.js",
@@ -3,11 +3,6 @@
3
3
  const PI2 = Math.PI * 2
4
4
  const pow = Math.pow
5
5
 
6
- // оптимизировать вычисления - для ускорения
7
- // сократить код - для компактности
8
- // разделить на отдельные методы вместо одного большого объекта - для независимости
9
- // поправить нейминг или перенестив другую область reverse, linear, yoyo - в идеале облегчить доступ через QARL."easeName"
10
- // или вообще использовать строки вместо функций - "easeName" - для простоты
11
6
  export const easings = {
12
7
  reverse: (t) => 1 - t,
13
8
  linear: (t) => t,
@@ -75,4 +70,4 @@ export const easings = {
75
70
  ? -0.5 * a * Math.pow(2, 20 * t - 10) * Math.sin(((20 * t - 11.125) * PI2) / p)
76
71
  : 0.5 * a * Math.pow(2, -20 * t + 10) * Math.sin(((20 * t - 11.125) * PI2) / p) + 1
77
72
  )
78
- }
73
+ }
@@ -1,11 +1,11 @@
1
1
  import { easings } from "./easings"
2
2
 
3
3
  /**
4
- * Объект, содержащий модификаторы анимации.
4
+ * Object containing animation modifiers.
5
5
  * @namespace
6
- * @property {function} pingPong - Реализует пинг-понг эффект для анимации.
7
- * @property {function} yoyo - Реализует эффект зеркального отражения анимации.
8
- * @property {function} bounce - Реализует эффект отскока для анимации.
6
+ * @property {function} pingPong - Implements ping-pong effect for animation.
7
+ * @property {function} yoyo - Implements mirror reflection effect for animation.
8
+ * @property {function} bounce - Implements bounce effect for animation.
9
9
  * @example
10
10
  * const animation = new Core({ time: 1000, mode: modes.pingPong })
11
11
  * animation.play()
@@ -14,9 +14,9 @@ import { easings } from "./easings"
14
14
  */
15
15
  export const modes = {
16
16
  /**
17
- * Реализует пинг-понг эффект для анимации.
18
- * @param {number} t - Текущее время анимации.
19
- * @returns {number} Измененное значение времени для эффекта пинг-понг.
17
+ * Implements ping-pong effect for animation.
18
+ * @param {number} t - Current animation time.
19
+ * @returns {number} Modified time value for ping-pong effect.
20
20
  */
21
21
  pingPong: function (t) {
22
22
  return t <= 0.5
@@ -25,18 +25,18 @@ export const modes = {
25
25
  },
26
26
 
27
27
  /**
28
- * Реализует эффект зеркального отражения анимации.
29
- * @param {number} t - Текущее время анимации.
30
- * @returns {number} Измененное значение времени для эффекта зеркального отражения.
28
+ * Implements mirror reflection effect for animation.
29
+ * @param {number} t - Current animation time.
30
+ * @returns {number} Modified time value for mirror reflection effect.
31
31
  */
32
32
  yoyo: function (t) {
33
33
  return this._easing(easings.yoyo(t))
34
34
  },
35
35
 
36
36
  /**
37
- * Реализует эффект отскока для анимации.
38
- * @param {number} t - Текущее время анимации.
39
- * @returns {number} Измененное значение времени для эффекта отскока.
37
+ * Implements bounce effect for animation.
38
+ * @param {number} t - Current animation time.
39
+ * @returns {number} Modified time value for bounce effect.
40
40
  */
41
41
  bounce: function (t) {
42
42
  return easings.yoyo(this._easing(t))
@@ -4,7 +4,7 @@ export class FromTo extends Core {
4
4
 
5
5
  static DEFAULTS = {
6
6
  ...Core.DEFAULTS,
7
- dynamic: false, // в динамическом состоянии можно обновлять значения from и to во время анимации
7
+ dynamic: false, // in dynamic state you can update from and to values during animation
8
8
  from: null,
9
9
  to: null
10
10
  }
package/src/core/Core.js CHANGED
@@ -37,6 +37,11 @@ export class Core extends EventEmitter {
37
37
  return this;
38
38
  }
39
39
 
40
+ onceComplete(...args) {
41
+ super.once(EVENTS.COMPLETE, ...args);
42
+ return this;
43
+ }
44
+
40
45
  /**
41
46
  * Default settings for the Core class.
42
47
  * @static
@@ -59,7 +64,6 @@ export class Core extends EventEmitter {
59
64
  * @private
60
65
  */
61
66
  static mergeConfigs(target, source) {
62
- // Проверка на циклические ссылки
63
67
  if (target === source) {
64
68
  return;
65
69
  }
@@ -136,14 +140,12 @@ export class Core extends EventEmitter {
136
140
  * @private
137
141
  */
138
142
  _processEasing() {
139
- // Поддержка строк для easing
140
143
  const easing = typeof this.settings.easing === 'string'
141
144
  ? easings[this.settings.easing] || easings.linear
142
145
  : this.settings.easing;
143
146
 
144
147
  this._easing = this.reversed ? this._reversedEasing : easing;
145
148
 
146
- // Поддержка строк для mode
147
149
  const mode = typeof this.settings.mode === 'string'
148
150
  ? modes[this.settings.mode]
149
151
  : this.settings.mode;
@@ -182,6 +184,7 @@ export class Core extends EventEmitter {
182
184
 
183
185
  if (this.remainingDelay > 0) return;
184
186
 
187
+ this.emit(EVENTS.BEGIN);
185
188
  this.step = this._stepTime;
186
189
  this.step(Math.abs(this.remainingDelay));
187
190
  this.remainingDelay = this.settings.delay;
package/src/core/Loop.js CHANGED
@@ -2,7 +2,7 @@ class Loop {
2
2
  constructor(callback, options = {}) {
3
3
  this.callback = callback;
4
4
  this.options = {
5
- maxDeltaTime: 100, // максимальный deltaTime в ms
5
+ maxDeltaTime: 100,
6
6
  ...options
7
7
  };
8
8
 
@@ -41,7 +41,6 @@ export class FromTo extends Core {
41
41
  return a + (b - a) * t
42
42
  }
43
43
 
44
- // Определение метода _recreateLerps
45
44
  _recreateLerps() {
46
45
  this._createLerps()
47
46
  }
@@ -100,5 +99,3 @@ export class FromTo extends Core {
100
99
  return this
101
100
  }
102
101
  }
103
-
104
-
@@ -1,6 +1,8 @@
1
1
  import * as THREE from 'three';
2
2
  import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
3
- import { GlobalManager, Loop } from '../src/index.js';
3
+ import { Manager, GlobalManager, Loop } from '../src/index.js';
4
+
5
+ const manager = new Manager();
4
6
 
5
7
  class ThreeScene {
6
8
  constructor() {
@@ -19,11 +21,11 @@ class ThreeScene {
19
21
  }
20
22
 
21
23
  init() {
22
- // Создаем сцену
24
+ // Create scene
23
25
  this.scene = new THREE.Scene();
24
26
  this.scene.background = new THREE.Color(0x111111);
25
27
 
26
- // Создаем камеру
28
+ // Create camera
27
29
  this.camera = new THREE.PerspectiveCamera(
28
30
  75,
29
31
  window.innerWidth / window.innerHeight,
@@ -32,7 +34,7 @@ class ThreeScene {
32
34
  );
33
35
  this.camera.position.set(0, 0, 5);
34
36
 
35
- // Создаем рендерер
37
+ // Create renderer
36
38
  this.renderer = new THREE.WebGLRenderer({
37
39
  canvas: document.getElementById('canvas'),
38
40
  antialias: true
@@ -41,33 +43,33 @@ class ThreeScene {
41
43
  this.renderer.shadowMap.enabled = true;
42
44
  this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
43
45
 
44
- // Добавляем OrbitControls
46
+ // Add OrbitControls
45
47
  this.controls = new OrbitControls(this.camera, this.renderer.domElement);
46
48
  this.controls.enableDamping = true;
47
49
  this.controls.dampingFactor = 0.05;
48
50
 
49
- // Создаем освещение
51
+ // Setup lighting
50
52
  this.setupLighting();
51
53
 
52
- // Создаем объекты
54
+ // Create objects
53
55
  this.createObjects();
54
56
 
55
- // Обработка изменения размера окна
57
+ // Handle window resize
56
58
  window.addEventListener('resize', () => this.onWindowResize());
57
59
  }
58
60
 
59
61
  setupLighting() {
60
- // Основной свет
62
+ // Ambient light
61
63
  const ambientLight = new THREE.AmbientLight(0x404040, 0.4);
62
64
  this.scene.add(ambientLight);
63
65
 
64
- // Направленный свет
66
+ // Directional light
65
67
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
66
68
  directionalLight.position.set(10, 10, 5);
67
69
  directionalLight.castShadow = true;
68
70
  this.scene.add(directionalLight);
69
71
 
70
- // Точечный свет
72
+ // Point light
71
73
  const pointLight = new THREE.PointLight(0x4CAF50, 0.6, 100);
72
74
  pointLight.position.set(-5, 5, 5);
73
75
  this.scene.add(pointLight);
@@ -76,7 +78,7 @@ class ThreeScene {
76
78
  }
77
79
 
78
80
  createObjects() {
79
- // Куб
81
+ // Cube
80
82
  const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
81
83
  const cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xff6b6b });
82
84
  const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
@@ -86,7 +88,7 @@ class ThreeScene {
86
88
  this.scene.add(cube);
87
89
  this.objects.cube = cube;
88
90
 
89
- // Сфера
91
+ // Sphere
90
92
  const sphereGeometry = new THREE.SphereGeometry(0.7, 32, 32);
91
93
  const sphereMaterial = new THREE.MeshLambertMaterial({ color: 0x4ecdc4 });
92
94
  const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
@@ -96,7 +98,7 @@ class ThreeScene {
96
98
  this.scene.add(sphere);
97
99
  this.objects.sphere = sphere;
98
100
 
99
- // Тор
101
+ // Torus
100
102
  const torusGeometry = new THREE.TorusGeometry(0.6, 0.2, 16, 100);
101
103
  const torusMaterial = new THREE.MeshLambertMaterial({ color: 0x45b7d1 });
102
104
  const torus = new THREE.Mesh(torusGeometry, torusMaterial);
@@ -106,7 +108,7 @@ class ThreeScene {
106
108
  this.scene.add(torus);
107
109
  this.objects.torus = torus;
108
110
 
109
- // Плоскость (пол)
111
+ // Plane (floor)
110
112
  const planeGeometry = new THREE.PlaneGeometry(20, 20);
111
113
  const planeMaterial = new THREE.MeshLambertMaterial({ color: 0x333333 });
112
114
  const plane = new THREE.Mesh(planeGeometry, planeMaterial);
@@ -116,50 +118,50 @@ class ThreeScene {
116
118
  this.scene.add(plane);
117
119
  this.objects.plane = plane;
118
120
 
119
- // Стрелка
121
+ // Arrow
120
122
  this.createArrow();
121
123
  }
122
124
 
123
125
  createArrow() {
124
- // Создаем группу для стрелки
126
+ // Create arrow group
125
127
  const arrowGroup = new THREE.Group();
126
128
 
127
- // Прямоугольник (основание стрелки)
129
+ // Rectangle (arrow shaft)
128
130
  const shaftGeometry = new THREE.BoxGeometry(0.5, 1.5, 0.1);
129
131
  const shaftMaterial = new THREE.MeshLambertMaterial({ color: 0xff4757 });
130
132
  const shaft = new THREE.Mesh(shaftGeometry, shaftMaterial);
131
- shaft.position.y = 0.5; // Поднимаем на половину высоты
133
+ shaft.position.y = 0.5; // Raise by half height
132
134
  shaft.castShadow = false;
133
135
  shaft.receiveShadow = false;
134
136
 
135
- // Два прямоугольника для наконечника стрелки
137
+ // Two rectangles for arrow head
136
138
  const arrowMaterial = new THREE.MeshLambertMaterial({ color: 0xff4757 });
137
139
 
138
- // Первый прямоугольник стрелки
140
+ // First arrow rectangle
139
141
  const arrowGeometry1 = new THREE.BoxGeometry(0.8, 0.3, 0.1);
140
142
  const arrow1 = new THREE.Mesh(arrowGeometry1, arrowMaterial);
141
143
  arrow1.position.set(0.2, 1.25, 0);
142
- arrow1.rotation.z = -Math.PI / 4; // Поворачиваем на 30 градусов
144
+ arrow1.rotation.z = -Math.PI / 4; // Rotate 30 degrees
143
145
  arrow1.castShadow = false;
144
146
  arrow1.receiveShadow = false;
145
147
 
146
- // Второй прямоугольник стрелки
148
+ // Second arrow rectangle
147
149
  const arrowGeometry2 = new THREE.BoxGeometry(0.8, 0.3, 0.1);
148
150
  const arrow2 = new THREE.Mesh(arrowGeometry2, arrowMaterial);
149
151
  arrow2.position.set(-0.2, 1.25, 0);
150
- arrow2.rotation.z = Math.PI / 4; // Поворачиваем на -30 градусов
152
+ arrow2.rotation.z = Math.PI / 4; // Rotate -30 degrees
151
153
  arrow2.castShadow = false;
152
154
  arrow2.receiveShadow = false;
153
155
 
154
- // Добавляем части в группу
156
+ // Add parts to group
155
157
  arrowGroup.add(shaft);
156
158
  arrowGroup.add(arrow1);
157
159
  arrowGroup.add(arrow2);
158
160
 
159
- // Поворачиваем группу так, чтобы стрелка смотрела вниз
161
+ // Rotate group so arrow points down
160
162
  arrowGroup.rotation.x = Math.PI;
161
163
 
162
- // Позиционируем стрелку
164
+ // Position arrow
163
165
  arrowGroup.position.set(5, 3, 0);
164
166
 
165
167
  this.scene.add(arrowGroup);
@@ -212,7 +214,7 @@ class ThreeScene {
212
214
 
213
215
  animateTorus() {
214
216
  const torus = this.objects.torus;
215
- const animation = GlobalManager.create({
217
+ const animation = manager.create({
216
218
  target: torus.scale,
217
219
  time: 1500,
218
220
  from: { x: 1, y: 1, z: 1 },
@@ -233,9 +235,9 @@ class ThreeScene {
233
235
  time: 2000,
234
236
  properties: ['position.y', 'scale.y', 'rotation.y'],
235
237
  points: [
236
- [3, 1, -Math.PI * 2], // Начальная позиция - высоко, нормальный размер
237
- [0, 0.5, 0], // Опускается ниже и сжимается по Y (как мячик при ударе)
238
- [3, 1, Math.PI * 2] // Возвращается в исходное состояние
238
+ [3, 1, -Math.PI * 2], // Initial position - high, normal size
239
+ [0, 0.5, 0], // Goes down and compresses on Y (like ball on impact)
240
+ [3, 1, Math.PI * 2] // Returns to initial state
239
241
  ],
240
242
  smoothing: 20,
241
243
  easing: 'inOutSine',
@@ -253,20 +255,17 @@ class ThreeScene {
253
255
  }
254
256
 
255
257
  startAnimationLoop() {
256
- this.loop = Loop.start((dt) => {
257
- // Обновляем анимации через GlobalManager
258
- GlobalManager.update(dt);
258
+ this.loop = Loop.start(GlobalManager.update);
259
+ this.loop = Loop.start(manager.update);
259
260
 
260
- // Обновляем контролы камеры
261
+ this.loop = Loop.start((dt) => {
261
262
  this.controls.update();
262
-
263
- // Рендерим сцену
264
263
  this.renderer.render(this.scene, this.camera);
265
264
  });
266
265
  }
267
266
  }
268
267
 
269
- // Инициализация при загрузке страницы
268
+ // Initialize on page load
270
269
  document.addEventListener('DOMContentLoaded', () => {
271
270
  new ThreeScene();
272
271
  });