@stakekit/fluid-animation
Version:
694 lines (659 loc) • 30.9 kB
JavaScript
var T = Object.defineProperty;
var Q = (n, e, s) => e in n ? T(n, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : n[e] = s;
var t = (n, e, s) => (Q(n, typeof e != "symbol" ? e + "" : e, s), s);
import { Scene as h, ShaderMaterial as l, PlaneGeometry as v, Mesh as c, AdditiveBlending as y, Vector2 as a, OrthographicCamera as B, BufferGeometry as F, Float32BufferAttribute as x, MathUtils as d, TextureLoader as A, WebGLRenderTarget as I, HalfFloatType as L, FloatType as U, PerspectiveCamera as O, WebGLRenderer as k } from "three";
import { createNoise2D as S } from "simplex-noise";
const u = `#define GLSLIFY 1
varying vec2 vUv;
void main(){
vUv = vec2(0.5)+(position.xy)*0.5;
gl_Position = vec4(position, 1.0);
}
`, H = `#define GLSLIFY 1
uniform sampler2D velocity;
uniform vec2 size;
uniform float delta;
varying vec2 vUv;
void main() {
vec2 ratio = max(size.x, size.y) / size;
vec2 spot_new = vUv;
vec2 vel_old = texture2D(velocity, vUv).xy;
// back trace
vec2 spot_old = spot_new - vel_old * delta * ratio;
vec2 vel_new1 = texture2D(velocity, spot_old).xy;
// forward trace
vec2 spot_new2 = spot_old + vel_new1 * delta * ratio;
vec2 error = spot_new2 - spot_new;
vec2 spot_new3 = spot_new - error / 2.0;
vec2 vel_2 = texture2D(velocity, spot_new3).xy;
// back trace 2
vec2 spot_old2 = spot_new3 - vel_2 * delta * ratio;
vec2 newVel2 = texture2D(velocity, spot_old2).xy * 0.997;
gl_FragColor = vec4(newVel2, 0.0, 1.0);
}
`;
class E {
constructor(e, s, i, r) {
t(this, "scene");
t(this, "geometry");
t(this, "plane");
t(this, "material");
this.fluid = e, this.stage = s, this.velocity1 = i, this.velocity2 = r, this.scene = new h(), this.material = new l({
vertexShader: u,
fragmentShader: H,
uniforms: {
size: { value: e.size },
cellSize: { value: e.cellSize },
velocity: { value: this.velocity1.texture },
delta: { value: this.stage.delta }
}
}), this.geometry = new v(2, 2), this.plane = new c(this.geometry, this.material), this.scene.add(this.plane);
}
update() {
this.material.uniforms.delta.value = this.stage.delta, this.stage.renderer.setRenderTarget(this.velocity2), this.stage.renderer.render(this.scene, this.stage.camera), this.stage.renderer.setRenderTarget(null);
}
}
const f = `#define GLSLIFY 1
uniform vec2 center;
uniform vec2 size;
varying vec2 vUv;
void main(){
vUv = uv;
gl_Position = vec4(position.xy * size + center, 0.0, 1.0);
}
`, C = `#define GLSLIFY 1
uniform vec2 force;
uniform vec2 center;
uniform vec2 scale;
varying vec2 vUv;
void main(){
vec2 circle = (vUv - 0.5) * 2.0;
float d = 1.0 - min(length(circle), 1.0);
d *= d;
gl_FragColor = vec4(force, 0.0, d);
}
`;
class R {
constructor(e, s) {
t(this, "mesh");
t(this, "scene");
this.stage = e, this.velocity2 = s, this.scene = new h(), this.mesh = new c(
new v(1, 1),
new l({
vertexShader: f,
fragmentShader: C,
transparent: !0,
blending: y,
uniforms: {
size: { value: this.stage.pointerSize },
force: { value: this.stage.pointerForce },
center: { value: new a() }
}
})
), this.scene.add(this.mesh);
}
update() {
this.mesh.material.uniforms.center.value.copy(this.stage.pointer), this.stage.renderer.setRenderTarget(this.velocity2), this.stage.renderer.render(this.scene, this.stage.camera);
}
}
const P = `#define GLSLIFY 1
uniform sampler2D velocity;
uniform float delta;
uniform vec2 cellSize;
varying vec2 vUv;
void main(){
float x0 = texture2D(velocity, vUv-vec2(cellSize.x, 0)).x;
float x1 = texture2D(velocity, vUv+vec2(cellSize.x, 0)).x;
float y0 = texture2D(velocity, vUv-vec2(0, cellSize.y)).y;
float y1 = texture2D(velocity, vUv+vec2(0, cellSize.y)).y;
float divergence = (x1-x0 + y1-y0) / 2.0;
gl_FragColor = vec4(divergence / delta);
}
`;
class Y {
constructor(e, s, i, r) {
t(this, "scene");
t(this, "geometry");
t(this, "plane");
t(this, "material");
this.fluid = e, this.stage = s, this.velocity2 = i, this.divergence = r, this.scene = new h(), this.material = new l({
vertexShader: u,
fragmentShader: P,
uniforms: {
size: { value: e.size },
cellSize: { value: e.cellSize },
delta: { value: this.stage.delta },
velocity: { value: this.velocity2.texture }
}
}), this.geometry = new v(2, 2), this.plane = new c(this.geometry, this.material), this.scene.add(this.plane);
}
update() {
this.material.uniforms.delta.value = this.stage.delta, this.stage.renderer.setRenderTarget(this.divergence), this.stage.renderer.render(this.scene, this.stage.camera), this.stage.renderer.setRenderTarget(null);
}
}
const M = `#define GLSLIFY 1
uniform sampler2D pressure;
uniform sampler2D divergence;
uniform vec2 cellSize;
varying vec2 vUv;
void main(){
// poisson equation
float p0 = texture2D(pressure, vUv+vec2(cellSize.x * 2.0, 0)).r;
float p1 = texture2D(pressure, vUv-vec2(cellSize.x * 2.0, 0)).r;
float p2 = texture2D(pressure, vUv+vec2(0, cellSize.y * 2.0 )).r;
float p3 = texture2D(pressure, vUv-vec2(0, cellSize.y * 2.0 )).r;
float div = texture2D(divergence, vUv).r;
float newP = (p0 + p1 + p2 + p3) / 4.0 - div;
gl_FragColor = vec4(newP);
}
`, X = 16;
class W {
constructor(e, s, i, r, o) {
t(this, "scene");
t(this, "material");
t(this, "geometry");
t(this, "plane");
t(this, "pressure");
this.fluid = e, this.stage = s, this.divergence = i, this.pressure1 = r, this.pressure2 = o, this.scene = new h(), this.material = new l({
vertexShader: u,
fragmentShader: M,
uniforms: {
cellSize: {
value: this.fluid.cellSize
},
divergence: {
value: this.divergence.texture
},
pressure: {
value: this.pressure1.texture
}
}
}), this.pressure = this.pressure2, this.geometry = new v(2, 2), this.plane = new c(this.geometry, this.material), this.scene.add(this.plane);
}
update() {
let e, s;
for (let i = 0; i < X; i++)
i % 2 === 0 ? (e = this.pressure1, s = this.pressure2) : (e = this.pressure2, s = this.pressure1), this.material.uniforms.pressure.value = e.texture, this.pressure = s, this.stage.renderer.setRenderTarget(s), this.stage.renderer.render(this.scene, this.stage.camera), this.stage.renderer.setRenderTarget(null);
}
}
const b = `#define GLSLIFY 1
uniform sampler2D pressure;
uniform sampler2D velocity;
uniform vec2 cellSize;
uniform float delta;
varying vec2 vUv;
void main(){
float step = 1.0;
float p0 = texture2D(pressure, vUv+vec2(cellSize.x * step, 0)).r;
float p1 = texture2D(pressure, vUv-vec2(cellSize.x * step, 0)).r;
float p2 = texture2D(pressure, vUv+vec2(0, cellSize.y * step)).r;
float p3 = texture2D(pressure, vUv-vec2(0, cellSize.y * step)).r;
vec2 v = texture2D(velocity, vUv).xy;
vec2 gradP = vec2(p0 - p1, p2 - p3) * 0.5;
v = v - gradP * delta;
gl_FragColor = vec4(v, 0.0, 1.0);
}
`;
class q {
constructor(e, s, i, r, o) {
t(this, "scene");
t(this, "geometry");
t(this, "plane");
t(this, "material");
this.fluid = e, this.stage = s, this.velocity1 = i, this.velocity2 = r, this.pressure = o, this.scene = new h(), this.material = new l({
vertexShader: u,
fragmentShader: b,
uniforms: {
cellSize: {
value: this.fluid.cellSize
},
velocity: {
value: this.velocity2.texture
},
pressure: {
value: this.pressure.texture
},
delta: { value: this.stage.delta }
}
}), this.geometry = new v(2, 2), this.plane = new c(this.geometry, this.material), this.scene.add(this.plane);
}
update(e) {
this.material.uniforms.delta.value = this.stage.delta, this.material.uniforms.pressure.value = e.texture, this.stage.renderer.setRenderTarget(this.velocity1), this.stage.renderer.render(this.scene, this.stage.camera), this.stage.renderer.setRenderTarget(null);
}
}
const G = `#define GLSLIFY 1
uniform sampler2D dye;
uniform sampler2D velocity;
uniform vec2 size;
uniform float delta;
uniform float decay;
varying vec2 vUv;
void main() {
vec2 ratio = max(size.x, size.y) / size;
vec2 spot_new = vUv;
vec2 vel_old = texture2D(velocity, vUv).xy;
// back trace
vec2 spot_old = spot_new - vel_old * delta * ratio;
vec2 vel_new1 = texture2D(velocity, spot_old).xy;
// forward trace
vec2 spot_new2 = spot_old + vel_new1 * delta * ratio;
vec2 error = spot_new2 - spot_new;
vec2 spot_new3 = spot_new - error / 2.0;
vec2 vel_2 = texture2D(velocity, spot_new3).xy;
// back trace 2
vec2 spot_old2 = spot_new3 - vel_2 * delta * ratio;
vec3 color = texture2D(dye, spot_old2).rgb * decay;
gl_FragColor = vec4(color, 1.0);
}
`;
class K {
constructor(e, s, i, r, o) {
t(this, "scene");
t(this, "geometry");
t(this, "plane");
t(this, "material");
this.fluid = e, this.stage = s, this.dye1 = i, this.dye2 = r, this.velocity = o, this.scene = new h(), this.material = new l({
vertexShader: u,
fragmentShader: G,
uniforms: {
size: { value: e.size },
cellSize: { value: e.cellSize },
dye: { value: this.dye1.texture },
velocity: { value: this.velocity.texture },
decay: { value: this.stage.fluidDecay },
delta: { value: this.stage.delta }
}
}), this.geometry = new v(2, 2), this.plane = new c(this.geometry, this.material), this.scene.add(this.plane);
}
update(e, s) {
this.material.uniforms.dye.value = e.texture, this.material.uniforms.delta.value = this.stage.delta, this.material.uniforms.decay.value = this.stage.fluidDecay, this.stage.renderer.setRenderTarget(s), this.stage.renderer.render(this.scene, this.stage.camera), this.stage.renderer.setRenderTarget(null);
}
}
const Z = new B(-1, 1, 1, -1, 0, 1);
class J extends F {
constructor() {
super(), this.setAttribute("position", new x([-1, 3, 0, -1, -1, 0, 3, -1, 0], 3)), this.setAttribute("uv", new x([0, 2, 0, 0, 2, 0], 2));
}
}
const V = new J();
class N {
constructor(e) {
this._mesh = new c(V, e);
}
dispose() {
this._mesh.geometry.dispose();
}
render(e) {
e.render(this._mesh, Z);
}
get material() {
return this._mesh.material;
}
set material(e) {
this._mesh.material = e;
}
}
const j = `#define GLSLIFY 1
varying vec2 vUv;
void main(){
vUv = vec2(0.5)+(position.xy)*0.5;
gl_Position = vec4(position, 1.0);
}
`, _ = `#define GLSLIFY 1
uniform sampler2D diffuse;
uniform float amount;
uniform float smoothAmount;
uniform float elapsed;
uniform vec2 resolution;
varying vec2 vUv;
float sdCircle(vec2 p, float r) {
return length(p) - r;
}
float random(vec2 p) {
vec2 K1 = vec2(
23.14069263277926, // e^pi (Gelfond's constant)
2.665144142690225 // 2^sqrt(2) (Gelfond\\u2013Schneider constant)
);
return fract(cos(dot(p, K1)) * 12345.6789);
}
vec3 black = vec3(0.0);
void main() {
vec4 color = texture2D(diffuse, vUv);
vec2 uvRandom = vUv;
float aspect = resolution.y / resolution.x;
vec2 center = (vUv * 2.0 - 1.0) * vec2(1.0, resolution.y / resolution.x);
float d = sdCircle(center, elapsed);
float c = smoothstep(0.0, smoothAmount, d);
uvRandom.y *= random(vec2(uvRandom.y));
color.rgb += random(uvRandom) * 0.0; // add background noise
gl_FragColor = vec4(mix(color.rgb, black, c), amount);
}
`;
class $ {
constructor(e) {
t(this, "fsQuad");
t(this, "material");
t(this, "startScale", 0);
t(this, "endScale", 1);
this.stage = e, this.fsQuad = new N(), this.material = new l({
vertexShader: j,
fragmentShader: _,
depthWrite: !1,
uniforms: {
diffuse: { value: null },
amount: { value: 0.1 },
smoothAmount: { value: 0.3 },
elapsed: { value: this.startScale },
resolution: { value: new a() }
}
}), this.fsQuad.material = this.material;
}
resize() {
const e = this.stage.width / this.stage.height, { isDesktop: s, width: i, dpr: r } = this.stage;
this.startScale = s ? 0.3 / e : 0.65, this.endScale = (s ? e : 1 / e) + 0.25, this.stage.renderer.getDrawingBufferSize(
this.material.uniforms.resolution.value
), this.material.uniforms.elapsed.value = d.lerp(
this.startScale,
this.endScale,
this.stage.elapsed
), this.material.uniforms.smoothAmount.value = 200 / (i * r);
}
update(e) {
this.material.uniforms.elapsed.value = d.lerp(
this.startScale,
this.endScale,
this.stage.elapsed
), this.material.uniforms.diffuse.value = e, this.fsQuad.render(this.stage.renderer);
}
}
const z = `#define GLSLIFY 1
uniform sampler2D grad;
uniform float opacity;
uniform float time;
uniform float colorChange;
varying vec2 vUv;
void main() {
vec2 circle = (vUv - 0.5) * 2.0;
float d = 1.0 - min(length(circle), 1.0);
d *= d;
// d = step(0.5, d);
float c = (cos(time * colorChange) + 1.0) * 0.5;
vec3 col = texture2D(grad, vec2(c, 0.0)).rgb;
float a = d * opacity;
gl_FragColor = vec4(col, a);
// gl_FragColor = vec4(col, 0.01);
}
`, ee = Math.random() * 2e4;
let te = class {
constructor(e) {
t(this, "mesh");
t(this, "scene");
this.stage = e, this.scene = new h(), this.mesh = new c(
new v(1, 1),
new l({
vertexShader: f,
fragmentShader: z,
transparent: !0,
blending: y,
uniforms: {
time: { value: 0 },
opacity: { value: this.stage.pointerOpacity },
colorChange: { value: 5e-4 },
grad: { value: null },
size: { value: this.stage.pointerSize },
center: { value: this.stage.pointer }
}
})
), this.scene.add(this.mesh);
}
setTexture(e) {
this.mesh.material.uniforms.grad.value = e;
}
update(e, s) {
this.mesh.material.uniforms.time.value = ee + e, this.mesh.material.uniforms.opacity.value = this.stage.pointerOpacity, this.stage.renderer.setRenderTarget(s), this.stage.renderer.render(this.scene, this.stage.camera), this.stage.renderer.setRenderTarget(null);
}
};
const se = Math.random() * 2e4;
class ie {
constructor(e) {
t(this, "mesh");
t(this, "scene");
t(this, "noise");
this.stage = e, this.noise = S(), this.scene = new h(), this.mesh = new c(
new v(1, 1),
new l({
vertexShader: f,
fragmentShader: z,
transparent: !0,
blending: y,
uniforms: {
time: { value: 0 },
opacity: { value: 1 },
colorChange: { value: 8e-4 },
grad: { value: null },
size: { value: new a(0.25, 0.25) },
center: { value: new a() }
}
})
), this.scene.add(this.mesh);
}
setTexture(e) {
this.mesh.material.uniforms.grad.value = e;
}
update(e, s) {
const { landscape: i, aspect: r } = this.stage, o = e * 125e-5, p = i ? 0.35 : 0.75, m = this.noise(0, o) * p, D = this.noise(1, o) * p * r, g = i ? 1.25 : 2;
this.mesh.material.uniforms.time.value = se + e, this.mesh.material.uniforms.opacity.value = (1 - this.stage.elapsed) * 0.1, this.mesh.material.uniforms.center.value.set(m, D), this.mesh.material.uniforms.size.value.set(
i ? g / r : g,
i ? g : g * r
), this.stage.renderer.setRenderTarget(s), this.stage.renderer.render(this.scene, this.stage.camera), this.stage.renderer.setRenderTarget(null);
}
}
const w = 0.25, re = "data:image/png;base64,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";
class ne {
constructor(e) {
t(this, "advection");
t(this, "addVelocity");
t(this, "divergence");
t(this, "poisson");
t(this, "pressure");
t(this, "startDye");
t(this, "addDye");
t(this, "dye");
t(this, "output");
t(this, "renderTargets");
t(this, "step", 0);
t(this, "outputTexture", null);
t(this, "size", new a());
t(this, "cellSize", new a());
this.stage = e, this.setSize(), this.renderTargets = {
velocity1: this.createRenderTarget(),
velocity2: this.createRenderTarget(),
divergence: this.createRenderTarget(),
pressure1: this.createRenderTarget(),
pressure2: this.createRenderTarget(),
dye1: this.createRenderTarget(),
dye2: this.createRenderTarget()
}, this.startDye = new ie(this.stage), this.advection = new E(
this,
e,
this.renderTargets.velocity1,
this.renderTargets.velocity2
), this.addVelocity = new R(
this.stage,
this.renderTargets.velocity2
), this.addDye = new te(this.stage), this.divergence = new Y(
this,
this.stage,
this.renderTargets.velocity2,
this.renderTargets.divergence
), this.dye = new K(
this,
this.stage,
this.renderTargets.dye1,
this.renderTargets.dye2,
this.renderTargets.velocity2
), this.poisson = new W(
this,
this.stage,
this.renderTargets.divergence,
this.renderTargets.pressure1,
this.renderTargets.pressure2
), this.pressure = new q(
this,
e,
this.renderTargets.velocity1,
this.renderTargets.velocity2,
this.renderTargets.pressure1
), this.output = new $(e), this.resize(), this.load();
}
async load() {
const e = await new A().loadAsync(re);
this.startDye.setTexture(e), this.addDye.setTexture(e);
}
createRenderTarget() {
const e = /(iPad|iPhone|iPod)/g.test(navigator.userAgent) ? L : U;
return new I(this.size.x, this.size.y, {
type: e
});
}
setSize() {
const e = Math.round(w * this.stage.width), s = Math.round(w * this.stage.height), i = 1 / e, r = 1 / s;
this.cellSize.set(i, r), this.size.set(e, s);
}
resize() {
this.setSize(), Object.values(this.renderTargets).forEach(
(e) => e.setSize(this.size.x, this.size.y)
), this.output.resize();
}
update(e) {
this.step++;
const s = this.step % 2 === 0;
this.stage.elapsed < 1 && this.startDye.update(
e,
s ? this.renderTargets.dye1 : this.renderTargets.dye2
), this.advection.update(), this.addVelocity.update(), this.addDye.update(
e,
s ? this.renderTargets.dye1 : this.renderTargets.dye2
), this.divergence.update(), this.poisson.update(), this.pressure.update(this.poisson.pressure), this.dye.update(
s ? this.renderTargets.dye1 : this.renderTargets.dye2,
s ? this.renderTargets.dye2 : this.renderTargets.dye1
), this.outputTexture = s ? this.renderTargets.dye2.texture : this.renderTargets.dye1.texture, this.output.update(this.outputTexture), this.output.update(this.renderTargets.dye1.texture);
}
}
class ae {
constructor(e) {
t(this, "noise");
t(this, "pointer", new a());
t(this, "size", 1.25);
t(this, "opacity", 3);
t(this, "force", 3);
this.stage = e, this.noise = S();
}
update(e) {
const { aspect: s } = this.stage, r = e * 3e-4;
this.size = 1.25 + (Math.sin(r) + 1) * 0.5;
const o = d.lerp(0.9, 1, this.stage.elapsed), p = this.noise(0, r) * o, m = this.noise(1, r) * o / s;
this.pointer.set(p, m);
}
}
class oe {
constructor(e, s) {
t(this, "fluid");
t(this, "fakePointer");
t(this, "movement", new a());
t(this, "pointer", new a());
t(this, "devicePointer", new a());
t(this, "lastPointer", new a());
t(this, "pointerSize", new a());
t(this, "pointerForce", new a());
t(this, "renderer");
t(this, "scene");
t(this, "camera");
t(this, "dpr");
t(this, "width", 0);
t(this, "height", 0);
t(this, "left", 0);
t(this, "top", 0);
t(this, "hFov", 1);
t(this, "vFov", 1);
t(this, "aspect", 1);
t(this, "elapsed", 1.2);
t(this, "pointerOpacity", 0.4);
t(this, "landscape", !1);
t(this, "pointerMix", 1);
t(this, "pointerMixTarget", 1);
t(this, "fluidDecay", 0.99);
t(this, "delta", 1 / 60);
this.node = e, this.app = s, this.scene = new h(), this.camera = new O(), this.camera.position.z = 10, this.renderer = new k({ antialias: !0, alpha: !0 }), this.fakePointer = new ae(this), this.renderer.setPixelRatio(Math.min(2, window.devicePixelRatio)), this.renderer.autoClear = !1, this.renderer.setClearColor(0), this.dpr = this.renderer.getPixelRatio(), this.node.appendChild(this.renderer.domElement), document.addEventListener("mousemove", this.onMouseMove.bind(this)), document.addEventListener("touchstart", this.onTouchMove.bind(this)), document.addEventListener("touchmove", this.onTouchMove.bind(this), {
passive: !1
}), this.fluid = new ne(this), new ResizeObserver(this.resize.bind(this)).observe(this.node), this.resize();
}
resize() {
const { left: e, top: s, width: i, height: r } = this.node.getBoundingClientRect();
this.left = e, this.top = s, this.width = i, this.height = r, this.landscape = i > r, this.aspect = this.width / this.height, this.camera.aspect = this.aspect, this.camera.updateProjectionMatrix(), this.renderer.setSize(i, r), this.camera.position.z = 1 / this.camera.aspect * this.camera.getFocalLength() / this.camera.getFilmHeight(), this.vFov = this.camera.position.z * this.camera.getFilmHeight() / this.camera.getFocalLength(), this.hFov = this.vFov * this.camera.aspect, this.fluid.resize();
}
onTouchMove(e) {
this.pointerMixTarget = 1;
const { clientX: s, clientY: i } = e.touches[0];
this.onMove(s, i);
}
onMouseMove(e) {
this.pointerMixTarget = 1;
const { x: s, y: i } = e;
this.onMove(s, i);
}
onMove(e, s) {
const i = (e - this.left) / this.width * 2 - 1, r = -((s - this.top) / this.height) * 2 + 1;
this.devicePointer.set(i, r);
}
update(e) {
this.pointerMixTarget *= 0.995, this.pointerMix += (this.pointerMixTarget - this.pointerMix) * 0.01, this.pointer.lerpVectors(
this.fakePointer.pointer,
this.devicePointer,
this.pointerMix
), this.movement.subVectors(this.pointer, this.lastPointer), this.lastPointer.copy(this.pointer), this.delta = d.lerp(1 / 180, 1 / 60, this.pointerMix), this.fluidDecay = d.lerp(0.995, 0.99, this.pointerMix), this.pointerOpacity = d.lerp(this.fakePointer.opacity, 4, this.pointerMix) * this.movement.length(), this.pointerForce.copy(this.movement).multiplyScalar(
d.lerp(this.fakePointer.force, 2, this.pointerMix)
);
const s = d.lerp(this.fakePointer.size, 1.25, this.pointerMix);
this.pointerSize.set(
this.landscape ? s / this.aspect : s,
this.landscape ? s : s * this.aspect
), this.fluid.update(e), this.fakePointer.update(e), this.renderer.render(this.scene, this.camera);
}
get isDesktop() {
return this.app.isDesktop;
}
get fluidMap() {
return this.fluid.outputTexture;
}
}
class he {
constructor(e) {
t(this, "stage");
t(this, "pointerX", 0);
t(this, "pointerY", 0);
t(this, "scrollY", 0);
t(this, "isDesktop", !1);
this.update = this.update.bind(this);
const s = window.matchMedia("(min-width:1024px)");
s.addEventListener("change", () => this.isDesktop = s.matches), this.isDesktop = s.matches, this.stage = new oe(e, this), this.init();
}
async init() {
requestAnimationFrame(this.update), document.body.addEventListener(
"pointermove",
this.onPointerMove.bind(this)
);
}
onPointerMove(e) {
this.pointerX = e.x, this.pointerY = e.y;
}
update(e) {
requestAnimationFrame(this.update), this.stage.update(e);
}
}
const ue = (n) => {
new he(n);
};
export {
ue as startFluid
};