@andresclua/perlindom 0.0.5 → 0.0.6

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/CHANGELOG.md CHANGED
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.0.6] - 2025-02-09
9
+
10
+ ## Changed
11
+ - **Transform Handling**: Movement now composes `translate3d` with existing CSS transforms (`scale`, `rotate`, etc.) instead of overriding them
12
+ - **Base Transform Extraction**: Introduced `#extractBaseTransform()` to strip prior translations while keeping scale/rotate/skew intact
13
+ - **Destroy Behavior**: `destroy()` now restores the original inline `transform` value of the element
14
+
15
+ ### Improved
16
+ - **Configuration**: Added `preserveBaseTranslation` option to control whether original translations are kept
17
+ - **Flexibility**: New `refreshBaseTransform()` method allows recalculating the base transform when classes or styles change dynamically
18
+
8
19
  ## [0.0.5] - 2025-01-07
9
20
 
10
21
  - **Remove logs** : remove logs
@@ -1,59 +1,65 @@
1
- var j = Object.defineProperty;
2
- var S = (c) => {
1
+ var D = Object.defineProperty;
2
+ var z = (c) => {
3
3
  throw TypeError(c);
4
4
  };
5
- var C = (c, t, i) => t in c ? j(c, t, { enumerable: !0, configurable: !0, writable: !0, value: i }) : c[t] = i;
6
- var q = (c, t, i) => C(c, typeof t != "symbol" ? t + "" : t, i), k = (c, t, i) => t.has(c) || S("Cannot " + i);
7
- var Y = (c, t, i) => t.has(c) ? S("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(c) : t.set(c, i);
8
- var a = (c, t, i) => (k(c, t, "access private method"), i);
9
- var n, W, H, R, v, p, T, $, L;
10
- const o = class o {
5
+ var H = (c, t, s) => t in c ? D(c, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : c[t] = s;
6
+ var S = (c, t, s) => H(c, typeof t != "symbol" ? t + "" : t, s), j = (c, t, s) => t.has(c) || z("Cannot " + s);
7
+ var A = (c, t, s) => t.has(c) ? z("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(c) : t.set(c, s);
8
+ var n = (c, t, s) => (j(c, t, "access private method"), s);
9
+ var r, E, I, d, P, f, W, C, T, B;
10
+ const l = class l {
11
11
  constructor({
12
12
  element: t,
13
- x: i = null,
14
- y: r = null,
13
+ x: s = null,
14
+ y: e = null,
15
15
  speed: h = 0.01,
16
- seed: l = 0,
17
- lerpSpeed: s = 0.1
16
+ seed: o = 0,
17
+ lerpSpeed: i = 0.1,
18
+ preserveBaseTranslation: a = !1
19
+ // <-- si querés mantener la traslación base
18
20
  }) {
19
- Y(this, p);
20
- q(this, "animate", () => {
21
- var t, i, r, h, l, s, e, m, g, f, u, d;
22
- if (this.lerpFactor !== this.targetLerpFactor && (this.lerpFactor = a(this, p, $).call(this, this.lerpFactor, this.targetLerpFactor, this.lerpSpeed), Math.abs(this.lerpFactor - this.targetLerpFactor) < 1e-3 && (this.lerpFactor = this.targetLerpFactor)), this.lerpFactor > 0) {
21
+ A(this, f);
22
+ S(this, "animate", () => {
23
+ var t, s, e, h, o, i, a, m, g, p, u, R;
24
+ if (this.lerpFactor !== this.targetLerpFactor && (this.lerpFactor = n(this, f, C).call(this, this.lerpFactor, this.targetLerpFactor, this.lerpSpeed), Math.abs(this.lerpFactor - this.targetLerpFactor) < 1e-3 && (this.lerpFactor = this.targetLerpFactor)), this.lerpFactor > 0) {
23
25
  this.time += this.speed * this.lerpFactor;
24
- const x = this.noise.perlin2(this.time, 0), A = this.noise.perlin2(this.time, 100);
26
+ const x = this.noise.perlin2(this.time, 0), b = this.noise.perlin2(this.time, 100);
25
27
  if (this.el) {
26
- let F, y, P, X;
28
+ let F, y, v, L;
27
29
  if (this.hasPercentages) {
28
- const w = this.el.parentElement || document.body, M = w.clientWidth, B = w.clientHeight;
29
- this.xRange && (F = a(t = o, n, R).call(t, this.xRange.min) ? a(i = o, n, v).call(i, this.xRange.min, M) : this.xRange.min, y = a(r = o, n, R).call(r, this.xRange.max) ? a(h = o, n, v).call(h, this.xRange.max, M) : this.xRange.max), this.yRange && (P = a(l = o, n, R).call(l, this.yRange.min) ? a(s = o, n, v).call(s, this.yRange.min, B) : this.yRange.min, X = a(e = o, n, R).call(e, this.yRange.max) ? a(m = o, n, v).call(m, this.yRange.max, B) : this.yRange.max);
30
+ const Y = this.el.parentElement || document.body, $ = Y.clientWidth, M = Y.clientHeight;
31
+ this.xRange && (F = n(t = l, r, d).call(t, this.xRange.min) ? n(s = l, r, P).call(s, this.xRange.min, $) : this.xRange.min, y = n(e = l, r, d).call(e, this.xRange.max) ? n(h = l, r, P).call(h, this.xRange.max, $) : this.xRange.max), this.yRange && (v = n(o = l, r, d).call(o, this.yRange.min) ? n(i = l, r, P).call(i, this.yRange.min, M) : this.yRange.min, L = n(a = l, r, d).call(a, this.yRange.max) ? n(m = l, r, P).call(m, this.yRange.max, M) : this.yRange.max);
30
32
  } else
31
- F = (g = this.xRange) == null ? void 0 : g.min, y = (f = this.xRange) == null ? void 0 : f.max, P = (u = this.yRange) == null ? void 0 : u.min, X = (d = this.yRange) == null ? void 0 : d.max;
32
- const z = this.xRange ? a(this, p, L).call(this, x, -1, 1, F, y) : 0, b = this.yRange ? a(this, p, L).call(this, A, -1, 1, P, X) : 0;
33
- this.lastX = z, this.lastY = b, this.el.style.transform = `translate3d(${z}px, ${b}px, 0)`;
33
+ F = (g = this.xRange) == null ? void 0 : g.min, y = (p = this.xRange) == null ? void 0 : p.max, v = (u = this.yRange) == null ? void 0 : u.min, L = (R = this.yRange) == null ? void 0 : R.max;
34
+ const X = this.xRange ? n(this, f, T).call(this, x, -1, 1, F, y) : 0, w = this.yRange ? n(this, f, T).call(this, b, -1, 1, v, L) : 0;
35
+ this.lastX = X, this.lastY = w, this.el.style.transform = `translate3d(${X}px, ${w}px, 0) ${this.baseTransform}`.trim();
34
36
  } else {
35
- const F = this.xRange ? a(this, p, L).call(this, x, -1, 1, this.xRange.min, this.xRange.max) : 0, y = this.yRange ? a(this, p, L).call(this, A, -1, 1, this.yRange.min, this.yRange.max) : 0;
37
+ const F = this.xRange ? n(this, f, T).call(this, x, -1, 1, this.xRange.min, this.xRange.max) : 0, y = this.yRange ? n(this, f, T).call(this, b, -1, 1, this.yRange.min, this.yRange.max) : 0;
36
38
  this.lastX = F, this.lastY = y;
37
39
  }
38
40
  }
39
41
  (this.lerpFactor > 0 || this.targetLerpFactor > 0) && (this.raf = requestAnimationFrame(this.animate));
40
42
  });
41
- var e, m, g, f;
42
- if (this.el = t, this.xRange = i, this.yRange = r, this.speed = h, this.time = l, this.isPlaying = !0, this.lerpFactor = 1, this.lerpSpeed = s, this.targetLerpFactor = 1, this.lastX = 0, this.lastY = 0, this.hasPercentages = !1, (i && (a(e = o, n, R).call(e, i.min) || a(m = o, n, R).call(m, i.max)) || r && (a(g = o, n, R).call(g, r.min) || a(f = o, n, R).call(f, r.max))) && (this.hasPercentages = !0), t) {
43
- const u = window.getComputedStyle(t);
44
- u.position === "static" && (t.style.position = "relative");
45
- const d = u.transform;
46
- (!d || d === "none") && (t.style.transform = "translate3d(0px, 0px, 0px)"), this.hasPercentages && (this.handleResize = this.handleResize.bind(this), window.addEventListener("resize", this.handleResize));
47
- }
48
- this.animate = this.animate.bind(this), this.init(l);
43
+ var m, g, p, u;
44
+ if (this.el = t, this.xRange = s, this.yRange = e, this.speed = h, this.time = o, this.isPlaying = !0, this.lerpFactor = 1, this.lerpSpeed = i, this.targetLerpFactor = 1, this.lastX = 0, this.lastY = 0, this.preserveBaseTranslation = a, this.hasPercentages = !!(s && (n(m = l, r, d).call(m, s.min) || n(g = l, r, d).call(g, s.max)) || e && (n(p = l, r, d).call(p, e.min) || n(u = l, r, d).call(u, e.max))), t) {
45
+ const R = window.getComputedStyle(t);
46
+ R.position === "static" && (t.style.position = "relative"), this.originalInlineTransform = t.style.transform || "", this.baseTransform = n(this, f, B).call(this, R.transform, this.preserveBaseTranslation), this.hasPercentages && (this.handleResize = this.handleResize.bind(this), window.addEventListener("resize", this.handleResize));
47
+ } else
48
+ this.originalInlineTransform = "", this.baseTransform = "";
49
+ this.animate = this.animate.bind(this), this.init(o);
49
50
  }
50
51
  init(t) {
51
- var i;
52
- this.noise = a(this, p, T).call(this, a(i = o, n, H).call(i, t)), this.isPlaying = !0, this.lerpFactor = 1, this.targetLerpFactor = 1, this.raf = requestAnimationFrame(this.animate);
52
+ var s;
53
+ this.noise = n(this, f, W).call(this, n(s = l, r, I).call(s, t)), this.isPlaying = !0, this.lerpFactor = 1, this.targetLerpFactor = 1, this.raf = requestAnimationFrame(this.animate);
54
+ }
55
+ // Permite refrescar el transform base si cambian clases/estilos en runtime
56
+ refreshBaseTransform(t = this.preserveBaseTranslation) {
57
+ if (!this.el) return;
58
+ const s = window.getComputedStyle(this.el);
59
+ this.baseTransform = n(this, f, B).call(this, s.transform, t);
53
60
  }
54
61
  // Handle window resize for percentage-based values
55
62
  handleResize() {
56
- this.hasPercentages && this.el && (this.needsRecalculation = !0);
57
63
  }
58
64
  pause() {
59
65
  this.isPlaying && (this.targetLerpFactor = 0, this.isPlaying = !1);
@@ -62,66 +68,71 @@ const o = class o {
62
68
  this.isPlaying || (this.targetLerpFactor = 1, this.isPlaying = !0, this.lerpFactor === 0 && (this.raf = requestAnimationFrame(this.animate)));
63
69
  }
64
70
  destroy() {
65
- cancelAnimationFrame(this.raf), this.hasPercentages && window.removeEventListener("resize", this.handleResize);
71
+ cancelAnimationFrame(this.raf), this.el && (this.el.style.transform = this.originalInlineTransform || ""), this.hasPercentages && window.removeEventListener("resize", this.handleResize);
66
72
  }
67
73
  };
68
- n = new WeakSet(), W = function(t) {
74
+ r = new WeakSet(), E = function(t) {
69
75
  return function() {
70
- let i = t += 1831565813;
71
- return i = Math.imul(i ^ i >>> 15, i | 1), i ^= i + Math.imul(i ^ i >>> 7, i | 61), ((i ^ i >>> 14) >>> 0) / 4294967296;
76
+ let s = t += 1831565813;
77
+ return s = Math.imul(s ^ s >>> 15, s | 1), s ^= s + Math.imul(s ^ s >>> 7, s | 61), ((s ^ s >>> 14) >>> 0) / 4294967296;
72
78
  };
73
- }, H = function(t = 0) {
79
+ }, I = function(t = 0) {
74
80
  var h;
75
- const i = Array.from({ length: 256 }, (l, s) => s), r = a(h = o, n, W).call(h, t);
76
- for (let l = 255; l > 0; l--) {
77
- const s = Math.floor(r() * (l + 1));
78
- [i[l], i[s]] = [i[s], i[l]];
81
+ const s = Array.from({ length: 256 }, (o, i) => i), e = n(h = l, r, E).call(h, t);
82
+ for (let o = 255; o > 0; o--) {
83
+ const i = Math.floor(e() * (o + 1));
84
+ [s[o], s[i]] = [s[i], s[o]];
79
85
  }
80
- return i.concat(i);
81
- }, R = function(t) {
86
+ return s.concat(s);
87
+ }, d = function(t) {
82
88
  return typeof t == "string" && t.endsWith("%");
83
- }, v = function(t, i) {
89
+ }, P = function(t, s) {
84
90
  var h;
85
- return a(h = o, n, R).call(h, t) ? parseFloat(t) / 100 * i : t;
86
- }, p = new WeakSet(), T = function(t) {
87
- const i = (s) => s * s * s * (s * (s * 6 - 15) + 10), r = (s, e, m) => e + s * (m - e), h = (s, e, m) => {
88
- const g = s & 15, f = g < 8 ? e : m, u = g < 4 ? m : g === 12 || g === 14 ? e : 0;
89
- return (g & 1 ? -f : f) + (g & 2 ? -u : u);
90
- }, l = (s, e) => s & 1 ? -e : e;
91
+ return n(h = l, r, d).call(h, t) ? parseFloat(t) / 100 * s : t;
92
+ }, f = new WeakSet(), W = function(t) {
93
+ const s = (i) => i * i * i * (i * (i * 6 - 15) + 10), e = (i, a, m) => a + i * (m - a), h = (i, a, m) => {
94
+ const g = i & 15, p = g < 8 ? a : m, u = g < 4 ? m : g === 12 || g === 14 ? a : 0;
95
+ return (g & 1 ? -p : p) + (g & 2 ? -u : u);
96
+ }, o = (i, a) => i & 1 ? -a : a;
91
97
  return {
92
98
  // Original 1D Perlin noise function
93
- perlin1(s) {
94
- const e = Math.floor(s) & 255;
95
- s -= Math.floor(s);
96
- const m = i(s);
97
- return r(m, l(t[e], s), l(t[e + 1], s - 1));
99
+ perlin1(i) {
100
+ const a = Math.floor(i) & 255;
101
+ i -= Math.floor(i);
102
+ const m = s(i);
103
+ return e(m, o(t[a], i), o(t[a + 1], i - 1));
98
104
  },
99
105
  // New 2D Perlin noise function
100
- perlin2(s, e) {
101
- const m = Math.floor(s) & 255, g = Math.floor(e) & 255;
102
- s -= Math.floor(s), e -= Math.floor(e);
103
- const f = i(s), u = i(e), d = t[m] + g, x = t[m + 1] + g, A = t[d], F = t[d + 1], y = t[x], P = t[x + 1];
104
- return r(
106
+ perlin2(i, a) {
107
+ const m = Math.floor(i) & 255, g = Math.floor(a) & 255;
108
+ i -= Math.floor(i), a -= Math.floor(a);
109
+ const p = s(i), u = s(a), R = t[m] + g, x = t[m + 1] + g, b = t[R], F = t[R + 1], y = t[x], v = t[x + 1];
110
+ return e(
105
111
  u,
106
- r(
107
- f,
108
- h(t[A], s, e),
109
- h(t[y], s - 1, e)
110
- ),
111
- r(
112
- f,
113
- h(t[F], s, e - 1),
114
- h(t[P], s - 1, e - 1)
115
- )
112
+ e(p, h(t[b], i, a), h(t[y], i - 1, a)),
113
+ e(p, h(t[F], i, a - 1), h(t[v], i - 1, a - 1))
116
114
  );
117
115
  }
118
116
  };
119
- }, $ = function(t, i, r) {
120
- return t + r * (i - t);
121
- }, L = function(t, i, r, h, l) {
122
- return (t - i) * (l - h) / (r - i) + h;
123
- }, Y(o, n);
124
- let E = o;
117
+ }, C = function(t, s, e) {
118
+ return t + e * (s - t);
119
+ }, T = function(t, s, e, h, o) {
120
+ return (t - s) * (o - h) / (e - s) + h;
121
+ }, // Quita o preserva la traslación del transform base en 2D según flag
122
+ B = function(t, s = !1) {
123
+ if (!t || t === "none") return "";
124
+ try {
125
+ const e = new DOMMatrixReadOnly(t);
126
+ if (e.is2D) {
127
+ const h = s ? e.e : 0, o = s ? e.f : 0;
128
+ return `matrix(${e.a}, ${e.b}, ${e.c}, ${e.d}, ${h}, ${o})`;
129
+ } else
130
+ return t;
131
+ } catch {
132
+ return t;
133
+ }
134
+ }, A(l, r);
135
+ let q = l;
125
136
  export {
126
- E as default
137
+ q as default
127
138
  };
@@ -1 +1 @@
1
- (function(a,t){typeof exports=="object"&&typeof module<"u"?module.exports=t():typeof define=="function"&&define.amd?define(t):(a=typeof globalThis<"u"?globalThis:a||self,a.PerlinDOM=t())})(this,function(){"use strict";var $=Object.defineProperty;var T=a=>{throw TypeError(a)};var C=(a,t,p)=>t in a?$(a,t,{enumerable:!0,configurable:!0,writable:!0,value:p}):a[t]=p;var q=(a,t,p)=>C(a,typeof t!="symbol"?t+"":t,p),D=(a,t,p)=>t.has(a)||T("Cannot "+p);var b=(a,t,p)=>t.has(a)?T("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(a):t.set(a,p);var r=(a,t,p)=>(D(a,t,"access private method"),p);var t,E,W,R,L,f,j,H,A;const o=class o{constructor({element:e,x:i=null,y:h=null,speed:l=.01,seed:c=0,lerpSpeed:s=.1}){b(this,f);q(this,"animate",()=>{var e,i,h,l,c,s,n,m,g,u,d,F;if(this.lerpFactor!==this.targetLerpFactor&&(this.lerpFactor=r(this,f,H).call(this,this.lerpFactor,this.targetLerpFactor,this.lerpSpeed),Math.abs(this.lerpFactor-this.targetLerpFactor)<.001&&(this.lerpFactor=this.targetLerpFactor)),this.lerpFactor>0){this.time+=this.speed*this.lerpFactor;const P=this.noise.perlin2(this.time,0),X=this.noise.perlin2(this.time,100);if(this.el){let y,x,v,Y;if(this.hasPercentages){const w=this.el.parentElement||document.body,B=w.clientWidth,S=w.clientHeight;this.xRange&&(y=r(e=o,t,R).call(e,this.xRange.min)?r(i=o,t,L).call(i,this.xRange.min,B):this.xRange.min,x=r(h=o,t,R).call(h,this.xRange.max)?r(l=o,t,L).call(l,this.xRange.max,B):this.xRange.max),this.yRange&&(v=r(c=o,t,R).call(c,this.yRange.min)?r(s=o,t,L).call(s,this.yRange.min,S):this.yRange.min,Y=r(n=o,t,R).call(n,this.yRange.max)?r(m=o,t,L).call(m,this.yRange.max,S):this.yRange.max)}else y=(g=this.xRange)==null?void 0:g.min,x=(u=this.xRange)==null?void 0:u.max,v=(d=this.yRange)==null?void 0:d.min,Y=(F=this.yRange)==null?void 0:F.max;const z=this.xRange?r(this,f,A).call(this,P,-1,1,y,x):0,M=this.yRange?r(this,f,A).call(this,X,-1,1,v,Y):0;this.lastX=z,this.lastY=M,this.el.style.transform=`translate3d(${z}px, ${M}px, 0)`}else{const y=this.xRange?r(this,f,A).call(this,P,-1,1,this.xRange.min,this.xRange.max):0,x=this.yRange?r(this,f,A).call(this,X,-1,1,this.yRange.min,this.yRange.max):0;this.lastX=y,this.lastY=x}}(this.lerpFactor>0||this.targetLerpFactor>0)&&(this.raf=requestAnimationFrame(this.animate))});var n,m,g,u;if(this.el=e,this.xRange=i,this.yRange=h,this.speed=l,this.time=c,this.isPlaying=!0,this.lerpFactor=1,this.lerpSpeed=s,this.targetLerpFactor=1,this.lastX=0,this.lastY=0,this.hasPercentages=!1,(i&&(r(n=o,t,R).call(n,i.min)||r(m=o,t,R).call(m,i.max))||h&&(r(g=o,t,R).call(g,h.min)||r(u=o,t,R).call(u,h.max)))&&(this.hasPercentages=!0),e){const d=window.getComputedStyle(e);d.position==="static"&&(e.style.position="relative");const F=d.transform;(!F||F==="none")&&(e.style.transform="translate3d(0px, 0px, 0px)"),this.hasPercentages&&(this.handleResize=this.handleResize.bind(this),window.addEventListener("resize",this.handleResize))}this.animate=this.animate.bind(this),this.init(c)}init(e){var i;this.noise=r(this,f,j).call(this,r(i=o,t,W).call(i,e)),this.isPlaying=!0,this.lerpFactor=1,this.targetLerpFactor=1,this.raf=requestAnimationFrame(this.animate)}handleResize(){this.hasPercentages&&this.el&&(this.needsRecalculation=!0)}pause(){this.isPlaying&&(this.targetLerpFactor=0,this.isPlaying=!1)}play(){this.isPlaying||(this.targetLerpFactor=1,this.isPlaying=!0,this.lerpFactor===0&&(this.raf=requestAnimationFrame(this.animate)))}destroy(){cancelAnimationFrame(this.raf),this.hasPercentages&&window.removeEventListener("resize",this.handleResize)}};t=new WeakSet,E=function(e){return function(){let i=e+=1831565813;return i=Math.imul(i^i>>>15,i|1),i^=i+Math.imul(i^i>>>7,i|61),((i^i>>>14)>>>0)/4294967296}},W=function(e=0){var l;const i=Array.from({length:256},(c,s)=>s),h=r(l=o,t,E).call(l,e);for(let c=255;c>0;c--){const s=Math.floor(h()*(c+1));[i[c],i[s]]=[i[s],i[c]]}return i.concat(i)},R=function(e){return typeof e=="string"&&e.endsWith("%")},L=function(e,i){var l;return r(l=o,t,R).call(l,e)?parseFloat(e)/100*i:e},f=new WeakSet,j=function(e){const i=s=>s*s*s*(s*(s*6-15)+10),h=(s,n,m)=>n+s*(m-n),l=(s,n,m)=>{const g=s&15,u=g<8?n:m,d=g<4?m:g===12||g===14?n:0;return(g&1?-u:u)+(g&2?-d:d)},c=(s,n)=>s&1?-n:n;return{perlin1(s){const n=Math.floor(s)&255;s-=Math.floor(s);const m=i(s);return h(m,c(e[n],s),c(e[n+1],s-1))},perlin2(s,n){const m=Math.floor(s)&255,g=Math.floor(n)&255;s-=Math.floor(s),n-=Math.floor(n);const u=i(s),d=i(n),F=e[m]+g,P=e[m+1]+g,X=e[F],y=e[F+1],x=e[P],v=e[P+1];return h(d,h(u,l(e[X],s,n),l(e[x],s-1,n)),h(u,l(e[y],s,n-1),l(e[v],s-1,n-1)))}}},H=function(e,i,h){return e+h*(i-e)},A=function(e,i,h,l,c){return(e-i)*(c-l)/(h-i)+l},b(o,t);let a=o;return a});
1
+ (function(h,s){typeof exports=="object"&&typeof module<"u"?module.exports=s():typeof define=="function"&&define.amd?define(s):(h=typeof globalThis<"u"?globalThis:h||self,h.PerlinDOM=s())})(this,function(){"use strict";var j=Object.defineProperty;var S=h=>{throw TypeError(h)};var C=(h,s,u)=>s in h?j(h,s,{enumerable:!0,configurable:!0,writable:!0,value:u}):h[s]=u;var q=(h,s,u)=>C(h,typeof s!="symbol"?s+"":s,u),H=(h,s,u)=>s.has(h)||S("Cannot "+u);var B=(h,s,u)=>s.has(h)?S("Cannot add the same private member more than once"):s instanceof WeakSet?s.add(h):s.set(h,u);var r=(h,s,u)=>(H(h,s,"access private method"),u);var s,D,E,R,P,g,I,W,b,X;const c=class c{constructor({element:t,x:i=null,y:n=null,speed:o=.01,seed:l=0,lerpSpeed:e=.1,preserveBaseTranslation:a=!1}){B(this,g);q(this,"animate",()=>{var t,i,n,o,l,e,a,m,f,p,d,y;if(this.lerpFactor!==this.targetLerpFactor&&(this.lerpFactor=r(this,g,W).call(this,this.lerpFactor,this.targetLerpFactor,this.lerpSpeed),Math.abs(this.lerpFactor-this.targetLerpFactor)<.001&&(this.lerpFactor=this.targetLerpFactor)),this.lerpFactor>0){this.time+=this.speed*this.lerpFactor;const T=this.noise.perlin2(this.time,0),L=this.noise.perlin2(this.time,100);if(this.el){let F,x,v,A;if(this.hasPercentages){const Y=this.el.parentElement||document.body,$=Y.clientWidth,z=Y.clientHeight;this.xRange&&(F=r(t=c,s,R).call(t,this.xRange.min)?r(i=c,s,P).call(i,this.xRange.min,$):this.xRange.min,x=r(n=c,s,R).call(n,this.xRange.max)?r(o=c,s,P).call(o,this.xRange.max,$):this.xRange.max),this.yRange&&(v=r(l=c,s,R).call(l,this.yRange.min)?r(e=c,s,P).call(e,this.yRange.min,z):this.yRange.min,A=r(a=c,s,R).call(a,this.yRange.max)?r(m=c,s,P).call(m,this.yRange.max,z):this.yRange.max)}else F=(f=this.xRange)==null?void 0:f.min,x=(p=this.xRange)==null?void 0:p.max,v=(d=this.yRange)==null?void 0:d.min,A=(y=this.yRange)==null?void 0:y.max;const w=this.xRange?r(this,g,b).call(this,T,-1,1,F,x):0,M=this.yRange?r(this,g,b).call(this,L,-1,1,v,A):0;this.lastX=w,this.lastY=M,this.el.style.transform=`translate3d(${w}px, ${M}px, 0) ${this.baseTransform}`.trim()}else{const F=this.xRange?r(this,g,b).call(this,T,-1,1,this.xRange.min,this.xRange.max):0,x=this.yRange?r(this,g,b).call(this,L,-1,1,this.yRange.min,this.yRange.max):0;this.lastX=F,this.lastY=x}}(this.lerpFactor>0||this.targetLerpFactor>0)&&(this.raf=requestAnimationFrame(this.animate))});var m,f,p,d;if(this.el=t,this.xRange=i,this.yRange=n,this.speed=o,this.time=l,this.isPlaying=!0,this.lerpFactor=1,this.lerpSpeed=e,this.targetLerpFactor=1,this.lastX=0,this.lastY=0,this.preserveBaseTranslation=a,this.hasPercentages=!!(i&&(r(m=c,s,R).call(m,i.min)||r(f=c,s,R).call(f,i.max))||n&&(r(p=c,s,R).call(p,n.min)||r(d=c,s,R).call(d,n.max))),t){const y=window.getComputedStyle(t);y.position==="static"&&(t.style.position="relative"),this.originalInlineTransform=t.style.transform||"",this.baseTransform=r(this,g,X).call(this,y.transform,this.preserveBaseTranslation),this.hasPercentages&&(this.handleResize=this.handleResize.bind(this),window.addEventListener("resize",this.handleResize))}else this.originalInlineTransform="",this.baseTransform="";this.animate=this.animate.bind(this),this.init(l)}init(t){var i;this.noise=r(this,g,I).call(this,r(i=c,s,E).call(i,t)),this.isPlaying=!0,this.lerpFactor=1,this.targetLerpFactor=1,this.raf=requestAnimationFrame(this.animate)}refreshBaseTransform(t=this.preserveBaseTranslation){if(!this.el)return;const i=window.getComputedStyle(this.el);this.baseTransform=r(this,g,X).call(this,i.transform,t)}handleResize(){}pause(){this.isPlaying&&(this.targetLerpFactor=0,this.isPlaying=!1)}play(){this.isPlaying||(this.targetLerpFactor=1,this.isPlaying=!0,this.lerpFactor===0&&(this.raf=requestAnimationFrame(this.animate)))}destroy(){cancelAnimationFrame(this.raf),this.el&&(this.el.style.transform=this.originalInlineTransform||""),this.hasPercentages&&window.removeEventListener("resize",this.handleResize)}};s=new WeakSet,D=function(t){return function(){let i=t+=1831565813;return i=Math.imul(i^i>>>15,i|1),i^=i+Math.imul(i^i>>>7,i|61),((i^i>>>14)>>>0)/4294967296}},E=function(t=0){var o;const i=Array.from({length:256},(l,e)=>e),n=r(o=c,s,D).call(o,t);for(let l=255;l>0;l--){const e=Math.floor(n()*(l+1));[i[l],i[e]]=[i[e],i[l]]}return i.concat(i)},R=function(t){return typeof t=="string"&&t.endsWith("%")},P=function(t,i){var o;return r(o=c,s,R).call(o,t)?parseFloat(t)/100*i:t},g=new WeakSet,I=function(t){const i=e=>e*e*e*(e*(e*6-15)+10),n=(e,a,m)=>a+e*(m-a),o=(e,a,m)=>{const f=e&15,p=f<8?a:m,d=f<4?m:f===12||f===14?a:0;return(f&1?-p:p)+(f&2?-d:d)},l=(e,a)=>e&1?-a:a;return{perlin1(e){const a=Math.floor(e)&255;e-=Math.floor(e);const m=i(e);return n(m,l(t[a],e),l(t[a+1],e-1))},perlin2(e,a){const m=Math.floor(e)&255,f=Math.floor(a)&255;e-=Math.floor(e),a-=Math.floor(a);const p=i(e),d=i(a),y=t[m]+f,T=t[m+1]+f,L=t[y],F=t[y+1],x=t[T],v=t[T+1];return n(d,n(p,o(t[L],e,a),o(t[x],e-1,a)),n(p,o(t[F],e,a-1),o(t[v],e-1,a-1)))}}},W=function(t,i,n){return t+n*(i-t)},b=function(t,i,n,o,l){return(t-i)*(l-o)/(n-i)+o},X=function(t,i=!1){if(!t||t==="none")return"";try{const n=new DOMMatrixReadOnly(t);if(n.is2D){const o=i?n.e:0,l=i?n.f:0;return`matrix(${n.a}, ${n.b}, ${n.c}, ${n.d}, ${o}, ${l})`}else return t}catch{return t}},B(c,s);let h=c;return h});
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@andresclua/perlindom",
3
3
  "private": false,
4
- "version": "0.0.5",
4
+ "version": "0.0.6",
5
5
  "description": "A lightweight JavaScript library for creating smooth, organic animations for DOM elements using Perlin noise",
6
6
  "type": "module",
7
7
  "main": "./dist/PerlinDOM.umd.js",
package/readme.md CHANGED
@@ -336,6 +336,7 @@ See [CHANGELOG.md](./CHANGELOG.md) for detailed version history.
336
336
 
337
337
  ### Recent Updates
338
338
 
339
+ - **v0.0.6**: Enhanced PerlinDOM to preserve design transforms
339
340
  - **v0.0.4**: Package now public on npm, enhanced module exports configuration
340
341
  - **v0.0.3**: Fixed positioning conflicts, improved automatic position detection
341
342
  - **v0.0.2**: Added percentage support and responsive animations
package/src/index.html CHANGED
@@ -62,6 +62,8 @@
62
62
  left: calc(50% - 40px);
63
63
  top: calc(50% - 40px);
64
64
  filter: blur(5px);
65
+ transform: scale(3.5) skewX(120deg);
66
+
65
67
  }
66
68
 
67
69
  /* Example 2: Horizontal Only */
@@ -1,307 +1,318 @@
1
1
  class PerlinDOM {
2
- /* ---------- helpers privados y estáticos ---------- */
3
- static #mulberry32(a) {
4
- return function () {
5
- let t = (a += 0x6d2b79f5);
6
- t = Math.imul(t ^ (t >>> 15), t | 1);
7
- t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
8
- return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
9
- };
10
- }
11
-
12
- static #generatePermutation(seed = 0) {
13
- const permutation = Array.from({ length: 256 }, (_, i) => i);
14
- const rand = PerlinDOM.#mulberry32(seed);
15
- for (let i = 255; i > 0; i--) {
16
- const j = Math.floor(rand() * (i + 1));
17
- [permutation[i], permutation[j]] = [permutation[j], permutation[i]];
18
- }
19
- return permutation.concat(permutation);
20
- }
2
+ /* ---------- helpers privados y estáticos ---------- */
3
+ static #mulberry32(a) {
4
+ return function () {
5
+ let t = (a += 0x6d2b79f5);
6
+ t = Math.imul(t ^ (t >>> 15), t | 1);
7
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
8
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
9
+ };
10
+ }
21
11
 
22
- // Helper to check if a value is a percentage string
23
- static #isPercentage(value) {
24
- return typeof value === 'string' && value.endsWith('%');
12
+ static #generatePermutation(seed = 0) {
13
+ const permutation = Array.from({ length: 256 }, (_, i) => i);
14
+ const rand = PerlinDOM.#mulberry32(seed);
15
+ for (let i = 255; i > 0; i--) {
16
+ const j = Math.floor(rand() * (i + 1));
17
+ [permutation[i], permutation[j]] = [permutation[j], permutation[i]];
25
18
  }
19
+ return permutation.concat(permutation);
20
+ }
26
21
 
27
- // Helper to convert percentage to pixels
28
- static #percentToPixels(percentage, dimension) {
29
- if (!PerlinDOM.#isPercentage(percentage)) return percentage;
30
- const value = parseFloat(percentage);
31
- return (value / 100) * dimension;
32
- }
33
-
34
- constructor({
35
- element,
36
- x = null,
37
- y = null,
38
- speed = 0.01,
39
- seed = 0,
40
- lerpSpeed = 0.1
41
- }) {
42
- this.el = element;
43
- this.xRange = x;
44
- this.yRange = y;
45
- this.speed = speed;
46
- this.time = seed;
47
- this.isPlaying = true;
48
- this.lerpFactor = 1; // 1 = full speed, 0 = paused
49
- this.lerpSpeed = lerpSpeed; // How fast to transition between play/pause states
50
- this.targetLerpFactor = 1; // Target state (1 = play, 0 = pause)
51
- this.lastX = 0;
52
- this.lastY = 0;
53
-
54
- // Check if we have percentage values
55
- this.hasPercentages = false;
56
- if (x && (PerlinDOM.#isPercentage(x.min) || PerlinDOM.#isPercentage(x.max)) ||
57
- y && (PerlinDOM.#isPercentage(y.min) || PerlinDOM.#isPercentage(y.max))) {
58
- this.hasPercentages = true;
22
+ // Helper to check if a value is a percentage string
23
+ static #isPercentage(value) {
24
+ return typeof value === 'string' && value.endsWith('%');
25
+ }
26
+
27
+ // Helper to convert percentage to pixels
28
+ static #percentToPixels(percentage, dimension) {
29
+ if (!PerlinDOM.#isPercentage(percentage)) return percentage;
30
+ const value = parseFloat(percentage);
31
+ return (value / 100) * dimension;
32
+ }
33
+
34
+ constructor({
35
+ element,
36
+ x = null,
37
+ y = null,
38
+ speed = 0.01,
39
+ seed = 0,
40
+ lerpSpeed = 0.1,
41
+ preserveBaseTranslation = false, // <-- si querés mantener la traslación base
42
+ }) {
43
+ this.el = element;
44
+ this.xRange = x;
45
+ this.yRange = y;
46
+ this.speed = speed;
47
+ this.time = seed;
48
+ this.isPlaying = true;
49
+ this.lerpFactor = 1; // 1 = full speed, 0 = paused
50
+ this.lerpSpeed = lerpSpeed; // How fast to transition between play/pause states
51
+ this.targetLerpFactor = 1; // Target state (1 = play, 0 = pause)
52
+ this.lastX = 0;
53
+ this.lastY = 0;
54
+ this.preserveBaseTranslation = preserveBaseTranslation;
55
+
56
+ // Check if we have percentage values (paréntesis para evitar precedencia ambigua)
57
+ this.hasPercentages = !!(
58
+ (x && (PerlinDOM.#isPercentage(x.min) || PerlinDOM.#isPercentage(x.max))) ||
59
+ (y && (PerlinDOM.#isPercentage(y.min) || PerlinDOM.#isPercentage(y.max)))
60
+ );
61
+
62
+ // Solo inicializar estas propiedades si el elemento no es null
63
+ if (element) {
64
+ // Ensure element has positioning for transform to work properly
65
+ const computedStyle = window.getComputedStyle(element);
66
+ if (computedStyle.position === 'static') {
67
+ element.style.position = 'relative';
59
68
  }
60
-
61
- // Solo inicializar estas propiedades si el elemento no es null
62
- if (element) {
63
- // Ensure element has positioning for transform to work properly
64
- const computedStyle = window.getComputedStyle(element);
65
- if (computedStyle.position === 'static') {
66
- element.style.position = 'relative';
67
- }
68
-
69
- // Initialize transform if it doesn't exist
70
- const currentTransform = computedStyle.transform;
71
- if (!currentTransform || currentTransform === 'none') {
72
- element.style.transform = 'translate3d(0px, 0px, 0px)';
73
- }
74
-
75
- // If using percentages, add resize listener
76
- if (this.hasPercentages) {
77
- this.handleResize = this.handleResize.bind(this);
78
- window.addEventListener('resize', this.handleResize);
79
- }
80
-
69
+
70
+ // Guardamos el transform inline original para restaurar en destroy()
71
+ this.originalInlineTransform = element.style.transform || '';
72
+
73
+ // Capturamos el transform base (quitando translate en 2D por defecto)
74
+ this.baseTransform = this.#extractBaseTransform(
75
+ computedStyle.transform,
76
+ this.preserveBaseTranslation
77
+ );
78
+
79
+ // Si usamos porcentajes, escuchamos resize
80
+ if (this.hasPercentages) {
81
+ this.handleResize = this.handleResize.bind(this);
82
+ window.addEventListener('resize', this.handleResize);
81
83
  }
82
-
83
- this.animate = this.animate.bind(this);
84
-
85
- this.init(seed);
84
+ } else {
85
+ this.originalInlineTransform = '';
86
+ this.baseTransform = '';
86
87
  }
87
-
88
+
89
+ this.animate = this.animate.bind(this);
90
+ this.init(seed);
91
+ }
92
+
88
93
  init(seed) {
89
- this.noise = this.#createPerlin(PerlinDOM.#generatePermutation(seed));
90
- this.isPlaying = true;
91
- this.lerpFactor = 1;
92
- this.targetLerpFactor = 1;
93
- this.raf = requestAnimationFrame(this.animate);
94
- }
95
-
94
+ this.noise = this.#createPerlin(PerlinDOM.#generatePermutation(seed));
95
+ this.isPlaying = true;
96
+ this.lerpFactor = 1;
97
+ this.targetLerpFactor = 1;
98
+ this.raf = requestAnimationFrame(this.animate);
99
+ }
100
+
101
+ // Permite refrescar el transform base si cambian clases/estilos en runtime
102
+ refreshBaseTransform(preserveTranslation = this.preserveBaseTranslation) {
103
+ if (!this.el) return;
104
+ const cs = window.getComputedStyle(this.el);
105
+ this.baseTransform = this.#extractBaseTransform(cs.transform, preserveTranslation);
106
+ }
107
+
96
108
  // Handle window resize for percentage-based values
97
109
  handleResize() {
98
- // Only recalculate if we're using percentages
99
- if (this.hasPercentages && this.el) {
100
- // Force a recalculation on next animation frame
101
- this.needsRecalculation = true;
102
- }
103
- }
104
-
110
+ // No necesitamos recalcular nada fuera de animate; se leen dimensiones en cada frame
111
+ // Este método queda por si querés extender la lógica (debounce, etc.).
112
+ }
113
+
105
114
  pause() {
106
- if (this.isPlaying) {
107
- this.targetLerpFactor = 0; // Target paused state
108
- this.isPlaying = false;
109
- }
115
+ if (this.isPlaying) {
116
+ this.targetLerpFactor = 0; // Target paused state
117
+ this.isPlaying = false;
110
118
  }
111
-
119
+ }
120
+
112
121
  play() {
113
- if (!this.isPlaying) {
114
- this.targetLerpFactor = 1; // Target playing state
115
- this.isPlaying = true;
116
-
117
- // Only start a new animation frame if we're completely paused
118
- if (this.lerpFactor === 0) {
119
- this.raf = requestAnimationFrame(this.animate);
120
- }
121
-
122
+ if (!this.isPlaying) {
123
+ this.targetLerpFactor = 1; // Target playing state
124
+ this.isPlaying = true;
125
+
126
+ // Solo arrancar un nuevo frame si estaba completamente pausado
127
+ if (this.lerpFactor === 0) {
128
+ this.raf = requestAnimationFrame(this.animate);
122
129
  }
123
130
  }
124
-
125
- #createPerlin(p) {
126
- const fade = t => t * t * t * (t * (t * 6 - 15) + 10);
127
- const lerp = (t, a, b) => a + t * (b - a);
128
-
129
- // Enhanced gradient function for 2D
130
- const grad2D = (hash, x, y) => {
131
- const h = hash & 15;
132
- const u = h < 8 ? x : y;
133
- const v = h < 4 ? y : (h === 12 || h === 14 ? x : 0);
134
- return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v);
135
- };
136
-
137
- // 1D gradient (kept for backward compatibility)
138
- const grad1D = (hash, x) => (hash & 1 ? -x : x);
139
-
140
- return {
141
- // Original 1D Perlin noise function
142
- perlin1(x) {
143
- const X = Math.floor(x) & 255;
144
- x -= Math.floor(x);
145
- const u = fade(x);
146
- return lerp(u, grad1D(p[X], x), grad1D(p[X + 1], x - 1));
147
- },
148
-
149
- // New 2D Perlin noise function
150
- perlin2(x, y) {
151
- // Integer parts of coordinates
152
- const X = Math.floor(x) & 255;
153
- const Y = Math.floor(y) & 255;
154
-
155
- // Fractional parts of coordinates
156
- x -= Math.floor(x);
157
- y -= Math.floor(y);
158
-
159
- // Fade curves for x and y
160
- const u = fade(x);
161
- const v = fade(y);
162
-
163
- // Hash coordinates of the 4 square corners
164
- const A = p[X] + Y;
165
- const B = p[X + 1] + Y;
166
- const AA = p[A];
167
- const AB = p[A + 1];
168
- const BA = p[B];
169
- const BB = p[B + 1];
170
-
171
- // Blend the four corner gradients
172
- return lerp(
173
- v,
174
- lerp(
175
- u,
176
- grad2D(p[AA], x, y),
177
- grad2D(p[BA], x - 1, y)
178
- ),
179
- lerp(
180
- u,
181
- grad2D(p[AB], x, y - 1),
182
- grad2D(p[BB], x - 1, y - 1)
183
- )
184
- );
185
- }
186
- };
187
- }
188
-
189
- #lerp(a, b, t) {
190
- return a + t * (b - a);
191
- }
192
-
193
- animate = () => {
194
- // Update lerp factor towards target
195
- if (this.lerpFactor !== this.targetLerpFactor) {
196
- this.lerpFactor = this.#lerp(
197
- this.lerpFactor,
198
- this.targetLerpFactor,
199
- this.lerpSpeed
131
+ }
132
+
133
+ #createPerlin(p) {
134
+ const fade = t => t * t * t * (t * (t * 6 - 15) + 10);
135
+ const lerp = (t, a, b) => a + t * (b - a);
136
+
137
+ // Enhanced gradient function for 2D
138
+ const grad2D = (hash, x, y) => {
139
+ const h = hash & 15;
140
+ const u = h < 8 ? x : y;
141
+ const v = h < 4 ? y : (h === 12 || h === 14 ? x : 0);
142
+ return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v);
143
+ };
144
+
145
+ // 1D gradient (kept for backward compatibility)
146
+ const grad1D = (hash, x) => (hash & 1 ? -x : x);
147
+
148
+ return {
149
+ // Original 1D Perlin noise function
150
+ perlin1(x) {
151
+ const X = Math.floor(x) & 255;
152
+ x -= Math.floor(x);
153
+ const u = fade(x);
154
+ return lerp(u, grad1D(p[X], x), grad1D(p[X + 1], x - 1));
155
+ },
156
+
157
+ // New 2D Perlin noise function
158
+ perlin2(x, y) {
159
+ // Integer parts
160
+ const X = Math.floor(x) & 255;
161
+ const Y = Math.floor(y) & 255;
162
+
163
+ // Fractional parts
164
+ x -= Math.floor(x);
165
+ y -= Math.floor(y);
166
+
167
+ // Fade curves
168
+ const u = fade(x);
169
+ const v = fade(y);
170
+
171
+ // Hash coordinates of the 4 corners
172
+ const A = p[X] + Y;
173
+ const B = p[X + 1] + Y;
174
+ const AA = p[A];
175
+ const AB = p[A + 1];
176
+ const BA = p[B];
177
+ const BB = p[B + 1];
178
+
179
+ // Blend the four corner gradients
180
+ return lerp(
181
+ v,
182
+ lerp(u, grad2D(p[AA], x, y), grad2D(p[BA], x - 1, y)),
183
+ lerp(u, grad2D(p[AB], x, y - 1), grad2D(p[BB], x - 1, y - 1))
200
184
  );
201
-
202
- // Snap to target if very close
203
- if (Math.abs(this.lerpFactor - this.targetLerpFactor) < 0.001) {
204
- this.lerpFactor = this.targetLerpFactor;
205
- }
206
185
  }
207
-
208
- // Only update time if not completely paused
209
- if (this.lerpFactor > 0) {
210
- // Scale time increment by lerp factor for smooth speed transition
211
- this.time += this.speed * this.lerpFactor;
212
-
213
- // Use 2D Perlin noise for more natural movement
214
- // We use time for one dimension and a fixed offset for the other
215
- // This creates a path through the 2D noise field
216
- const noiseX = this.noise.perlin2(this.time, 0);
217
- const noiseY = this.noise.perlin2(this.time, 100); // Different slice of the noise field
218
-
219
- // Only process if we have an element
220
- if (this.el) {
221
- let minX, maxX, minY, maxY;
222
-
223
- // Get parent dimensions for percentage calculations if needed
224
- if (this.hasPercentages) {
225
- const parent = this.el.parentElement || document.body;
226
- const parentWidth = parent.clientWidth;
227
- const parentHeight = parent.clientHeight;
228
-
229
- // Convert percentage values to pixels if needed
230
- if (this.xRange) {
231
- minX = PerlinDOM.#isPercentage(this.xRange.min)
232
- ? PerlinDOM.#percentToPixels(this.xRange.min, parentWidth)
233
- : this.xRange.min;
234
-
235
- maxX = PerlinDOM.#isPercentage(this.xRange.max)
236
- ? PerlinDOM.#percentToPixels(this.xRange.max, parentWidth)
237
- : this.xRange.max;
238
- }
239
-
240
- if (this.yRange) {
241
- minY = PerlinDOM.#isPercentage(this.yRange.min)
242
- ? PerlinDOM.#percentToPixels(this.yRange.min, parentHeight)
243
- : this.yRange.min;
244
-
245
- maxY = PerlinDOM.#isPercentage(this.yRange.max)
246
- ? PerlinDOM.#percentToPixels(this.yRange.max, parentHeight)
247
- : this.yRange.max;
248
- }
249
- } else {
250
- // Use the original values if not using percentages
251
- minX = this.xRange?.min;
252
- maxX = this.xRange?.max;
253
- minY = this.yRange?.min;
254
- maxY = this.yRange?.max;
186
+ };
187
+ }
188
+
189
+ #lerp(a, b, t) {
190
+ return a + t * (b - a);
191
+ }
192
+
193
+ animate = () => {
194
+ // Update lerp factor towards target
195
+ if (this.lerpFactor !== this.targetLerpFactor) {
196
+ this.lerpFactor = this.#lerp(this.lerpFactor, this.targetLerpFactor, this.lerpSpeed);
197
+
198
+ // Snap to target if very close
199
+ if (Math.abs(this.lerpFactor - this.targetLerpFactor) < 0.001) {
200
+ this.lerpFactor = this.targetLerpFactor;
201
+ }
202
+ }
203
+
204
+ // Only update time if not completely paused
205
+ if (this.lerpFactor > 0) {
206
+ // Scale time increment by lerp factor for smooth speed transition
207
+ this.time += this.speed * this.lerpFactor;
208
+
209
+ // 2D Perlin noise for more natural movement
210
+ const noiseX = this.noise.perlin2(this.time, 0);
211
+ const noiseY = this.noise.perlin2(this.time, 100); // Different slice
212
+
213
+ // Only process if we have an element
214
+ if (this.el) {
215
+ let minX, maxX, minY, maxY;
216
+
217
+ // Get parent dimensions for percentage calculations if needed
218
+ if (this.hasPercentages) {
219
+ const parent = this.el.parentElement || document.body;
220
+ const parentWidth = parent.clientWidth;
221
+ const parentHeight = parent.clientHeight;
222
+
223
+ // Convert percentage values to pixels if needed
224
+ if (this.xRange) {
225
+ minX = PerlinDOM.#isPercentage(this.xRange.min)
226
+ ? PerlinDOM.#percentToPixels(this.xRange.min, parentWidth)
227
+ : this.xRange.min;
228
+
229
+ maxX = PerlinDOM.#isPercentage(this.xRange.max)
230
+ ? PerlinDOM.#percentToPixels(this.xRange.max, parentWidth)
231
+ : this.xRange.max;
232
+ }
233
+
234
+ if (this.yRange) {
235
+ minY = PerlinDOM.#isPercentage(this.yRange.min)
236
+ ? PerlinDOM.#percentToPixels(this.yRange.min, parentHeight)
237
+ : this.yRange.min;
238
+
239
+ maxY = PerlinDOM.#isPercentage(this.yRange.max)
240
+ ? PerlinDOM.#percentToPixels(this.yRange.max, parentHeight)
241
+ : this.yRange.max;
255
242
  }
256
-
257
- // Calculate the actual pixel values
258
- const valX = this.xRange
259
- ? this.#map(noiseX, -1, 1, minX, maxX)
260
- : 0;
261
-
262
- const valY = this.yRange
263
- ? this.#map(noiseY, -1, 1, minY, maxY)
264
- : 0;
265
-
266
- // Store current values for interpolation
267
- this.lastX = valX;
268
- this.lastY = valY;
269
-
270
- // Update position using transform for better performance
271
- this.el.style.transform = `translate3d(${valX}px, ${valY}px, 0)`;
272
243
  } else {
273
- // If no element, just calculate and store the values
274
- const valX = this.xRange
275
- ? this.#map(noiseX, -1, 1, this.xRange.min, this.xRange.max)
276
- : 0;
277
-
278
- const valY = this.yRange
279
- ? this.#map(noiseY, -1, 1, this.yRange.min, this.yRange.max)
280
- : 0;
281
-
282
- // Store current values for interpolation
283
- this.lastX = valX;
284
- this.lastY = valY;
244
+ // Use original values if not using percentages
245
+ minX = this.xRange?.min;
246
+ maxX = this.xRange?.max;
247
+ minY = this.yRange?.min;
248
+ maxY = this.yRange?.max;
285
249
  }
250
+
251
+ // Calculate pixel values
252
+ const valX = this.xRange ? this.#map(noiseX, -1, 1, minX, maxX) : 0;
253
+ const valY = this.yRange ? this.#map(noiseY, -1, 1, minY, maxY) : 0;
254
+
255
+ // Store current values for potential external use
256
+ this.lastX = valX;
257
+ this.lastY = valY;
258
+
259
+ // Compose translate3d with the base transform (scale/rotate/skew)
260
+ // Orden: primero translate (nuestro movimiento), luego el transform base del diseño
261
+ this.el.style.transform = `translate3d(${valX}px, ${valY}px, 0) ${this.baseTransform}`.trim();
262
+ } else {
263
+ // If no element, just calculate and store the values
264
+ const valX = this.xRange ? this.#map(noiseX, -1, 1, this.xRange.min, this.xRange.max) : 0;
265
+ const valY = this.yRange ? this.#map(noiseY, -1, 1, this.yRange.min, this.yRange.max) : 0;
266
+
267
+ this.lastX = valX;
268
+ this.lastY = valY;
286
269
  }
287
-
288
- // Continue animation if not completely paused or still transitioning
289
- if (this.lerpFactor > 0 || this.targetLerpFactor > 0) {
290
- this.raf = requestAnimationFrame(this.animate);
291
- }
292
- };
293
-
294
- #map(n, inMin, inMax, outMin, outMax) {
295
- return ((n - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
296
270
  }
297
-
298
- destroy() {
299
- cancelAnimationFrame(this.raf);
300
-
301
- // Remove resize listener if it was added
302
- if (this.hasPercentages) {
303
- window.removeEventListener('resize', this.handleResize);
271
+
272
+ // Continue animation if not completely paused or still transitioning
273
+ if (this.lerpFactor > 0 || this.targetLerpFactor > 0) {
274
+ this.raf = requestAnimationFrame(this.animate);
275
+ }
276
+ };
277
+
278
+ #map(n, inMin, inMax, outMin, outMax) {
279
+ return ((n - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
280
+ }
281
+
282
+ // Quita o preserva la traslación del transform base en 2D según flag
283
+ #extractBaseTransform(transformValue, preserveTranslation = false) {
284
+ if (!transformValue || transformValue === 'none') return '';
285
+
286
+ try {
287
+ const m = new DOMMatrixReadOnly(transformValue);
288
+ if (m.is2D) {
289
+ // matrix(a, b, c, d, e, f) -> rearmamos con e,f = 0 si NO preservamos traslación
290
+ const e = preserveTranslation ? m.e : 0;
291
+ const f = preserveTranslation ? m.f : 0;
292
+ return `matrix(${m.a}, ${m.b}, ${m.c}, ${m.d}, ${e}, ${f})`;
293
+ } else {
294
+ // 3D: lo dejamos tal cual (remover traslación en 3D requiere descomposición)
295
+ return transformValue;
304
296
  }
297
+ } catch {
298
+ // Fallback si DOMMatrix no está disponible o hay un valor raro
299
+ return transformValue;
300
+ }
301
+ }
302
+
303
+ destroy() {
304
+ cancelAnimationFrame(this.raf);
305
+
306
+ // Restaurar transform inline original
307
+ if (this.el) {
308
+ this.el.style.transform = this.originalInlineTransform || '';
309
+ }
310
+
311
+ // Remove resize listener if it was added
312
+ if (this.hasPercentages) {
313
+ window.removeEventListener('resize', this.handleResize);
305
314
  }
306
315
  }
307
- export default PerlinDOM;
316
+ }
317
+
318
+ export default PerlinDOM;