@react-three/drei 9.103.0 → 9.103.1

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 CHANGED
@@ -926,6 +926,14 @@ type PivotControlsProps = {
926
926
  autoTransform?: boolean
927
927
  /** Allows you to switch individual axes off */
928
928
  activeAxes?: [boolean, boolean, boolean]
929
+ /** Allows you to disable translation via axes arrows */
930
+ disableAxes?: boolean
931
+ /** Allows you to disable translation via axes planes */
932
+ disableSliders?: boolean
933
+ /** Allows you to disable rotation */
934
+ disableRotations?: boolean
935
+ /** Allows you to disable scaling */
936
+ disableScaling?: boolean
929
937
  /** RGB colors */
930
938
  axisColors?: [string | number, string | number, string | number]
931
939
  /** Color of the hovered item */
@@ -1082,6 +1090,8 @@ export type GridMaterialType = {
1082
1090
  fadeDistance?: number
1083
1091
  /** Fade strength, default: 1 */
1084
1092
  fadeStrength?: number
1093
+ /** Fade from camera (1) or origin (0), or somewhere in between, default: camera */
1094
+ fadeFrom?: number;
1085
1095
  }
1086
1096
 
1087
1097
  export type GridProps = GridMaterialType & {
@@ -3272,7 +3282,7 @@ function VideoMaterial({ src }) {
3272
3282
 
3273
3283
  NB: It's important to wrap `VideoMaterial` into `React.Suspense` since, `useVideoTexture(src)` here will be suspended until the user shares its screen.
3274
3284
 
3275
- HLS - useVideoTexture supports .m3u8 HLS manifest via (https://github.com/video-dev/hls.js).
3285
+ HLS - useVideoTexture supports .m3u8 HLS manifest via (https://github.com/video-dev/hls.js).
3276
3286
 
3277
3287
  You can fine-tune via the hls configuration:
3278
3288
 
@@ -3281,7 +3291,8 @@ You can fine-tune via the hls configuration:
3281
3291
  hls: { abrEwmaFastLive: 1.0, abrEwmaSlowLive: 3.0, enableWorker: true }
3282
3292
  })
3283
3293
  ```
3284
- >Available options: https://github.com/video-dev/hls.js/blob/master/docs/API.md#fine-tuning
3294
+
3295
+ > Available options: https://github.com/video-dev/hls.js/blob/master/docs/API.md#fine-tuning
3285
3296
 
3286
3297
  #### useTrailTexture
3287
3298
 
package/core/Grid.cjs.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),n=require("react"),o=require("three"),i=require("@react-three/fiber"),r=require("./shaderMaterial.cjs.js"),t=require("../helpers/constants.cjs.js");function l(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function a(e){if(e&&e.__esModule)return e;var n=Object.create(null);return e&&Object.keys(e).forEach((function(o){if("default"!==o){var i=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(n,o,i.get?i:{enumerable:!0,get:function(){return e[o]}})}})),n.default=e,Object.freeze(n)}var s=l(e),c=a(n),f=a(o);const d=r.shaderMaterial({cellSize:.5,sectionSize:1,fadeDistance:100,fadeStrength:1,cellThickness:.5,sectionThickness:1,cellColor:new f.Color,sectionColor:new f.Color,infiniteGrid:!1,followCamera:!1,worldCamProjPosition:new f.Vector3,worldPlanePosition:new f.Vector3},"\n varying vec3 localPosition;\n varying vec4 worldPosition;\n\n uniform vec3 worldCamProjPosition;\n uniform vec3 worldPlanePosition;\n uniform float fadeDistance;\n uniform bool infiniteGrid;\n uniform bool followCamera;\n\n void main() {\n localPosition = position.xzy;\n if (infiniteGrid) localPosition *= 1.0 + fadeDistance;\n \n worldPosition = modelMatrix * vec4(localPosition, 1.0);\n if (followCamera) {\n worldPosition.xyz += (worldCamProjPosition - worldPlanePosition);\n localPosition = (inverse(modelMatrix) * worldPosition).xyz;\n }\n\n gl_Position = projectionMatrix * viewMatrix * worldPosition;\n }\n ",`\n varying vec3 localPosition;\n varying vec4 worldPosition;\n\n uniform vec3 worldCamProjPosition;\n uniform float cellSize;\n uniform float sectionSize;\n uniform vec3 cellColor;\n uniform vec3 sectionColor;\n uniform float fadeDistance;\n uniform float fadeStrength;\n uniform float cellThickness;\n uniform float sectionThickness;\n\n float getGrid(float size, float thickness) {\n vec2 r = localPosition.xz / size;\n vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);\n float line = min(grid.x, grid.y) + 1.0 - thickness;\n return 1.0 - min(line, 1.0);\n }\n\n void main() {\n float g1 = getGrid(cellSize, cellThickness);\n float g2 = getGrid(sectionSize, sectionThickness);\n\n float dist = distance(worldCamProjPosition, worldPosition.xyz);\n float d = 1.0 - min(dist / fadeDistance, 1.0);\n vec3 color = mix(cellColor, sectionColor, min(1.0, sectionThickness * g2));\n\n gl_FragColor = vec4(color, (g1 + g2) * pow(d, fadeStrength));\n gl_FragColor.a = mix(0.75 * gl_FragColor.a, gl_FragColor.a, g2);\n if (gl_FragColor.a <= 0.0) discard;\n\n #include <tonemapping_fragment>\n #include <${t.version>=154?"colorspace_fragment":"encodings_fragment"}>\n }\n `),u=c.forwardRef((({args:e,cellColor:n="#000000",sectionColor:o="#2080ff",cellSize:r=.5,sectionSize:t=1,followCamera:l=!1,infiniteGrid:a=!1,fadeDistance:u=100,fadeStrength:m=1,cellThickness:g=.5,sectionThickness:P=1,side:w=f.BackSide,...v},C)=>{i.extend({GridMaterial:d});const h=c.useRef(null);c.useImperativeHandle(C,(()=>h.current),[]);const p=new f.Plane,x=new f.Vector3(0,1,0),j=new f.Vector3(0,0,0);i.useFrame((e=>{p.setFromNormalAndCoplanarPoint(x,j).applyMatrix4(h.current.matrixWorld);const n=h.current.material,o=n.uniforms.worldCamProjPosition,i=n.uniforms.worldPlanePosition;p.projectPoint(e.camera.position,o.value),i.value.set(0,0,0).applyMatrix4(h.current.matrixWorld)}));const z={cellSize:r,sectionSize:t,cellColor:n,sectionColor:o,cellThickness:g,sectionThickness:P},y={fadeDistance:u,fadeStrength:m,infiniteGrid:a,followCamera:l};return c.createElement("mesh",s.default({ref:h,frustumCulled:!1},v),c.createElement("gridMaterial",s.default({transparent:!0,"extensions-derivatives":!0,side:w},z,y)),c.createElement("planeGeometry",{args:e}))}));exports.Grid=u;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),n=require("react"),o=require("three"),i=require("@react-three/fiber"),r=require("./shaderMaterial.cjs.js"),t=require("../helpers/constants.cjs.js");function l(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function a(e){if(e&&e.__esModule)return e;var n=Object.create(null);return e&&Object.keys(e).forEach((function(o){if("default"!==o){var i=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(n,o,i.get?i:{enumerable:!0,get:function(){return e[o]}})}})),n.default=e,Object.freeze(n)}var s=l(e),c=a(n),f=a(o);const d=r.shaderMaterial({cellSize:.5,sectionSize:1,fadeDistance:100,fadeStrength:1,fadeFrom:1,cellThickness:.5,sectionThickness:1,cellColor:new f.Color,sectionColor:new f.Color,infiniteGrid:!1,followCamera:!1,worldCamProjPosition:new f.Vector3,worldPlanePosition:new f.Vector3},"\n varying vec3 localPosition;\n varying vec4 worldPosition;\n\n uniform vec3 worldCamProjPosition;\n uniform vec3 worldPlanePosition;\n uniform float fadeDistance;\n uniform bool infiniteGrid;\n uniform bool followCamera;\n\n void main() {\n localPosition = position.xzy;\n if (infiniteGrid) localPosition *= 1.0 + fadeDistance;\n \n worldPosition = modelMatrix * vec4(localPosition, 1.0);\n if (followCamera) {\n worldPosition.xyz += (worldCamProjPosition - worldPlanePosition);\n localPosition = (inverse(modelMatrix) * worldPosition).xyz;\n }\n\n gl_Position = projectionMatrix * viewMatrix * worldPosition;\n }\n ",`\n varying vec3 localPosition;\n varying vec4 worldPosition;\n\n uniform vec3 worldCamProjPosition;\n uniform float cellSize;\n uniform float sectionSize;\n uniform vec3 cellColor;\n uniform vec3 sectionColor;\n uniform float fadeDistance;\n uniform float fadeStrength;\n uniform float fadeFrom;\n uniform float cellThickness;\n uniform float sectionThickness;\n\n float getGrid(float size, float thickness) {\n vec2 r = localPosition.xz / size;\n vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);\n float line = min(grid.x, grid.y) + 1.0 - thickness;\n return 1.0 - min(line, 1.0);\n }\n\n void main() {\n float g1 = getGrid(cellSize, cellThickness);\n float g2 = getGrid(sectionSize, sectionThickness);\n\n vec3 from = worldCamProjPosition*vec3(fadeFrom);\n float dist = distance(from, worldPosition.xyz);\n float d = 1.0 - min(dist / fadeDistance, 1.0);\n vec3 color = mix(cellColor, sectionColor, min(1.0, sectionThickness * g2));\n\n gl_FragColor = vec4(color, (g1 + g2) * pow(d, fadeStrength));\n gl_FragColor.a = mix(0.75 * gl_FragColor.a, gl_FragColor.a, g2);\n if (gl_FragColor.a <= 0.0) discard;\n\n #include <tonemapping_fragment>\n #include <${t.version>=154?"colorspace_fragment":"encodings_fragment"}>\n }\n `),m=c.forwardRef((({args:e,cellColor:n="#000000",sectionColor:o="#2080ff",cellSize:r=.5,sectionSize:t=1,followCamera:l=!1,infiniteGrid:a=!1,fadeDistance:m=100,fadeStrength:u=1,fadeFrom:g=1,cellThickness:P=.5,sectionThickness:v=1,side:w=f.BackSide,...C},h)=>{i.extend({GridMaterial:d});const p=c.useRef(null);c.useImperativeHandle(h,(()=>p.current),[]);const x=new f.Plane,j=new f.Vector3(0,1,0),z=new f.Vector3(0,0,0);i.useFrame((e=>{x.setFromNormalAndCoplanarPoint(j,z).applyMatrix4(p.current.matrixWorld);const n=p.current.material,o=n.uniforms.worldCamProjPosition,i=n.uniforms.worldPlanePosition;x.projectPoint(e.camera.position,o.value),i.value.set(0,0,0).applyMatrix4(p.current.matrixWorld)}));const y={cellSize:r,sectionSize:t,cellColor:n,sectionColor:o,cellThickness:P,sectionThickness:v},S={fadeDistance:m,fadeStrength:u,fadeFrom:g,infiniteGrid:a,followCamera:l};return c.createElement("mesh",s.default({ref:p,frustumCulled:!1},C),c.createElement("gridMaterial",s.default({transparent:!0,"extensions-derivatives":!0,side:w},y,S)),c.createElement("planeGeometry",{args:e}))}));exports.Grid=m;
package/core/Grid.d.ts CHANGED
@@ -11,6 +11,7 @@ export type GridMaterialType = {
11
11
  infiniteGrid?: boolean;
12
12
  fadeDistance?: number;
13
13
  fadeStrength?: number;
14
+ fadeFrom?: number;
14
15
  side?: THREE.Side;
15
16
  };
16
17
  export type GridProps = GridMaterialType & {
package/core/Grid.js CHANGED
@@ -10,6 +10,7 @@ const GridMaterial = /* @__PURE__ */shaderMaterial({
10
10
  sectionSize: 1,
11
11
  fadeDistance: 100,
12
12
  fadeStrength: 1,
13
+ fadeFrom: 1,
13
14
  cellThickness: 0.5,
14
15
  sectionThickness: 1,
15
16
  cellColor: /* @__PURE__ */new THREE.Color(),
@@ -51,6 +52,7 @@ const GridMaterial = /* @__PURE__ */shaderMaterial({
51
52
  uniform vec3 sectionColor;
52
53
  uniform float fadeDistance;
53
54
  uniform float fadeStrength;
55
+ uniform float fadeFrom;
54
56
  uniform float cellThickness;
55
57
  uniform float sectionThickness;
56
58
 
@@ -65,7 +67,8 @@ const GridMaterial = /* @__PURE__ */shaderMaterial({
65
67
  float g1 = getGrid(cellSize, cellThickness);
66
68
  float g2 = getGrid(sectionSize, sectionThickness);
67
69
 
68
- float dist = distance(worldCamProjPosition, worldPosition.xyz);
70
+ vec3 from = worldCamProjPosition*vec3(fadeFrom);
71
+ float dist = distance(from, worldPosition.xyz);
69
72
  float d = 1.0 - min(dist / fadeDistance, 1.0);
70
73
  vec3 color = mix(cellColor, sectionColor, min(1.0, sectionThickness * g2));
71
74
 
@@ -87,6 +90,7 @@ const Grid = /* @__PURE__ */React.forwardRef(({
87
90
  infiniteGrid = false,
88
91
  fadeDistance = 100,
89
92
  fadeStrength = 1,
93
+ fadeFrom = 1,
90
94
  cellThickness = 0.5,
91
95
  sectionThickness = 1,
92
96
  side = THREE.BackSide,
@@ -119,6 +123,7 @@ const Grid = /* @__PURE__ */React.forwardRef(({
119
123
  const uniforms2 = {
120
124
  fadeDistance,
121
125
  fadeStrength,
126
+ fadeFrom,
122
127
  infiniteGrid,
123
128
  followCamera
124
129
  };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("three"),r=require("@react-three/fiber"),t=require("react");const u=e=>e===Object(e)&&!Array.isArray(e)&&"function"!=typeof e;function o(o,s){const a=r.useThree((e=>e.gl)),c=r.useLoader(e.TextureLoader,u(o)?Object.values(o):o);t.useLayoutEffect((()=>{null==s||s(c)}),[s]),t.useEffect((()=>{if("initTexture"in a){(Array.isArray(c)?c:[c]).forEach(a.initTexture)}}),[a,c]);return t.useMemo((()=>{if(u(o)){const e={};let r=0;for(const t in o)e[t]=c[r++];return e}return c}),[o,c])}o.preload=t=>r.useLoader.preload(e.TextureLoader,t),o.clear=t=>r.useLoader.clear(e.TextureLoader,t),exports.IsObject=u,exports.useTexture=o;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("three"),r=require("@react-three/fiber"),t=require("react");const u=e=>e===Object(e)&&!Array.isArray(e)&&"function"!=typeof e;function o(o,s){const a=r.useThree((e=>e.gl)),c=r.useLoader(e.TextureLoader,u(o)?Object.values(o):o);t.useLayoutEffect((()=>{null==s||s(c)}),[s]),t.useEffect((()=>{if("initTexture"in a){let r=[];Array.isArray(c)?r=c:c instanceof e.Texture?r=[c]:u(c)&&(r=Object.values(c)),r.forEach((r=>{r instanceof e.Texture&&a.initTexture(r)}))}}),[a,c]);return t.useMemo((()=>{if(u(o)){const e={};let r=0;for(const t in o)e[t]=c[r++];return e}return c}),[o,c])}o.preload=t=>r.useLoader.preload(e.TextureLoader,t),o.clear=t=>r.useLoader.clear(e.TextureLoader,t),exports.IsObject=u,exports.useTexture=o;
@@ -1,10 +1,14 @@
1
1
  import { Texture } from 'three';
2
- export declare const IsObject: (url: any) => url is Record<string, string>;
3
- export type MappedTextureType<T extends string[] | string | Record<string, string>> = T extends any[] ? Texture[] : T extends Record<string, string> ? {
2
+ export declare const IsObject: (url: unknown) => url is Record<string, string>;
3
+ type TextureArray<T> = T extends string[] ? Texture[] : never;
4
+ type TextureRecord<T> = T extends Record<string, string> ? {
4
5
  [key in keyof T]: Texture;
5
- } : Texture;
6
+ } : never;
7
+ type SingleTexture<T> = T extends string ? Texture : never;
8
+ export type MappedTextureType<T extends string[] | string | Record<string, string>> = TextureArray<T> | TextureRecord<T> | SingleTexture<T>;
6
9
  export declare function useTexture<Url extends string[] | string | Record<string, string>>(input: Url, onLoad?: (texture: MappedTextureType<Url>) => void): MappedTextureType<Url>;
7
10
  export declare namespace useTexture {
8
- var preload: (url: string) => undefined;
11
+ var preload: (url: string | string[]) => undefined;
9
12
  var clear: (input: string | string[]) => void;
10
13
  }
14
+ export {};
@@ -1,4 +1,4 @@
1
- import { TextureLoader } from 'three';
1
+ import { TextureLoader, Texture } from 'three';
2
2
  import { useThree, useLoader } from '@react-three/fiber';
3
3
  import { useLayoutEffect, useEffect, useMemo } from 'react';
4
4
 
@@ -15,8 +15,19 @@ function useTexture(input, onLoad) {
15
15
  // NOTE: only available for WebGLRenderer
16
16
  useEffect(() => {
17
17
  if ('initTexture' in gl) {
18
- const array = Array.isArray(textures) ? textures : [textures];
19
- array.forEach(gl.initTexture);
18
+ let textureArray = [];
19
+ if (Array.isArray(textures)) {
20
+ textureArray = textures;
21
+ } else if (textures instanceof Texture) {
22
+ textureArray = [textures];
23
+ } else if (IsObject(textures)) {
24
+ textureArray = Object.values(textures);
25
+ }
26
+ textureArray.forEach(texture => {
27
+ if (texture instanceof Texture) {
28
+ gl.initTexture(texture);
29
+ }
30
+ });
20
31
  }
21
32
  }, [gl, textures]);
22
33
  const mappedTextures = useMemo(() => {
@@ -1 +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=256,maxAge:e=750,radius:i=.3,intensity:a=.2,interpolate:h=0,smoothing:r=0,minForce:c=.3,blend:n="screen",ease:o=s}={}){this.size=t,this.maxAge=e,this.radius=i,this.intensity=a,this.ease=o,this.interpolate=h,this.smoothing=r,this.minForce=c,this.blend=n,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{size:s,maxAge:h,radius:r,intensity:c,interpolate:n,smoothing:o,minForce:l,blend:x,ease:u}=i,d=t.useMemo((()=>new a(i)),[s,h,r,c,n,o,l,x,u]);e.useFrame(((t,e)=>{d.update(e)}));const g=t.useCallback((t=>d.addTouch(t.uv)),[d]);return[d.texture,g]};
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=256,maxAge:e=750,radius:i=.3,intensity:a=.2,interpolate:h=0,smoothing:r=0,minForce:c=.3,blend:n="screen",ease:o=s}={}){this.size=t,this.maxAge=e,this.radius=i,this.intensity=a,this.ease=o,this.interpolate=h,this.smoothing=r,this.minForce=c,this.blend=n,this.trail=[],this.force=0,this.initTexture()}initTexture(){this.canvas=document.createElement("canvas"),this.canvas.width=this.canvas.height=this.size;const t=this.canvas.getContext("2d");if(null===t)throw new Error("2D not available");this.ctx=t,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{size:s,maxAge:h,radius:r,intensity:c,interpolate:n,smoothing:o,minForce:l,blend:x,ease:u}=i,d=t.useMemo((()=>new a(i)),[s,h,r,c,n,o,l,x,u]);e.useFrame(((t,e)=>{d.update(e)}));const g=t.useCallback((t=>d.addTouch(t.uv)),[d]);return[d.texture,g]};
@@ -2,15 +2,6 @@ import { useMemo, useCallback } from 'react';
2
2
  import { useFrame } from '@react-three/fiber';
3
3
  import { Texture } from 'three';
4
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
5
  // smooth new sample (measurement) based on previous sample (current)
15
6
  function smoothAverage(current, measurement, smoothing = 0.9) {
16
7
  return measurement * smoothing + current * (1.0 - smoothing);
@@ -47,7 +38,11 @@ class TrailTexture {
47
38
  initTexture() {
48
39
  this.canvas = document.createElement('canvas');
49
40
  this.canvas.width = this.canvas.height = this.size;
50
- this.ctx = this.canvas.getContext('2d');
41
+ const ctx = this.canvas.getContext('2d');
42
+ if (ctx === null) {
43
+ throw new Error('2D not available');
44
+ }
45
+ this.ctx = ctx;
51
46
  this.ctx.fillStyle = 'black';
52
47
  this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
53
48
  this.texture = new Texture(this.canvas);