@react-three/drei 9.42.1 → 9.43.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/README.md +32 -1
- package/core/index.cjs.js +1 -1
- package/core/index.d.ts +1 -0
- package/core/index.js +1 -0
- package/core/useHelper.cjs.js +1 -1
- package/core/useHelper.d.ts +2 -1
- package/core/useHelper.js +11 -22
- package/core/useTrailTexture.cjs.js +1 -0
- package/core/useTrailTexture.d.ts +17 -0
- package/core/useTrailTexture.js +160 -0
- package/index.cjs.js +1 -1
- package/index.js +1 -0
- package/native/index.cjs.js +1 -1
- package/native/index.js +1 -0
- package/package.json +1 -1
- package/web/index.cjs.js +1 -1
- package/web/index.js +1 -0
package/README.md
CHANGED
|
@@ -122,7 +122,8 @@ The `native` route of the library **does not** export `Html` or `Loader`. The de
|
|
|
122
122
|
<li><a href="#usetexture">useTexture</a></li>
|
|
123
123
|
<li><a href="#usektx2">useKTX2</a></li>
|
|
124
124
|
<li><a href="#usecubetexture">useCubeTexture</a></li>
|
|
125
|
-
<li><a href="#usevideotexture">useVideoTexture</a></li>
|
|
125
|
+
<li><a href="#usevideotexture">useVideoTexture</a></li>
|
|
126
|
+
<li><a href="#usetrailtexture">useTrailTexture</a></li>
|
|
126
127
|
</ul>
|
|
127
128
|
<li><a href="#performance">Performance</a></li>
|
|
128
129
|
<ul>
|
|
@@ -1975,6 +1976,35 @@ return (
|
|
|
1975
1976
|
<meshBasicMaterial map={texture} toneMapped={false} />
|
|
1976
1977
|
```
|
|
1977
1978
|
|
|
1979
|
+
#### useTrailTexture
|
|
1980
|
+
|
|
1981
|
+
<p>
|
|
1982
|
+
<a href="https://codesandbox.io/s/fj1qlg"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/fj1qlg/screenshot.png" alt="Demo"/></a>
|
|
1983
|
+
</p>
|
|
1984
|
+
|
|
1985
|
+
This hook returns a `THREE.Texture` with a pointer trail which can be used in shaders to control displacement among other things.
|
|
1986
|
+
|
|
1987
|
+
```tsx
|
|
1988
|
+
type TrailConfig = {
|
|
1989
|
+
size?: number // texture size (default: 64x64)
|
|
1990
|
+
maxAge?: number // max age (ms) of trail points (default: 750)
|
|
1991
|
+
radius?: number // trail radius (default: 0.3)
|
|
1992
|
+
intensity?: number // canvas trail opacity (default: 0.2)
|
|
1993
|
+
interpolate?: number // add points in between slow pointer events (default: 0)
|
|
1994
|
+
smoothing?: number // moving average of pointer force (default: 0)
|
|
1995
|
+
minForce?: number // minimum pointer force (default: 0.3)
|
|
1996
|
+
blend?: CanvasRenderingContext2D['globalCompositeOperation'] // (default: 'screen')
|
|
1997
|
+
ease?: (t: number) => number // default: easeCircOut
|
|
1998
|
+
}
|
|
1999
|
+
```
|
|
2000
|
+
|
|
2001
|
+
```jsx
|
|
2002
|
+
const { texture, onMove } = useTrailTexture(config: TrailConfig)
|
|
2003
|
+
return (
|
|
2004
|
+
<mesh onPointerMove={onMove}>
|
|
2005
|
+
<shaderMaterial displacementMap={texture} />
|
|
2006
|
+
```
|
|
2007
|
+
|
|
1978
2008
|
# Performance
|
|
1979
2009
|
|
|
1980
2010
|
#### Instances
|
|
@@ -2564,6 +2594,7 @@ Calculates a boundary box and centers the camera accordingly. If you are using c
|
|
|
2564
2594
|
<mesh />
|
|
2565
2595
|
</Bounds>
|
|
2566
2596
|
```
|
|
2597
|
+
|
|
2567
2598
|
The Bounds component also acts as a context provider, use the `useBounds` hook to refresh the bounds, fit the camera, clip near/far planes, go to camera orientations or focus objects. `refresh(object?: THREE.Object3D | THREE.Box3)` will recalculate bounds, since this can be expensive only call it when you know the view has changed. `clip` sets the cameras near/far planes. `to` sets a position and target for the camera. `fit` zooms and centers the view.
|
|
2568
2599
|
|
|
2569
2600
|
```jsx
|
package/core/index.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("./Billboard.cjs.js"),r=require("./QuadraticBezierLine.cjs.js"),s=require("./CubicBezierLine.cjs.js"),t=require("./CatmullRomLine.cjs.js"),o=require("./Line.cjs.js"),i=require("./PositionalAudio.cjs.js"),u=require("./Text.cjs.js"),a=require("./Text3D.cjs.js"),n=require("./Effects.cjs.js"),c=require("./GradientTexture.cjs.js"),j=require("./Image.cjs.js"),p=require("./Edges.cjs.js"),x=require("./Trail.cjs.js"),l=require("./Sampler.cjs.js"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("./Billboard.cjs.js"),r=require("./QuadraticBezierLine.cjs.js"),s=require("./CubicBezierLine.cjs.js"),t=require("./CatmullRomLine.cjs.js"),o=require("./Line.cjs.js"),i=require("./PositionalAudio.cjs.js"),u=require("./Text.cjs.js"),a=require("./Text3D.cjs.js"),n=require("./Effects.cjs.js"),c=require("./GradientTexture.cjs.js"),j=require("./Image.cjs.js"),p=require("./Edges.cjs.js"),x=require("./Trail.cjs.js"),l=require("./Sampler.cjs.js"),q=require("./ComputedAttribute.cjs.js"),d=require("./Clone.cjs.js"),m=require("./MarchingCubes.cjs.js"),h=require("./Decal.cjs.js"),C=require("./Svg.cjs.js"),M=require("./OrthographicCamera.cjs.js"),S=require("./PerspectiveCamera.cjs.js"),T=require("./CubeCamera.cjs.js"),P=require("./DeviceOrientationControls.cjs.js"),b=require("./FlyControls.cjs.js"),B=require("./MapControls.cjs.js"),g=require("./OrbitControls.cjs.js"),f=require("./TrackballControls.cjs.js"),v=require("./ArcballControls.cjs.js"),L=require("./TransformControls.cjs.js"),A=require("./PointerLockControls.cjs.js"),k=require("./FirstPersonControls.cjs.js"),D=require("./GizmoHelper.cjs.js"),E=require("./GizmoViewcube.cjs.js"),R=require("./GizmoViewport.cjs.js"),w=require("./useCubeTexture.cjs.js"),G=require("./useFBX.cjs.js"),z=require("./useGLTF.cjs.js"),F=require("./useKTX2.cjs.js"),O=require("./useProgress.cjs.js"),I=require("./useTexture.cjs.js"),V=require("./useVideoTexture.cjs.js"),y=require("./Stats.cjs.js"),H=require("./useDepthBuffer.cjs.js"),Q=require("./useAspect.cjs.js"),X=require("./useCamera.cjs.js"),K=require("./useDetectGPU.cjs.js"),W=require("./useHelper.cjs.js"),N=require("./useBVH.cjs.js"),U=require("./useContextBridge.cjs.js"),_=require("./useAnimations.cjs.js"),J=require("./useFBO.cjs.js"),Y=require("./useIntersect.cjs.js"),Z=require("./useBoxProjectedEnv.cjs.js"),$=require("./BBAnchor.cjs.js"),ee=require("./useTrailTexture.cjs.js"),re=require("./CurveModifier.cjs.js"),se=require("./MeshDistortMaterial.cjs.js"),te=require("./MeshWobbleMaterial.cjs.js"),oe=require("./MeshReflectorMaterial.cjs.js"),ie=require("./MeshRefractionMaterial.cjs.js"),ue=require("./PointMaterial.cjs.js"),ae=require("./shaderMaterial.cjs.js"),ne=require("./softShadows.cjs.js"),ce=require("./shapes.cjs.js"),je=require("./RoundedBox.cjs.js"),pe=require("./ScreenQuad.cjs.js"),xe=require("./Center.cjs.js"),le=require("./Bounds.cjs.js"),qe=require("./CameraShake.cjs.js"),de=require("./Float.cjs.js"),me=require("./Stage.cjs.js"),he=require("./Backdrop.cjs.js"),Ce=require("./Shadow.cjs.js"),Me=require("./ContactShadows.cjs.js"),Se=require("./AccumulativeShadows.cjs.js"),Te=require("./Reflector.cjs.js"),Pe=require("./SpotLight.cjs.js"),be=require("./Environment.cjs.js"),Be=require("./Lightformer.cjs.js"),ge=require("./Sky.cjs.js"),fe=require("./Stars.cjs.js"),ve=require("./Cloud.cjs.js"),Le=require("./Sparkles.cjs.js"),Ae=require("./useMatcapTexture.cjs.js"),ke=require("./useNormalTexture.cjs.js"),De=require("./Points.cjs.js"),Ee=require("./Instances.cjs.js"),Re=require("./Segments.cjs.js"),we=require("./Detailed.cjs.js"),Ge=require("./Preload.cjs.js"),ze=require("./BakeShadows.cjs.js"),Fe=require("./meshBounds.cjs.js"),Oe=require("./AdaptiveDpr.cjs.js"),Ie=require("./AdaptiveEvents.cjs.js"),Ve=require("./PerformanceMonitor.cjs.js"),ye=require("./RenderTexture.cjs.js"),He=require("./Mask.cjs.js");require("@babel/runtime/helpers/extends"),require("react"),require("@react-three/fiber"),require("react-merge-refs"),require("three"),require("three-stdlib"),require("troika-three-text"),require("suspend-react"),require("meshline"),require("lodash.pick"),require("lodash.omit"),require("zustand"),require("stats.js"),require("../helpers/useEffectfulState.cjs.js"),require("detect-gpu"),require("three-mesh-bvh"),require("../materials/BlurPass.cjs.js"),require("../materials/ConvolutionMaterial.cjs.js"),require("../materials/MeshReflectorMaterial.cjs.js"),require("../materials/MeshRefractionMaterial.cjs.js"),require("../helpers/environment-assets.cjs.js"),require("../materials/SpotLightMaterial.cjs.js"),require("react-composer"),exports.Billboard=e.Billboard,exports.QuadraticBezierLine=r.QuadraticBezierLine,exports.CubicBezierLine=s.CubicBezierLine,exports.CatmullRomLine=t.CatmullRomLine,exports.Line=o.Line,exports.PositionalAudio=i.PositionalAudio,exports.Text=u.Text,exports.Text3D=a.Text3D,exports.Effects=n.Effects,exports.isWebGL2Available=n.isWebGL2Available,exports.GradientTexture=c.GradientTexture,exports.Image=j.Image,exports.Edges=p.Edges,exports.Trail=x.Trail,exports.useTrail=x.useTrail,exports.Sampler=l.Sampler,exports.useSurfaceSampler=l.useSurfaceSampler,exports.ComputedAttribute=q.ComputedAttribute,exports.Clone=d.Clone,exports.MarchingCube=m.MarchingCube,exports.MarchingCubes=m.MarchingCubes,exports.MarchingPlane=m.MarchingPlane,exports.Decal=h.Decal,exports.Svg=C.Svg,exports.OrthographicCamera=M.OrthographicCamera,exports.PerspectiveCamera=S.PerspectiveCamera,exports.CubeCamera=T.CubeCamera,exports.DeviceOrientationControls=P.DeviceOrientationControls,exports.FlyControls=b.FlyControls,exports.MapControls=B.MapControls,exports.OrbitControls=g.OrbitControls,exports.TrackballControls=f.TrackballControls,exports.ArcballControls=v.ArcballControls,exports.TransformControls=L.TransformControls,exports.PointerLockControls=A.PointerLockControls,exports.FirstPersonControls=k.FirstPersonControls,exports.GizmoHelper=D.GizmoHelper,exports.useGizmoContext=D.useGizmoContext,exports.GizmoViewcube=E.GizmoViewcube,exports.GizmoViewport=R.GizmoViewport,exports.useCubeTexture=w.useCubeTexture,exports.useFBX=G.useFBX,exports.useGLTF=z.useGLTF,exports.useKTX2=F.useKTX2,exports.useProgress=O.useProgress,exports.IsObject=I.IsObject,exports.useTexture=I.useTexture,exports.useVideoTexture=V.useVideoTexture,exports.Stats=y.Stats,exports.useDepthBuffer=H.useDepthBuffer,exports.useAspect=Q.useAspect,exports.useCamera=X.useCamera,exports.useDetectGPU=K.useDetectGPU,exports.useHelper=W.useHelper,exports.useBVH=N.useBVH,exports.useContextBridge=U.useContextBridge,exports.useAnimations=_.useAnimations,exports.useFBO=J.useFBO,exports.useIntersect=Y.useIntersect,exports.useBoxProjectedEnv=Z.useBoxProjectedEnv,exports.BBAnchor=$.BBAnchor,exports.useTrailTexture=ee.useTrailTexture,exports.CurveModifier=re.CurveModifier,exports.MeshDistortMaterial=se.MeshDistortMaterial,exports.MeshWobbleMaterial=te.MeshWobbleMaterial,exports.MeshReflectorMaterial=oe.MeshReflectorMaterial,exports.MeshRefractionMaterial=ie.MeshRefractionMaterial,exports.PointMaterial=ue.PointMaterial,exports.PointMaterialImpl=ue.PointMaterialImpl,exports.shaderMaterial=ae.shaderMaterial,exports.softShadows=ne.softShadows,exports.Box=ce.Box,exports.Capsule=ce.Capsule,exports.Circle=ce.Circle,exports.Cone=ce.Cone,exports.Cylinder=ce.Cylinder,exports.Dodecahedron=ce.Dodecahedron,exports.Extrude=ce.Extrude,exports.Icosahedron=ce.Icosahedron,exports.Lathe=ce.Lathe,exports.Octahedron=ce.Octahedron,exports.Plane=ce.Plane,exports.Polyhedron=ce.Polyhedron,exports.Ring=ce.Ring,exports.Sphere=ce.Sphere,exports.Tetrahedron=ce.Tetrahedron,exports.Torus=ce.Torus,exports.TorusKnot=ce.TorusKnot,exports.Tube=ce.Tube,exports.RoundedBox=je.RoundedBox,exports.ScreenQuad=pe.ScreenQuad,exports.Center=xe.Center,exports.Bounds=le.Bounds,exports.useBounds=le.useBounds,exports.CameraShake=qe.CameraShake,exports.Float=de.Float,exports.Stage=me.Stage,exports.Backdrop=he.Backdrop,exports.Shadow=Ce.Shadow,exports.ContactShadows=Me.ContactShadows,exports.AccumulativeShadows=Se.AccumulativeShadows,exports.RandomizedLight=Se.RandomizedLight,exports.accumulativeContext=Se.accumulativeContext,exports.Reflector=Te.Reflector,exports.SpotLight=Pe.SpotLight,exports.SpotLightShadow=Pe.SpotLightShadow,exports.Environment=be.Environment,exports.EnvironmentCube=be.EnvironmentCube,exports.EnvironmentMap=be.EnvironmentMap,exports.EnvironmentPortal=be.EnvironmentPortal,exports.useEnvironment=be.useEnvironment,exports.Lightformer=Be.Lightformer,exports.Sky=ge.Sky,exports.calcPosFromAngles=ge.calcPosFromAngles,exports.Stars=fe.Stars,exports.Cloud=ve.Cloud,exports.Sparkles=Le.Sparkles,exports.useMatcapTexture=Ae.useMatcapTexture,exports.useNormalTexture=ke.useNormalTexture,exports.Point=De.Point,exports.Points=De.Points,exports.PointsBuffer=De.PointsBuffer,exports.PositionPoint=De.PositionPoint,exports.Instance=Ee.Instance,exports.Instances=Ee.Instances,exports.Merged=Ee.Merged,exports.Segment=Re.Segment,exports.SegmentObject=Re.SegmentObject,exports.Segments=Re.Segments,exports.Detailed=we.Detailed,exports.Preload=Ge.Preload,exports.BakeShadows=ze.BakeShadows,exports.meshBounds=Fe.meshBounds,exports.AdaptiveDpr=Oe.AdaptiveDpr,exports.AdaptiveEvents=Ie.AdaptiveEvents,exports.PerformanceMonitor=Ve.PerformanceMonitor,exports.usePerformanceMonitor=Ve.usePerformanceMonitor,exports.RenderTexture=ye.RenderTexture,exports.Mask=He.Mask,exports.useMask=He.useMask;
|
package/core/index.d.ts
CHANGED
|
@@ -52,6 +52,7 @@ export * from './useFBO';
|
|
|
52
52
|
export * from './useIntersect';
|
|
53
53
|
export * from './useBoxProjectedEnv';
|
|
54
54
|
export * from './BBAnchor';
|
|
55
|
+
export * from './useTrailTexture';
|
|
55
56
|
export * from './CurveModifier';
|
|
56
57
|
export * from './MeshDistortMaterial';
|
|
57
58
|
export * from './MeshWobbleMaterial';
|
package/core/index.js
CHANGED
|
@@ -52,6 +52,7 @@ export { useFBO } from './useFBO.js';
|
|
|
52
52
|
export { useIntersect } from './useIntersect.js';
|
|
53
53
|
export { useBoxProjectedEnv } from './useBoxProjectedEnv.js';
|
|
54
54
|
export { BBAnchor } from './BBAnchor.js';
|
|
55
|
+
export { useTrailTexture } from './useTrailTexture.js';
|
|
55
56
|
export { CurveModifier } from './CurveModifier.js';
|
|
56
57
|
export { MeshDistortMaterial } from './MeshDistortMaterial.js';
|
|
57
58
|
export { MeshWobbleMaterial } from './MeshWobbleMaterial.js';
|
package/core/useHelper.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),r=require("@react-three/fiber");function t(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var u=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,u.get?u:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var u=t(e);exports.useHelper=function(e,t,...n){const c=u.useRef(),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),r=require("@react-three/fiber");function t(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var u=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,u.get?u:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var u=t(e);exports.useHelper=function(e,t,...n){const c=u.useRef(),s=r.useThree((e=>e.scene));return u.useEffect((()=>{let r;if(e&&null!=e&&e.current&&t&&(c.current=r=new t(e.current,...n)),r)return s.add(r),()=>{c.current=void 0,s.remove(r),null==r.dispose||r.dispose()}}),[s,t,e,...n]),r.useFrame((()=>{var e;null==(e=c.current)||null==e.update||e.update()})),c};
|
package/core/useHelper.d.ts
CHANGED
|
@@ -3,8 +3,9 @@ import { Object3D } from 'three';
|
|
|
3
3
|
import { Falsey } from 'utility-types';
|
|
4
4
|
declare type Helper = Object3D & {
|
|
5
5
|
update: () => void;
|
|
6
|
+
dispose: () => void;
|
|
6
7
|
};
|
|
7
8
|
declare type Constructor = new (...args: any[]) => any;
|
|
8
9
|
declare type Rest<T> = T extends [infer _, ...infer R] ? R : never;
|
|
9
|
-
export declare function useHelper<T extends Constructor>(object3D: React.MutableRefObject<Object3D
|
|
10
|
+
export declare function useHelper<T extends Constructor>(object3D: React.MutableRefObject<Object3D> | Falsey, helperConstructor: T, ...args: Rest<ConstructorParameters<T>>): React.MutableRefObject<Helper | undefined>;
|
|
10
11
|
export {};
|
package/core/useHelper.js
CHANGED
|
@@ -5,36 +5,25 @@ function useHelper(object3D, helperConstructor, ...args) {
|
|
|
5
5
|
const helper = React.useRef();
|
|
6
6
|
const scene = useThree(state => state.scene);
|
|
7
7
|
React.useEffect(() => {
|
|
8
|
-
|
|
9
|
-
if (helperConstructor && object3D != null && object3D.current) {
|
|
10
|
-
helper.current = new helperConstructor(object3D.current, ...args);
|
|
8
|
+
let currentHelper = undefined;
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
}
|
|
10
|
+
if (object3D && object3D != null && object3D.current && helperConstructor) {
|
|
11
|
+
helper.current = currentHelper = new helperConstructor(object3D.current, ...args);
|
|
16
12
|
}
|
|
17
|
-
/**
|
|
18
|
-
* Dispose of the helper if no object 3D is passed
|
|
19
|
-
*/
|
|
20
13
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
14
|
+
if (currentHelper) {
|
|
15
|
+
scene.add(currentHelper);
|
|
16
|
+
return () => {
|
|
17
|
+
helper.current = undefined;
|
|
18
|
+
scene.remove(currentHelper);
|
|
19
|
+
currentHelper.dispose == null ? void 0 : currentHelper.dispose();
|
|
20
|
+
};
|
|
24
21
|
}
|
|
25
|
-
|
|
26
|
-
return () => {
|
|
27
|
-
if (helper.current) {
|
|
28
|
-
scene.remove(helper.current);
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
22
|
}, [scene, helperConstructor, object3D, ...args]);
|
|
32
23
|
useFrame(() => {
|
|
33
24
|
var _helper$current;
|
|
34
25
|
|
|
35
|
-
|
|
36
|
-
helper.current.update();
|
|
37
|
-
}
|
|
26
|
+
return void ((_helper$current = helper.current) == null ? void 0 : _helper$current.update == null ? void 0 : _helper$current.update());
|
|
38
27
|
});
|
|
39
28
|
return helper;
|
|
40
29
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("react"),e=require("@react-three/fiber"),i=require("three");const s=t=>Math.sqrt(1-Math.pow(t-1,2));class a{constructor({size:t=64,maxAge:e=750,radius:i=.3,intensity:a=.2,interpolate:h=0,smoothing:r=0,minForce:c=.3,blend:o="screen",ease:n=s}={}){this.size=t,this.maxAge=e,this.radius=i,this.intensity=a,this.ease=n,this.interpolate=h,this.smoothing=r,this.minForce=c,this.blend=o,this.trail=[],this.force=0,this.initTexture()}initTexture(){this.canvas=document.createElement("canvas"),this.canvas.width=this.canvas.height=this.size,this.ctx=this.canvas.getContext("2d"),this.ctx.fillStyle="black",this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height),this.texture=new i.Texture(this.canvas),this.canvas.id="touchTexture",this.canvas.style.width=this.canvas.style.height=`${this.canvas.width}px`}update(t){this.clear(),this.trail.forEach(((e,i)=>{e.age+=1e3*t,e.age>this.maxAge&&this.trail.splice(i,1)})),this.trail.length||(this.force=0),this.trail.forEach((t=>{this.drawTouch(t)})),this.texture.needsUpdate=!0}clear(){this.ctx.globalCompositeOperation="source-over",this.ctx.fillStyle="black",this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)}addTouch(t){const e=this.trail[this.trail.length-1];if(e){const i=e.x-t.x,s=e.y-t.y,a=i*i+s*s,h=Math.max(this.minForce,Math.min(1e4*a,1));if(this.force=function(t,e,i=.9){return e*i+t*(1-i)}(h,this.force,this.smoothing),this.interpolate){const t=Math.ceil(a/Math.pow(.5*this.radius/this.interpolate,2));if(t>1)for(let a=1;a<t;a++)this.trail.push({x:e.x-i/t*a,y:e.y-s/t*a,age:0,force:h})}}this.trail.push({x:t.x,y:t.y,age:0,force:this.force})}drawTouch(t){const e={x:t.x*this.size,y:(1-t.y)*this.size};let i=1;i=t.age<.3*this.maxAge?this.ease(t.age/(.3*this.maxAge)):this.ease(1-(t.age-.3*this.maxAge)/(.7*this.maxAge)),i*=t.force,this.ctx.globalCompositeOperation=this.blend;const s=this.size*this.radius*i,a=this.ctx.createRadialGradient(e.x,e.y,Math.max(0,.25*s),e.x,e.y,Math.max(0,s));a.addColorStop(0,`rgba(255, 255, 255, ${this.intensity})`),a.addColorStop(1,"rgba(0, 0, 0, 0.0)"),this.ctx.beginPath(),this.ctx.fillStyle=a,this.ctx.arc(e.x,e.y,Math.max(0,s),0,2*Math.PI),this.ctx.fill()}}exports.useTrailTexture=function(i){const s=t.useMemo((()=>new a(i)),[i]);e.useFrame(((t,e)=>{s&&s.update(e)}));const h=t.useCallback((t=>{s.addTouch(t.uv)}),[s]);return{texture:s.texture,onMove:h}};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Texture } from 'three';
|
|
2
|
+
declare type TrailConfig = {
|
|
3
|
+
size?: number;
|
|
4
|
+
maxAge?: number;
|
|
5
|
+
radius?: number;
|
|
6
|
+
intensity?: number;
|
|
7
|
+
interpolate?: number;
|
|
8
|
+
smoothing?: number;
|
|
9
|
+
minForce?: number;
|
|
10
|
+
blend?: CanvasRenderingContext2D['globalCompositeOperation'];
|
|
11
|
+
ease?: (t: number) => number;
|
|
12
|
+
};
|
|
13
|
+
export declare function useTrailTexture(config?: TrailConfig): {
|
|
14
|
+
texture: Texture;
|
|
15
|
+
onMove: (e: any) => void;
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { useMemo, useCallback } from 'react';
|
|
2
|
+
import { useFrame } from '@react-three/fiber';
|
|
3
|
+
import { Texture } from 'three';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Adapted from https://github.com/brunoimbrizi/interactive-particles/blob/master/src/scripts/webgl/particles/TrailTexture.js
|
|
7
|
+
* Changes:
|
|
8
|
+
* * accepts config as constructor params
|
|
9
|
+
* * frame-rate independent aging
|
|
10
|
+
* * added option to interpolate between slow mouse events
|
|
11
|
+
* * added option for smoothing between values to avoid large jumps in force
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// smooth new sample (measurement) based on previous sample (current)
|
|
15
|
+
function smoothAverage(current, measurement, smoothing = 0.9) {
|
|
16
|
+
return measurement * smoothing + current * (1.0 - smoothing);
|
|
17
|
+
} // default ease
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
const easeCircleOut = x => Math.sqrt(1 - Math.pow(x - 1, 2));
|
|
21
|
+
|
|
22
|
+
class TrailTexture {
|
|
23
|
+
constructor({
|
|
24
|
+
size = 64,
|
|
25
|
+
maxAge = 750,
|
|
26
|
+
radius = 0.3,
|
|
27
|
+
intensity = 0.2,
|
|
28
|
+
interpolate = 0,
|
|
29
|
+
smoothing = 0,
|
|
30
|
+
minForce = 0.3,
|
|
31
|
+
blend = 'screen',
|
|
32
|
+
// source-over is canvas default. Others are slower
|
|
33
|
+
ease = easeCircleOut
|
|
34
|
+
} = {}) {
|
|
35
|
+
this.size = size;
|
|
36
|
+
this.maxAge = maxAge;
|
|
37
|
+
this.radius = radius;
|
|
38
|
+
this.intensity = intensity;
|
|
39
|
+
this.ease = ease;
|
|
40
|
+
this.interpolate = interpolate;
|
|
41
|
+
this.smoothing = smoothing;
|
|
42
|
+
this.minForce = minForce;
|
|
43
|
+
this.blend = blend;
|
|
44
|
+
this.trail = [];
|
|
45
|
+
this.force = 0;
|
|
46
|
+
this.initTexture();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
initTexture() {
|
|
50
|
+
this.canvas = document.createElement('canvas');
|
|
51
|
+
this.canvas.width = this.canvas.height = this.size;
|
|
52
|
+
this.ctx = this.canvas.getContext('2d');
|
|
53
|
+
this.ctx.fillStyle = 'black';
|
|
54
|
+
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
55
|
+
this.texture = new Texture(this.canvas);
|
|
56
|
+
this.canvas.id = 'touchTexture';
|
|
57
|
+
this.canvas.style.width = this.canvas.style.height = `${this.canvas.width}px`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
update(delta) {
|
|
61
|
+
this.clear(); // age points
|
|
62
|
+
|
|
63
|
+
this.trail.forEach((point, i) => {
|
|
64
|
+
point.age += delta * 1000; // remove old
|
|
65
|
+
|
|
66
|
+
if (point.age > this.maxAge) {
|
|
67
|
+
this.trail.splice(i, 1);
|
|
68
|
+
}
|
|
69
|
+
}); // reset force when empty (when smoothing)
|
|
70
|
+
|
|
71
|
+
if (!this.trail.length) this.force = 0;
|
|
72
|
+
this.trail.forEach(point => {
|
|
73
|
+
this.drawTouch(point);
|
|
74
|
+
});
|
|
75
|
+
this.texture.needsUpdate = true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
clear() {
|
|
79
|
+
this.ctx.globalCompositeOperation = 'source-over';
|
|
80
|
+
this.ctx.fillStyle = 'black';
|
|
81
|
+
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
addTouch(point) {
|
|
85
|
+
const last = this.trail[this.trail.length - 1];
|
|
86
|
+
|
|
87
|
+
if (last) {
|
|
88
|
+
const dx = last.x - point.x;
|
|
89
|
+
const dy = last.y - point.y;
|
|
90
|
+
const dd = dx * dx + dy * dy;
|
|
91
|
+
const force = Math.max(this.minForce, Math.min(dd * 10000, 1));
|
|
92
|
+
this.force = smoothAverage(force, this.force, this.smoothing);
|
|
93
|
+
|
|
94
|
+
if (!!this.interpolate) {
|
|
95
|
+
const lines = Math.ceil(dd / Math.pow(this.radius * 0.5 / this.interpolate, 2));
|
|
96
|
+
|
|
97
|
+
if (lines > 1) {
|
|
98
|
+
for (let i = 1; i < lines; i++) {
|
|
99
|
+
this.trail.push({
|
|
100
|
+
x: last.x - dx / lines * i,
|
|
101
|
+
y: last.y - dy / lines * i,
|
|
102
|
+
age: 0,
|
|
103
|
+
force
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
this.trail.push({
|
|
111
|
+
x: point.x,
|
|
112
|
+
y: point.y,
|
|
113
|
+
age: 0,
|
|
114
|
+
force: this.force
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
drawTouch(point) {
|
|
119
|
+
const pos = {
|
|
120
|
+
x: point.x * this.size,
|
|
121
|
+
y: (1 - point.y) * this.size
|
|
122
|
+
};
|
|
123
|
+
let intensity = 1;
|
|
124
|
+
|
|
125
|
+
if (point.age < this.maxAge * 0.3) {
|
|
126
|
+
intensity = this.ease(point.age / (this.maxAge * 0.3));
|
|
127
|
+
} else {
|
|
128
|
+
intensity = this.ease(1 - (point.age - this.maxAge * 0.3) / (this.maxAge * 0.7));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
intensity *= point.force; // apply blending
|
|
132
|
+
|
|
133
|
+
this.ctx.globalCompositeOperation = this.blend;
|
|
134
|
+
const radius = this.size * this.radius * intensity;
|
|
135
|
+
const grd = this.ctx.createRadialGradient(pos.x, pos.y, Math.max(0, radius * 0.25), pos.x, pos.y, Math.max(0, radius));
|
|
136
|
+
grd.addColorStop(0, `rgba(255, 255, 255, ${this.intensity})`);
|
|
137
|
+
grd.addColorStop(1, `rgba(0, 0, 0, 0.0)`);
|
|
138
|
+
this.ctx.beginPath();
|
|
139
|
+
this.ctx.fillStyle = grd;
|
|
140
|
+
this.ctx.arc(pos.x, pos.y, Math.max(0, radius), 0, Math.PI * 2);
|
|
141
|
+
this.ctx.fill();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function useTrailTexture(config) {
|
|
147
|
+
const trail = useMemo(() => new TrailTexture(config), [config]);
|
|
148
|
+
useFrame((_, delta) => {
|
|
149
|
+
if (trail) trail.update(delta);
|
|
150
|
+
});
|
|
151
|
+
const onMove = useCallback(e => {
|
|
152
|
+
trail.addTouch(e.uv);
|
|
153
|
+
}, [trail]);
|
|
154
|
+
return {
|
|
155
|
+
texture: trail.texture,
|
|
156
|
+
onMove
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export { useTrailTexture };
|