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 +1 -14
- package/dist/qarl.es.min.js +1 -1
- package/package.json +1 -1
- package/src/behaviors/easings.js +1 -6
- package/src/behaviors/modes.js +13 -13
- package/src/controllers/FromTo.js +1 -1
- package/src/core/Core.js +6 -3
- package/src/core/Loop.js +1 -1
- package/src/ultra/FromToUltra.js +0 -3
- package/test/test-three-scene.js +37 -38
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
|
```
|
package/dist/qarl.es.min.js
CHANGED
|
@@ -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
package/src/behaviors/easings.js
CHANGED
|
@@ -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
|
+
}
|
package/src/behaviors/modes.js
CHANGED
|
@@ -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, //
|
|
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
package/src/ultra/FromToUltra.js
CHANGED
|
@@ -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
|
-
|
package/test/test-three-scene.js
CHANGED
|
@@ -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
|
-
//
|
|
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; //
|
|
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; //
|
|
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 =
|
|
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], //
|
|
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(
|
|
257
|
-
|
|
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
|
});
|