use-scroll-animate 4.7.0 → 4.8.0
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 +10 -0
- package/README.md +1 -1
- package/README_ja.md +1 -1
- package/README_zh.md +1 -1
- package/dist/chunks/{index-tags-BQh_uGqH.cjs → index-tags-CIRY2KnU.cjs} +2 -2
- package/dist/chunks/{index-tags-BQh_uGqH.cjs.map → index-tags-CIRY2KnU.cjs.map} +1 -1
- package/dist/chunks/{index-tags-43Xtd01A.js → index-tags-Dh8nwXqw.js} +2 -2
- package/dist/chunks/{index-tags-43Xtd01A.js.map → index-tags-Dh8nwXqw.js.map} +1 -1
- package/dist/components/a11y.cjs +1 -1
- package/dist/components/a11y.d.cts +1 -1
- package/dist/components/a11y.d.ts +1 -1
- package/dist/components/a11y.js +1 -1
- package/dist/components/angular.cjs +1 -1
- package/dist/components/angular.d.cts +2 -1
- package/dist/components/angular.d.ts +2 -1
- package/dist/components/angular.js +1 -1
- package/dist/components/jsx.d.cts +1 -1
- package/dist/components/jsx.d.ts +1 -1
- package/dist/components/lazy.cjs +1 -1
- package/dist/components/lazy.d.cts +1 -1
- package/dist/components/lazy.d.ts +1 -1
- package/dist/components/lazy.js +1 -1
- package/dist/components/lite.cjs +184 -10
- package/dist/components/lite.cjs.map +1 -1
- package/dist/components/lite.js +177 -11
- package/dist/components/lite.js.map +1 -1
- package/dist/components/perf.cjs +1 -1
- package/dist/components/perf.d.cts +1 -1
- package/dist/components/perf.d.ts +1 -1
- package/dist/components/perf.js +1 -1
- package/dist/components/react.cjs +1 -1
- package/dist/components/react.js +1 -1
- package/dist/components/solid.cjs +1 -1
- package/dist/components/solid.d.cts +2 -1
- package/dist/components/solid.d.ts +2 -1
- package/dist/components/solid.js +1 -1
- package/dist/components/svelte.cjs +1 -1
- package/dist/components/svelte.d.cts +2 -1
- package/dist/components/svelte.d.ts +2 -1
- package/dist/components/svelte.js +1 -1
- package/dist/components/vue.cjs +1 -1
- package/dist/components/vue.d.cts +2 -1
- package/dist/components/vue.d.ts +2 -1
- package/dist/components/vue.js +1 -1
- package/dist/components/webgl.cjs +184 -10
- package/dist/components/webgl.cjs.map +1 -1
- package/dist/components/webgl.css +1 -1
- package/dist/components/webgl.d.cts +59 -5
- package/dist/components/webgl.d.ts +59 -5
- package/dist/components/webgl.js +178 -12
- package/dist/components/webgl.js.map +1 -1
- package/dist/components.cjs +9 -1
- package/dist/components.cjs.map +1 -1
- package/dist/components.css +1 -1
- package/dist/components.d.cts +60 -6
- package/dist/components.d.ts +60 -6
- package/dist/components.js +2 -2
- package/dist/components.umd.js +2 -2
- package/dist/components.umd.js.map +1 -1
- package/docs/ROADMAP.md +1 -1
- package/docs/components.md +7 -0
- package/package.json +1 -1
package/dist/components/perf.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var base = require('../chunks/base-CxYU2NK_.cjs');
|
|
4
|
-
var indexTags = require('../chunks/index-tags-
|
|
4
|
+
var indexTags = require('../chunks/index-tags-CIRY2KnU.cjs');
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* use-scroll-animate/components/perf — performance toolkit (4.5).
|
|
@@ -31,7 +31,7 @@ declare const COMPONENT_CATEGORIES: {
|
|
|
31
31
|
readonly timeline: readonly ["usa-timeline"];
|
|
32
32
|
readonly gesture: readonly ["usa-swipeable", "usa-pinch-zoom"];
|
|
33
33
|
readonly svg: readonly ["usa-draw", "usa-morph", "usa-mask-reveal", "usa-anim-icon"];
|
|
34
|
-
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid"];
|
|
34
|
+
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid", "usa-post-fx"];
|
|
35
35
|
readonly depth: readonly ["usa-cube", "usa-depth"];
|
|
36
36
|
readonly layout: readonly ["usa-auto-animate", "usa-masonry"];
|
|
37
37
|
readonly packs: readonly ["usa-pack"];
|
|
@@ -31,7 +31,7 @@ declare const COMPONENT_CATEGORIES: {
|
|
|
31
31
|
readonly timeline: readonly ["usa-timeline"];
|
|
32
32
|
readonly gesture: readonly ["usa-swipeable", "usa-pinch-zoom"];
|
|
33
33
|
readonly svg: readonly ["usa-draw", "usa-morph", "usa-mask-reveal", "usa-anim-icon"];
|
|
34
|
-
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid"];
|
|
34
|
+
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid", "usa-post-fx"];
|
|
35
35
|
readonly depth: readonly ["usa-cube", "usa-depth"];
|
|
36
36
|
readonly layout: readonly ["usa-auto-animate", "usa-masonry"];
|
|
37
37
|
readonly packs: readonly ["usa-pack"];
|
package/dist/components/perf.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { o as onFrame, t as setStyleLoader, e as animationBudget, g as getMotionIntensity, f as configureComponents, i as setAnimationBudget, b as activeAnimations } from '../chunks/base-CZiIAMBc.js';
|
|
2
2
|
export { s as schedulerStats } from '../chunks/base-CZiIAMBc.js';
|
|
3
|
-
import { C as COMPONENT_CATEGORIES } from '../chunks/index-tags-
|
|
3
|
+
import { C as COMPONENT_CATEGORIES } from '../chunks/index-tags-Dh8nwXqw.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* use-scroll-animate/components/perf — performance toolkit (4.5).
|
package/dist/components/react.js
CHANGED
|
@@ -1522,6 +1522,7 @@ declare global {
|
|
|
1522
1522
|
'usa-shader': UsaGLElement;
|
|
1523
1523
|
'usa-distort': UsaGLElement;
|
|
1524
1524
|
'usa-liquid': UsaGLElement;
|
|
1525
|
+
'usa-post-fx': UsaGLElement;
|
|
1525
1526
|
}
|
|
1526
1527
|
}
|
|
1527
1528
|
|
|
@@ -1645,7 +1646,7 @@ declare const COMPONENT_CATEGORIES: {
|
|
|
1645
1646
|
readonly timeline: readonly ["usa-timeline"];
|
|
1646
1647
|
readonly gesture: readonly ["usa-swipeable", "usa-pinch-zoom"];
|
|
1647
1648
|
readonly svg: readonly ["usa-draw", "usa-morph", "usa-mask-reveal", "usa-anim-icon"];
|
|
1648
|
-
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid"];
|
|
1649
|
+
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid", "usa-post-fx"];
|
|
1649
1650
|
readonly depth: readonly ["usa-cube", "usa-depth"];
|
|
1650
1651
|
readonly layout: readonly ["usa-auto-animate", "usa-masonry"];
|
|
1651
1652
|
readonly packs: readonly ["usa-pack"];
|
|
@@ -1522,6 +1522,7 @@ declare global {
|
|
|
1522
1522
|
'usa-shader': UsaGLElement;
|
|
1523
1523
|
'usa-distort': UsaGLElement;
|
|
1524
1524
|
'usa-liquid': UsaGLElement;
|
|
1525
|
+
'usa-post-fx': UsaGLElement;
|
|
1525
1526
|
}
|
|
1526
1527
|
}
|
|
1527
1528
|
|
|
@@ -1645,7 +1646,7 @@ declare const COMPONENT_CATEGORIES: {
|
|
|
1645
1646
|
readonly timeline: readonly ["usa-timeline"];
|
|
1646
1647
|
readonly gesture: readonly ["usa-swipeable", "usa-pinch-zoom"];
|
|
1647
1648
|
readonly svg: readonly ["usa-draw", "usa-morph", "usa-mask-reveal", "usa-anim-icon"];
|
|
1648
|
-
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid"];
|
|
1649
|
+
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid", "usa-post-fx"];
|
|
1649
1650
|
readonly depth: readonly ["usa-cube", "usa-depth"];
|
|
1650
1651
|
readonly layout: readonly ["usa-auto-animate", "usa-masonry"];
|
|
1651
1652
|
readonly packs: readonly ["usa-pack"];
|
package/dist/components/solid.js
CHANGED
|
@@ -1522,6 +1522,7 @@ declare global {
|
|
|
1522
1522
|
'usa-shader': UsaGLElement;
|
|
1523
1523
|
'usa-distort': UsaGLElement;
|
|
1524
1524
|
'usa-liquid': UsaGLElement;
|
|
1525
|
+
'usa-post-fx': UsaGLElement;
|
|
1525
1526
|
}
|
|
1526
1527
|
}
|
|
1527
1528
|
|
|
@@ -1645,7 +1646,7 @@ declare const COMPONENT_CATEGORIES: {
|
|
|
1645
1646
|
readonly timeline: readonly ["usa-timeline"];
|
|
1646
1647
|
readonly gesture: readonly ["usa-swipeable", "usa-pinch-zoom"];
|
|
1647
1648
|
readonly svg: readonly ["usa-draw", "usa-morph", "usa-mask-reveal", "usa-anim-icon"];
|
|
1648
|
-
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid"];
|
|
1649
|
+
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid", "usa-post-fx"];
|
|
1649
1650
|
readonly depth: readonly ["usa-cube", "usa-depth"];
|
|
1650
1651
|
readonly layout: readonly ["usa-auto-animate", "usa-masonry"];
|
|
1651
1652
|
readonly packs: readonly ["usa-pack"];
|
|
@@ -1522,6 +1522,7 @@ declare global {
|
|
|
1522
1522
|
'usa-shader': UsaGLElement;
|
|
1523
1523
|
'usa-distort': UsaGLElement;
|
|
1524
1524
|
'usa-liquid': UsaGLElement;
|
|
1525
|
+
'usa-post-fx': UsaGLElement;
|
|
1525
1526
|
}
|
|
1526
1527
|
}
|
|
1527
1528
|
|
|
@@ -1645,7 +1646,7 @@ declare const COMPONENT_CATEGORIES: {
|
|
|
1645
1646
|
readonly timeline: readonly ["usa-timeline"];
|
|
1646
1647
|
readonly gesture: readonly ["usa-swipeable", "usa-pinch-zoom"];
|
|
1647
1648
|
readonly svg: readonly ["usa-draw", "usa-morph", "usa-mask-reveal", "usa-anim-icon"];
|
|
1648
|
-
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid"];
|
|
1649
|
+
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid", "usa-post-fx"];
|
|
1649
1650
|
readonly depth: readonly ["usa-cube", "usa-depth"];
|
|
1650
1651
|
readonly layout: readonly ["usa-auto-animate", "usa-masonry"];
|
|
1651
1652
|
readonly packs: readonly ["usa-pack"];
|
package/dist/components/vue.cjs
CHANGED
|
@@ -1522,6 +1522,7 @@ declare global {
|
|
|
1522
1522
|
'usa-shader': UsaGLElement;
|
|
1523
1523
|
'usa-distort': UsaGLElement;
|
|
1524
1524
|
'usa-liquid': UsaGLElement;
|
|
1525
|
+
'usa-post-fx': UsaGLElement;
|
|
1525
1526
|
}
|
|
1526
1527
|
}
|
|
1527
1528
|
|
|
@@ -1645,7 +1646,7 @@ declare const COMPONENT_CATEGORIES: {
|
|
|
1645
1646
|
readonly timeline: readonly ["usa-timeline"];
|
|
1646
1647
|
readonly gesture: readonly ["usa-swipeable", "usa-pinch-zoom"];
|
|
1647
1648
|
readonly svg: readonly ["usa-draw", "usa-morph", "usa-mask-reveal", "usa-anim-icon"];
|
|
1648
|
-
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid"];
|
|
1649
|
+
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid", "usa-post-fx"];
|
|
1649
1650
|
readonly depth: readonly ["usa-cube", "usa-depth"];
|
|
1650
1651
|
readonly layout: readonly ["usa-auto-animate", "usa-masonry"];
|
|
1651
1652
|
readonly packs: readonly ["usa-pack"];
|
package/dist/components/vue.d.ts
CHANGED
|
@@ -1522,6 +1522,7 @@ declare global {
|
|
|
1522
1522
|
'usa-shader': UsaGLElement;
|
|
1523
1523
|
'usa-distort': UsaGLElement;
|
|
1524
1524
|
'usa-liquid': UsaGLElement;
|
|
1525
|
+
'usa-post-fx': UsaGLElement;
|
|
1525
1526
|
}
|
|
1526
1527
|
}
|
|
1527
1528
|
|
|
@@ -1645,7 +1646,7 @@ declare const COMPONENT_CATEGORIES: {
|
|
|
1645
1646
|
readonly timeline: readonly ["usa-timeline"];
|
|
1646
1647
|
readonly gesture: readonly ["usa-swipeable", "usa-pinch-zoom"];
|
|
1647
1648
|
readonly svg: readonly ["usa-draw", "usa-morph", "usa-mask-reveal", "usa-anim-icon"];
|
|
1648
|
-
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid"];
|
|
1649
|
+
readonly webgl: readonly ["usa-shader", "usa-distort", "usa-liquid", "usa-post-fx"];
|
|
1649
1650
|
readonly depth: readonly ["usa-cube", "usa-depth"];
|
|
1650
1651
|
readonly layout: readonly ["usa-auto-animate", "usa-masonry"];
|
|
1651
1652
|
readonly packs: readonly ["usa-pack"];
|
package/dist/components/vue.js
CHANGED
|
@@ -12,6 +12,12 @@ const SHADERS = {
|
|
|
12
12
|
waves: 'void main(){vec2 u=v_uv;float t=u_time*.4;float w=0.;for(int i=0;i<4;i++){float f=float(i)+1.;w+=sin(u.x*6.*f+t*f)*.08/f;}float l=smoothstep(.0,.02,abs(u.y-.5-w));vec3 col=mix(vec3(.2,.5,1.),vec3(.04,.06,.15),l)+vec3(.1,.0,.2)*u.y;gl_FragColor=vec4(col,1.);}',
|
|
13
13
|
aurora: 'void main(){vec2 u=v_uv;float t=u_time*.2;float b=0.;for(int i=0;i<3;i++){float f=float(i);b+=.4/abs((u.y-.6+.15*sin(u.x*3.+t+f*1.7))*(8.+f*4.));}vec3 col=vec3(.02,.03,.08)+b*mix(vec3(.1,.9,.6),vec3(.6,.3,1.),u.x)*.35;gl_FragColor=vec4(col,1.);}',
|
|
14
14
|
distort: 'void main(){vec2 u=v_uv;vec2 d=u-u_mouse;float r=length(d);float k=u_hover*.08*exp(-r*r*18.);u-=normalize(d+1e-4)*k;float s=u_hover*.006;vec3 col=vec3(texture2D(u_tex,u+vec2(s,0.)).r,texture2D(u_tex,u).g,texture2D(u_tex,u-vec2(s,0.)).b);gl_FragColor=vec4(col,1.);}',
|
|
15
|
+
// 4.8 particle presets (procedural, one quad: no buffers, no per-particle JS)
|
|
16
|
+
snow: 'float h(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}void main(){vec2 u=v_uv;u.x*=u_resolution.x/max(u_resolution.y,1.);vec3 col=mix(vec3(.05,.08,.16),vec3(.12,.16,.3),v_uv.y);for(int l=0;l<3;l++){float s=8.+float(l)*7.;vec2 q=u*s;q.y+=u_time*(.6+float(l)*.35);q.x+=sin(q.y*.7+float(l))*.3;vec2 id=floor(q);vec2 f=fract(q)-.5;float r=h(id);if(r>.6){vec2 o=vec2(h(id+3.)-.5,h(id+7.)-.5)*.6;float d=length(f-o);col+=smoothstep(.09-float(l)*.02,0.,d)*(.5+.5*r);}}gl_FragColor=vec4(col,1.);}',
|
|
17
|
+
fireflies: 'float h(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}void main(){vec2 u=v_uv;u.x*=u_resolution.x/max(u_resolution.y,1.);vec3 col=vec3(.02,.04,.03);for(int l=0;l<2;l++){vec2 q=u*(5.+float(l)*4.);vec2 id=floor(q);vec2 f=fract(q)-.5;float r=h(id+float(l)*13.);vec2 o=.35*vec2(sin(u_time*(.4+r)+r*6.28),cos(u_time*(.3+r)+r*12.));float d=length(f-o);float tw=.5+.5*sin(u_time*3.*r+r*20.);col+=vec3(1.,.85,.3)*smoothstep(.12,0.,d)*tw*step(.45,r);}gl_FragColor=vec4(col,1.);}',
|
|
18
|
+
stars: 'float h(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}void main(){vec2 c=v_uv-.5;c.x*=u_resolution.x/max(u_resolution.y,1.);vec3 col=vec3(.01,.01,.04);for(int l=0;l<4;l++){float z=fract(float(l)*.25+u_time*.05);float sc=mix(20.,.5,z);vec2 q=c*sc+float(l)*7.;vec2 id=floor(q);vec2 f=fract(q)-.5;float r=h(id);float d=length(f-(vec2(h(id+1.),h(id+2.))-.5)*.7);col+=vec3(.8,.9,1.)*smoothstep(.06,0.,d)*step(.8,r)*smoothstep(0.,.5,z)*smoothstep(1.,.8,z)*2.;}gl_FragColor=vec4(col,1.);}',
|
|
19
|
+
bokeh: 'float h(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453);}void main(){vec2 u=v_uv;u.x*=u_resolution.x/max(u_resolution.y,1.);vec3 col=mix(vec3(.08,.03,.12),vec3(.02,.05,.12),v_uv.y);for(int l=0;l<3;l++){vec2 q=u*(2.5+float(l)*1.5);q.y-=u_time*.05*(1.+float(l));vec2 id=floor(q);vec2 f=fract(q)-.5;float r=h(id+float(l)*5.);float d=length(f-(vec2(h(id+4.),h(id+9.))-.5)*.5);vec3 tint=.5+.5*cos(r*6.28+vec3(0.,2.,4.));col+=tint*smoothstep(.3,.26,d)*.18*step(.35,r);}gl_FragColor=vec4(col,1.);}',
|
|
20
|
+
rain: 'float h(float n){return fract(sin(n)*43758.5453);}void main(){vec2 u=v_uv;vec3 col=mix(vec3(.04,.06,.1),vec3(.1,.13,.2),u.y);float n=floor(u.x*120.);float sp=.8+h(n)*1.2;float y=fract(u.y+u_time*sp+h(n+1.));float drop=smoothstep(.0,.08,y)*smoothstep(.16,.08,y)*step(.7,h(n+2.));col+=vec3(.5,.6,.8)*drop*.6;gl_FragColor=vec4(col,1.);}',
|
|
15
21
|
liquid: 'void main(){vec2 u=v_uv;vec2 o=vec2(0.);for(int i=0;i<4;i++){vec4 r=u_ripples[i];if(r.w>0.){float d=distance(u,r.xy);float w=sin(d*60.-r.z*12.)*exp(-d*6.)*exp(-r.z*1.6)*r.w*.02;o+=normalize(u-r.xy+1e-4)*w;}}o+=vec2(sin(u.y*10.+u_time),cos(u.x*10.+u_time))*.002*u_hover;gl_FragColor=texture2D(u_tex,u+o);}',
|
|
16
22
|
};
|
|
17
23
|
/** Full fragment source for a preset or custom body (adds the shared header). */
|
|
@@ -71,9 +77,10 @@ function glQuad(canvas, frag) {
|
|
|
71
77
|
const U = (n) => g.getUniformLocation(prog, n);
|
|
72
78
|
const uT = U('u_time'), uR = U('u_resolution'), uM = U('u_mouse'), uH = U('u_hover'), uRp = U('u_ripples');
|
|
73
79
|
let tex = null;
|
|
80
|
+
const extraLoc = {};
|
|
74
81
|
const quad = {
|
|
75
|
-
resize() {
|
|
76
|
-
const dpr = Math.min(2, (typeof devicePixelRatio === 'number' && devicePixelRatio) || 1);
|
|
82
|
+
resize(scale = 1) {
|
|
83
|
+
const dpr = Math.min(2, (typeof devicePixelRatio === 'number' && devicePixelRatio) || 1) * Math.min(1, Math.max(0.25, scale));
|
|
77
84
|
const w = Math.max(1, Math.round((canvas.clientWidth || 300) * dpr));
|
|
78
85
|
const h = Math.max(1, Math.round((canvas.clientHeight || 150) * dpr));
|
|
79
86
|
if (canvas.width !== w || canvas.height !== h)
|
|
@@ -96,6 +103,9 @@ function glQuad(canvas, frag) {
|
|
|
96
103
|
g.uniform1f(uH, u.hover ?? 0);
|
|
97
104
|
if (uRp)
|
|
98
105
|
g.uniform4fv(uRp, new Float32Array((u.ripples ?? []).concat(Array(16).fill(0)).slice(0, 16)));
|
|
106
|
+
if (u.extra)
|
|
107
|
+
for (const [k, v] of Object.entries(u.extra))
|
|
108
|
+
g.uniform1f((extraLoc[k] ?? (extraLoc[k] = U(k))), v);
|
|
99
109
|
g.drawArrays(g.TRIANGLES, 0, 6);
|
|
100
110
|
},
|
|
101
111
|
dispose() {
|
|
@@ -110,7 +120,132 @@ function glQuad(canvas, frag) {
|
|
|
110
120
|
return quad;
|
|
111
121
|
}
|
|
112
122
|
|
|
113
|
-
|
|
123
|
+
/**
|
|
124
|
+
* 4.8 — WebGL preset library on `glQuad()`: particle presets (`snow`,
|
|
125
|
+
* `fireflies`, `stars`, `bokeh`, `rain` — usable as `<usa-shader preset>`),
|
|
126
|
+
* chainable post-processing passes for images (`<usa-post-fx>`), one CSS
|
|
127
|
+
* fallback per preset, and an adaptive quality governor (fps + battery).
|
|
128
|
+
*/
|
|
129
|
+
const PARTICLE_PRESETS = ['snow', 'fireflies', 'stars', 'bokeh', 'rain'];
|
|
130
|
+
/** Post-processing passes: `vec3 fx(vec3 c, vec2 uv)` bodies, applied in order. `u_intensity` 0–1. */
|
|
131
|
+
const POST_EFFECTS = {
|
|
132
|
+
vignette: 'c*=mix(1.,smoothstep(.85,.25,length(uv-.5)),u_intensity);',
|
|
133
|
+
grain: 'c+=(fract(sin(dot(uv*u_resolution+u_time,vec2(12.9898,78.233)))*43758.5453)-.5)*.18*u_intensity;',
|
|
134
|
+
chromatic: 'float s=.008*u_intensity;c=vec3(texture2D(u_tex,uv+vec2(s,0.)).r,c.g,texture2D(u_tex,uv-vec2(s,0.)).b);',
|
|
135
|
+
scanlines: 'c*=1.-.25*u_intensity*step(.5,fract(uv.y*u_resolution.y*.5));',
|
|
136
|
+
crt: 'vec2 d=uv-.5;float r=dot(d,d);c*=1.-.6*u_intensity*r;c*=.92+.08*sin(uv.y*u_resolution.y*3.14159);c.r*=1.+.05*u_intensity;',
|
|
137
|
+
bloom: 'vec3 b=vec3(0.);for(int i=0;i<8;i++){float a=float(i)*.785;b+=max(texture2D(u_tex,uv+vec2(cos(a),sin(a))*.012).rgb-.6,0.);}c+=b*.35*u_intensity;',
|
|
138
|
+
pixelate: 'float px=mix(1.,48.,u_intensity);vec2 g=floor(uv*u_resolution/px)*px/u_resolution;c=texture2D(u_tex,g+.5*px/u_resolution).rgb;',
|
|
139
|
+
duotone: 'float l=dot(c,vec3(.299,.587,.114));c=mix(c,mix(vec3(.12,.05,.35),vec3(1.,.55,.4),l),u_intensity);',
|
|
140
|
+
glitch: 'float k=step(.97,fract(sin(floor(uv.y*24.)+floor(u_time*6.))*4375.5));c=mix(c,texture2D(u_tex,uv+vec2(k*.04*u_intensity,0.)).rgb,k);',
|
|
141
|
+
};
|
|
142
|
+
/** One fragment shader running the passes in order over `u_tex` (pixel-sampling passes read the source). */
|
|
143
|
+
function postFxShader(effects) {
|
|
144
|
+
const list = effects.filter((e) => POST_EFFECTS[e]);
|
|
145
|
+
const body = list.map((e) => `{${POST_EFFECTS[e]}}`).join('');
|
|
146
|
+
return `uniform float u_intensity;void main(){vec2 uv=v_uv;vec3 c=texture2D(u_tex,uv).rgb;${body}gl_FragColor=vec4(clamp(c,0.,1.),1.);}`;
|
|
147
|
+
}
|
|
148
|
+
/** The unified CSS fallback (no WebGL / reduced data): a still background or image filter per preset. */
|
|
149
|
+
const GL_FALLBACKS = {
|
|
150
|
+
gradient: 'linear-gradient(120deg,#6366f1,#ec4899 50%,#22d3ee)',
|
|
151
|
+
plasma: 'conic-gradient(from 90deg,#f43f5e,#a855f7,#06b6d4,#f43f5e)',
|
|
152
|
+
waves: 'linear-gradient(#0a0f26,#1e3a8a)',
|
|
153
|
+
aurora: 'radial-gradient(120% 60% at 30% 40%,#10b98155,transparent),radial-gradient(100% 50% at 70% 50%,#8b5cf655,transparent),#05070f',
|
|
154
|
+
snow: 'radial-gradient(2px 2px at 20% 30%,#fff,transparent),radial-gradient(2px 2px at 70% 60%,#fff,transparent),radial-gradient(1.5px 1.5px at 40% 80%,#fff,transparent),linear-gradient(#0d1428,#1f2a4d)',
|
|
155
|
+
fireflies: 'radial-gradient(3px 3px at 25% 40%,#fde68a,transparent),radial-gradient(3px 3px at 65% 70%,#fde68a,transparent),#05090a',
|
|
156
|
+
stars: 'radial-gradient(1px 1px at 10% 20%,#fff,transparent),radial-gradient(1px 1px at 80% 30%,#fff,transparent),radial-gradient(1.5px 1.5px at 50% 70%,#cfe0ff,transparent),#02020a',
|
|
157
|
+
bokeh: 'radial-gradient(40px 40px at 30% 40%,#f472b633,transparent),radial-gradient(60px 60px at 70% 60%,#60a5fa33,transparent),#140820',
|
|
158
|
+
rain: 'repeating-linear-gradient(100deg,#ffffff10 0 1px,transparent 1px 14px),linear-gradient(#0a0f1a,#1a2133)',
|
|
159
|
+
// post-fx fallbacks are CSS filters on the <img>
|
|
160
|
+
'post:duotone': 'grayscale(1) sepia(.6) hue-rotate(220deg) saturate(2)',
|
|
161
|
+
'post:vignette': 'brightness(.95) contrast(1.05)',
|
|
162
|
+
'post:crt': 'contrast(1.15) saturate(1.2)',
|
|
163
|
+
'post:bloom': 'brightness(1.08) saturate(1.15)',
|
|
164
|
+
};
|
|
165
|
+
/** CSS fallback for a shader preset / post effect list. */
|
|
166
|
+
function glFallbackCss(preset, post = false) {
|
|
167
|
+
if (post)
|
|
168
|
+
return preset.split(/\s+/).map((e) => GL_FALLBACKS[`post:${e}`]).filter(Boolean).join(' ');
|
|
169
|
+
return GL_FALLBACKS[preset] || GL_FALLBACKS.gradient;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Adaptive quality for GL loops: measures fps, steps the resolution scale
|
|
173
|
+
* down (1 → 0.5 → 0.35) after two slow seconds and back up after five good
|
|
174
|
+
* ones, and caps the frame rate in battery-saver mode. Pure — feed it times.
|
|
175
|
+
*/
|
|
176
|
+
function glGovernor(options = {}) {
|
|
177
|
+
const { minFps = 40, saverFps = 30 } = options;
|
|
178
|
+
const STEPS = [1, 0.5, 0.35];
|
|
179
|
+
let step = 0;
|
|
180
|
+
let frames = 0;
|
|
181
|
+
let winStart = -1;
|
|
182
|
+
let last = -Infinity;
|
|
183
|
+
let slow = 0;
|
|
184
|
+
let good = 0;
|
|
185
|
+
let fps = 60;
|
|
186
|
+
const g = {
|
|
187
|
+
saver: false,
|
|
188
|
+
get scale() {
|
|
189
|
+
return Math.min(STEPS[step], g.saver ? 0.6 : 1);
|
|
190
|
+
},
|
|
191
|
+
get fps() {
|
|
192
|
+
return fps;
|
|
193
|
+
},
|
|
194
|
+
tick(t) {
|
|
195
|
+
if (winStart < 0)
|
|
196
|
+
winStart = t;
|
|
197
|
+
if (g.saver && t - last < 1000 / saverFps - 1)
|
|
198
|
+
return false;
|
|
199
|
+
last = t;
|
|
200
|
+
frames++;
|
|
201
|
+
if (t - winStart >= 1000) {
|
|
202
|
+
fps = Math.round((frames * 1000) / (t - winStart));
|
|
203
|
+
frames = 0;
|
|
204
|
+
winStart = t;
|
|
205
|
+
const before = g.scale;
|
|
206
|
+
if (fps < minFps && !g.saver) {
|
|
207
|
+
good = 0;
|
|
208
|
+
if (++slow >= 2 && step < STEPS.length - 1)
|
|
209
|
+
((step++), (slow = 0));
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
slow = 0;
|
|
213
|
+
if (++good >= 5 && step > 0)
|
|
214
|
+
((step--), (good = 0));
|
|
215
|
+
}
|
|
216
|
+
if (g.scale !== before)
|
|
217
|
+
g.onScale?.(g.scale);
|
|
218
|
+
}
|
|
219
|
+
return true;
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
return g;
|
|
223
|
+
}
|
|
224
|
+
/** Watch the Battery Status API (where available) and Save-Data; calls `cb(true)` in saver conditions. Returns a stop function. */
|
|
225
|
+
function watchPowerSaver(cb) {
|
|
226
|
+
let stopped = false;
|
|
227
|
+
const nav = (typeof navigator !== 'undefined' ? navigator : {});
|
|
228
|
+
const saveData = !!nav.connection?.saveData;
|
|
229
|
+
if (saveData)
|
|
230
|
+
cb(true);
|
|
231
|
+
if (typeof nav.getBattery !== 'function')
|
|
232
|
+
return () => undefined;
|
|
233
|
+
let battery = null;
|
|
234
|
+
const update = () => !stopped && cb(saveData || (!!battery && !battery.charging && battery.level <= 0.2));
|
|
235
|
+
nav.getBattery().then((b) => {
|
|
236
|
+
battery = b;
|
|
237
|
+
update();
|
|
238
|
+
b.addEventListener?.('levelchange', update);
|
|
239
|
+
b.addEventListener?.('chargingchange', update);
|
|
240
|
+
}, () => undefined);
|
|
241
|
+
return () => {
|
|
242
|
+
stopped = true;
|
|
243
|
+
battery?.removeEventListener?.('levelchange', update);
|
|
244
|
+
battery?.removeEventListener?.('chargingchange', update);
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
var css = "usa-shader,usa-distort,usa-liquid,usa-post-fx{display:block;position:relative;isolation:isolate;overflow:hidden}usa-shader{background:linear-gradient(120deg,#6366f1,#ec4899 50%,#22d3ee)}usa-shader>canvas.usa-gl{position:absolute;inset:0;width:100%;height:100%;z-index:-1;display:block}usa-distort>canvas.usa-gl,usa-liquid>canvas.usa-gl{position:absolute;inset:0;width:100%;height:100%;display:block;pointer-events:none}usa-distort>img,usa-liquid>img{display:block;width:100%;height:auto}usa-distort[data-active]>img,usa-liquid[data-active]>img{visibility:hidden}usa-distort[data-fallback]>img{transition:transform 0.6s cubic-bezier(0.22,1,0.36,1),filter 0.6s}usa-distort[data-fallback]:hover>img{transform:scale(1.04);filter:saturate(1.2)}@media (prefers-reduced-motion:reduce){usa-distort[data-fallback]:hover>img{transform:none}}usa-shader[data-fallback]{background:var(--usa-gl-fallback,linear-gradient(120deg,#6366f1,#ec4899 50%,#22d3ee))}usa-post-fx>canvas.usa-gl{position:absolute;inset:0;width:100%;height:100%;display:block;pointer-events:none}usa-post-fx>img{display:block;width:100%;height:auto}usa-post-fx[data-active]>img{visibility:hidden}usa-post-fx[data-fallback]>img{filter:var(--usa-gl-filter,none)}";
|
|
114
249
|
|
|
115
250
|
function make(kind) {
|
|
116
251
|
return (Base) => class extends Base {
|
|
@@ -123,15 +258,23 @@ function make(kind) {
|
|
|
123
258
|
this._hover = 0;
|
|
124
259
|
this._hoverTo = 0;
|
|
125
260
|
this._ripples = [];
|
|
261
|
+
this._scale = 1;
|
|
126
262
|
}
|
|
127
263
|
static get observedAttributes() {
|
|
128
|
-
return kind === 'shader' ? ['preset', 'speed'] : ['src'];
|
|
264
|
+
return kind === 'shader' ? ['preset', 'speed', 'quality'] : kind === 'post' ? ['effects', 'intensity', 'quality'] : ['src'];
|
|
129
265
|
}
|
|
130
266
|
get active() {
|
|
131
267
|
return !!this._q;
|
|
132
268
|
}
|
|
133
269
|
fallback(reason) {
|
|
134
270
|
this.setAttribute('data-fallback', reason);
|
|
271
|
+
// 4.8 unified fallback: a still CSS rendering of the preset / effects
|
|
272
|
+
if (reason !== 'off') {
|
|
273
|
+
if (kind === 'shader')
|
|
274
|
+
this.style.setProperty('--usa-gl-fallback', glFallbackCss(this.str('preset', 'gradient')));
|
|
275
|
+
if (kind === 'post')
|
|
276
|
+
this.style.setProperty('--usa-gl-filter', glFallbackCss(this.str('effects', 'vignette grain'), true) || 'none');
|
|
277
|
+
}
|
|
135
278
|
this._c?.remove();
|
|
136
279
|
this._c = null;
|
|
137
280
|
this._q?.dispose();
|
|
@@ -149,12 +292,13 @@ function make(kind) {
|
|
|
149
292
|
mouse: this._mouse,
|
|
150
293
|
hover: this._hover,
|
|
151
294
|
ripples: this._ripples.flatMap((r) => [r.x, r.y, (t - r.t) / 1000, this.num('strength', 1)]),
|
|
295
|
+
extra: kind === 'post' ? { u_intensity: base.clamp(this.num('intensity', 0.6), 0, 1) } : undefined,
|
|
152
296
|
});
|
|
153
297
|
}
|
|
154
298
|
mount() {
|
|
155
299
|
this.removeAttribute('data-fallback');
|
|
156
300
|
const custom = this.querySelector('script[type="x-shader/x-fragment"]');
|
|
157
|
-
const frag = kind === 'shader' ? custom?.textContent || this.str('preset', 'gradient') : kind;
|
|
301
|
+
const frag = kind === 'shader' ? custom?.textContent || this.str('preset', 'gradient') : kind === 'post' ? postFxShader(this.str('effects', 'vignette grain').split(/[\s,]+/)) : kind;
|
|
158
302
|
const img = kind === 'shader' ? null : this.querySelector('img');
|
|
159
303
|
if (kind !== 'shader' && !img)
|
|
160
304
|
return this.fallback('no-image');
|
|
@@ -179,7 +323,7 @@ function make(kind) {
|
|
|
179
323
|
}
|
|
180
324
|
};
|
|
181
325
|
const draw = () => {
|
|
182
|
-
q.resize();
|
|
326
|
+
q.resize(this._scale);
|
|
183
327
|
this.frame();
|
|
184
328
|
};
|
|
185
329
|
if (img && !(img.complete && img.naturalWidth)) {
|
|
@@ -193,7 +337,7 @@ function make(kind) {
|
|
|
193
337
|
this.setAttribute('data-active', '');
|
|
194
338
|
this.onCleanup(() => this.removeAttribute('data-active'));
|
|
195
339
|
draw();
|
|
196
|
-
if (kind
|
|
340
|
+
if (kind === 'distort' || kind === 'liquid') {
|
|
197
341
|
const pos = (e) => {
|
|
198
342
|
const r = this.getBoundingClientRect();
|
|
199
343
|
this._mouse = [base.clamp((e.clientX - r.left) / (r.width || 1), 0, 1), base.clamp(1 - (e.clientY - r.top) / (r.height || 1), 0, 1)];
|
|
@@ -210,7 +354,7 @@ function make(kind) {
|
|
|
210
354
|
// 4.0.1: also follow the element's own size (grid reflow, card expand…)
|
|
211
355
|
if (typeof ResizeObserver !== 'undefined') {
|
|
212
356
|
const ro = new ResizeObserver(() => {
|
|
213
|
-
q.resize();
|
|
357
|
+
q.resize(this._scale);
|
|
214
358
|
if (!this._id)
|
|
215
359
|
this.frame();
|
|
216
360
|
});
|
|
@@ -219,9 +363,20 @@ function make(kind) {
|
|
|
219
363
|
}
|
|
220
364
|
if (this.reduced)
|
|
221
365
|
return; // one static frame, no loop
|
|
366
|
+
// 4.8 adaptive quality: fps-driven resolution steps + battery saver frame cap
|
|
367
|
+
const gov = glGovernor();
|
|
368
|
+
const auto = this.str('quality', 'auto') !== 'high';
|
|
369
|
+
gov.onScale = (sc) => {
|
|
370
|
+
this._scale = sc;
|
|
371
|
+
this.setAttribute('data-quality', String(sc));
|
|
372
|
+
q.resize(sc);
|
|
373
|
+
};
|
|
374
|
+
if (auto)
|
|
375
|
+
this.onCleanup(watchPowerSaver((saver) => ((gov.saver = saver), gov.onScale?.(gov.scale))));
|
|
222
376
|
let visible = false;
|
|
223
377
|
const loop = () => {
|
|
224
|
-
|
|
378
|
+
if (!auto || gov.tick(base.now()))
|
|
379
|
+
this.frame();
|
|
225
380
|
this._id = base.raf(loop);
|
|
226
381
|
};
|
|
227
382
|
const sync = () => {
|
|
@@ -232,7 +387,7 @@ function make(kind) {
|
|
|
232
387
|
};
|
|
233
388
|
this.inView((v) => ((visible = v), sync()));
|
|
234
389
|
this.listen(document, 'visibilitychange', sync);
|
|
235
|
-
this.listen(window, 'resize', () => q.resize(), { passive: true });
|
|
390
|
+
this.listen(window, 'resize', () => q.resize(this._scale), { passive: true });
|
|
236
391
|
this.onCleanup(() => base.caf(this._id));
|
|
237
392
|
}
|
|
238
393
|
};
|
|
@@ -260,6 +415,16 @@ function defineDistort(tag = 'usa-distort') {
|
|
|
260
415
|
function defineLiquid(tag = 'usa-liquid') {
|
|
261
416
|
return base.defineElement(tag, make('liquid'), { id: 'webgl', text: css });
|
|
262
417
|
}
|
|
418
|
+
/**
|
|
419
|
+
* `<usa-post-fx effects="vignette grain crt" intensity="0.6">` — GPU
|
|
420
|
+
* post-processing over the `<img>` inside (4.8): `vignette` · `grain` ·
|
|
421
|
+
* `chromatic` · `scanlines` · `crt` · `bloom` · `pixelate` · `duotone` ·
|
|
422
|
+
* `glitch`, chained in order. `quality="high"` disables adaptive quality.
|
|
423
|
+
* Fallback: the image with an approximate CSS filter.
|
|
424
|
+
*/
|
|
425
|
+
function definePostFx(tag = 'usa-post-fx') {
|
|
426
|
+
return base.defineElement(tag, make('post'), { id: 'webgl', text: css });
|
|
427
|
+
}
|
|
263
428
|
|
|
264
429
|
/**
|
|
265
430
|
* use-scroll-animate/components/webgl — lightweight canvas / WebGL (v3.4).
|
|
@@ -272,16 +437,25 @@ function defineWebglComponents() {
|
|
|
272
437
|
defineShader();
|
|
273
438
|
defineDistort();
|
|
274
439
|
defineLiquid();
|
|
440
|
+
definePostFx();
|
|
275
441
|
}
|
|
276
442
|
|
|
277
443
|
exports.configureComponents = base.configureComponents;
|
|
278
444
|
exports.prefersReducedMotion = base.prefersReducedMotion;
|
|
445
|
+
exports.GL_FALLBACKS = GL_FALLBACKS;
|
|
446
|
+
exports.PARTICLE_PRESETS = PARTICLE_PRESETS;
|
|
447
|
+
exports.POST_EFFECTS = POST_EFFECTS;
|
|
279
448
|
exports.SHADERS = SHADERS;
|
|
280
449
|
exports.defineDistort = defineDistort;
|
|
281
450
|
exports.defineLiquid = defineLiquid;
|
|
451
|
+
exports.definePostFx = definePostFx;
|
|
282
452
|
exports.defineShader = defineShader;
|
|
283
453
|
exports.defineWebglComponents = defineWebglComponents;
|
|
284
454
|
exports.fragmentSource = fragmentSource;
|
|
455
|
+
exports.glFallbackCss = glFallbackCss;
|
|
456
|
+
exports.glGovernor = glGovernor;
|
|
285
457
|
exports.glQuad = glQuad;
|
|
458
|
+
exports.postFxShader = postFxShader;
|
|
286
459
|
exports.supportsWebGL = supportsWebGL;
|
|
460
|
+
exports.watchPowerSaver = watchPowerSaver;
|
|
287
461
|
//# sourceMappingURL=webgl.cjs.map
|