Skip to content

Commit c2b2e78

Browse files
authored
Merge pull request #63 from takuma-hmng8/dev
add intersections to DomSyncerObject
2 parents 5c8ca3e + 3ba72fe commit c2b2e78

File tree

10 files changed

+45
-10
lines changed

10 files changed

+45
-10
lines changed

app/domSyncer/DomSyncer.tsx

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as THREE from "three";
2-
import { useEffect, useLayoutEffect, useRef } from "react";
2+
import { useCallback, useEffect, useLayoutEffect, useRef } from "react";
33
import { useFrame, extend, useThree, useLoader } from "@react-three/fiber";
44
import { FxMaterial, FxMaterialProps } from "@/utils/fxMaterial";
55
import {
@@ -50,6 +50,34 @@ export const DomSyncer = ({ state }: { state: number }) => {
5050
[state]
5151
);
5252

53+
const { setFrameloop } = useThree();
54+
const isPlaying = useRef<boolean>(true);
55+
56+
useEffect(() => {
57+
let id: number;
58+
const filterIntersection = () => {
59+
if (domSyncerObj.intersections.some((item) => item)) {
60+
// どっかには交差してる
61+
if (!isPlaying.current) {
62+
setFrameloop("always");
63+
isPlaying.current = true;
64+
}
65+
} else {
66+
// どこにも交差してない
67+
if (isPlaying.current) {
68+
setFrameloop("never");
69+
isPlaying.current = false;
70+
}
71+
}
72+
73+
id = requestAnimationFrame(filterIntersection);
74+
};
75+
id = requestAnimationFrame(filterIntersection);
76+
return () => {
77+
cancelAnimationFrame(id);
78+
};
79+
}, [domSyncerObj.intersections, setFrameloop]);
80+
5381
const domArr = useRef<(HTMLElement | Element)[]>([]);
5482
const contentArr = useRef<HTMLElement[]>([]);
5583

app/domSyncer/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export default function Page() {
9797
</>
9898
)}
9999
</div>
100+
<div style={{ height: "200vh" }}></div>
100101
</>
101102
);
102103
}

packages/use-shader-fx/build/use-shader-fx.js

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/use-shader-fx/build/use-shader-fx.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/use-shader-fx/build/use-shader-fx.umd.cjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ void main() {
527527
alpha *= textureAlpha;
528528
529529
gl_FragColor = vec4(textureColor, alpha);
530-
}`;const tn=({params:t,size:s,scene:o})=>{o.children.length>0&&(o.children.forEach(u=>{u instanceof n.Mesh&&(u.geometry.dispose(),u.material.dispose())}),o.remove(...o.children)),t.texture.forEach((u,e)=>{const l=new n.Mesh(new n.PlaneGeometry(1,1),new n.ShaderMaterial({vertexShader:en,fragmentShader:nn,transparent:!0,uniforms:{u_texture:{value:u},u_textureResolution:{value:new n.Vector2(0,0)},u_resolution:{value:new n.Vector2(0,0)},u_borderRadius:{value:t.boderRadius[e]?t.boderRadius[e]:0}}}));o.add(l)})},rn=()=>{const t=a.useRef([]),s=a.useRef([]);return a.useCallback(({isIntersectingRef:u,isIntersectingOnceRef:e,params:l})=>{t.current.length>0&&t.current.forEach((v,r)=>{v.unobserve(s.current[r])}),s.current=[],t.current=[];const d=new Array(l.dom.length).fill(!1);u.current=[...d],e.current=[...d],l.dom.forEach((v,r)=>{const c=m=>{m.forEach(f=>{l.onIntersect[r]&&l.onIntersect[r](f),u.current[r]=f.isIntersecting})},p=new IntersectionObserver(c,{rootMargin:"0px",threshold:0});p.observe(v),t.current.push(p),s.current.push(v)})},[])},on=()=>{const t=a.useRef([]),s=a.useCallback(({params:o,size:u,resolutionRef:e,scene:l,isIntersectingRef:d})=>{l.children.length!==t.current.length&&(t.current=new Array(l.children.length)),l.children.forEach((v,r)=>{const c=o.dom[r];if(!c){k&&console.warn("DOM is null.");return}const p=c.getBoundingClientRect();if(t.current[r]=p,v.scale.set(p.width,p.height,1),v.position.set(p.left+p.width*.5-u.width*.5,-p.top-p.height*.5+u.height*.5,0),d.current[r]&&(o.rotation[r]&&v.rotation.copy(o.rotation[r]),v instanceof n.Mesh)){const m=v.material;i(m,"u_texture",o.texture[r]),i(m,"u_textureResolution",o.resolution[r]),i(m,"u_resolution",e.current.set(p.width,p.height)),i(m,"u_borderRadius",o.boderRadius[r]?o.boderRadius[r]:0)}})},[]);return[t.current,s]},an=()=>{const t=a.useRef([]),s=a.useRef([]),o=a.useCallback((u,e=!1)=>{t.current.forEach((d,v)=>{d&&(s.current[v]=!0)});const l=e?[...s.current]:[...t.current];return u<0?l:l[u]},[]);return{isIntersectingRef:t,isIntersectingOnceRef:s,isIntersecting:o}},Q={texture:[],dom:[],resolution:[],boderRadius:[],rotation:[],onIntersect:[]},un=({size:t,dpr:s,samples:o=0},u=[])=>{const e=a.useMemo(()=>new n.Scene,[]),l=b(t),[d,v]=D({scene:e,camera:l,size:t,dpr:s,samples:o,isSizeUpdate:!0}),[r,c]=C(Q),[p,m]=on(),f=a.useRef(new n.Vector2(0,0)),[g,h]=a.useState(!0);a.useEffect(()=>{h(!0)},u);const y=rn(),{isIntersectingOnceRef:S,isIntersectingRef:_,isIntersecting:T}=an();return[a.useCallback((E,B)=>{const{gl:R,size:M}=E;return B&&c(B),Qe(r)&&(g&&(tn({params:r,size:M,scene:e}),y({isIntersectingRef:_,isIntersectingOnceRef:S,params:r}),h(!1)),m({params:r,size:M,resolutionRef:f,scene:e,isIntersectingRef:_})),v(R)},[v,c,y,m,g,e,r,S,_]),c,{scene:e,camera:l,renderTarget:d,output:d.texture,isIntersecting:T,DOMRects:p}]};var sn=`precision mediump float;
530+
}`;const tn=({params:t,size:s,scene:o})=>{o.children.length>0&&(o.children.forEach(u=>{u instanceof n.Mesh&&(u.geometry.dispose(),u.material.dispose())}),o.remove(...o.children)),t.texture.forEach((u,e)=>{const l=new n.Mesh(new n.PlaneGeometry(1,1),new n.ShaderMaterial({vertexShader:en,fragmentShader:nn,transparent:!0,uniforms:{u_texture:{value:u},u_textureResolution:{value:new n.Vector2(0,0)},u_resolution:{value:new n.Vector2(0,0)},u_borderRadius:{value:t.boderRadius[e]?t.boderRadius[e]:0}}}));o.add(l)})},rn=()=>{const t=a.useRef([]),s=a.useRef([]);return a.useCallback(({isIntersectingRef:u,isIntersectingOnceRef:e,params:l})=>{t.current.length>0&&t.current.forEach((v,r)=>{v.unobserve(s.current[r])}),s.current=[],t.current=[];const d=new Array(l.dom.length).fill(!1);u.current=[...d],e.current=[...d],l.dom.forEach((v,r)=>{const c=m=>{m.forEach(f=>{l.onIntersect[r]&&l.onIntersect[r](f),u.current[r]=f.isIntersecting})},p=new IntersectionObserver(c,{rootMargin:"0px",threshold:0});p.observe(v),t.current.push(p),s.current.push(v)})},[])},on=()=>{const t=a.useRef([]),s=a.useCallback(({params:o,size:u,resolutionRef:e,scene:l,isIntersectingRef:d})=>{l.children.length!==t.current.length&&(t.current=new Array(l.children.length)),l.children.forEach((v,r)=>{const c=o.dom[r];if(!c){k&&console.warn("DOM is null.");return}const p=c.getBoundingClientRect();if(t.current[r]=p,v.scale.set(p.width,p.height,1),v.position.set(p.left+p.width*.5-u.width*.5,-p.top-p.height*.5+u.height*.5,0),d.current[r]&&(o.rotation[r]&&v.rotation.copy(o.rotation[r]),v instanceof n.Mesh)){const m=v.material;i(m,"u_texture",o.texture[r]),i(m,"u_textureResolution",o.resolution[r]),i(m,"u_resolution",e.current.set(p.width,p.height)),i(m,"u_borderRadius",o.boderRadius[r]?o.boderRadius[r]:0)}})},[]);return[t.current,s]},an=()=>{const t=a.useRef([]),s=a.useRef([]),o=a.useCallback((u,e=!1)=>{t.current.forEach((d,v)=>{d&&(s.current[v]=!0)});const l=e?[...s.current]:[...t.current];return u<0?l:l[u]},[]);return{isIntersectingRef:t,isIntersectingOnceRef:s,isIntersecting:o}},Q={texture:[],dom:[],resolution:[],boderRadius:[],rotation:[],onIntersect:[]},un=({size:t,dpr:s,samples:o=0},u=[])=>{const e=a.useMemo(()=>new n.Scene,[]),l=b(t),[d,v]=D({scene:e,camera:l,size:t,dpr:s,samples:o,isSizeUpdate:!0}),[r,c]=C(Q),[p,m]=on(),f=a.useRef(new n.Vector2(0,0)),[g,h]=a.useState(!0);a.useEffect(()=>{h(!0)},u);const y=rn(),{isIntersectingOnceRef:S,isIntersectingRef:_,isIntersecting:T}=an();return[a.useCallback((E,B)=>{const{gl:R,size:M}=E;return B&&c(B),Qe(r)&&(g&&(tn({params:r,size:M,scene:e}),y({isIntersectingRef:_,isIntersectingOnceRef:S,params:r}),h(!1)),m({params:r,size:M,resolutionRef:f,scene:e,isIntersectingRef:_})),v(R)},[v,c,y,m,g,e,r,S,_]),c,{scene:e,camera:l,renderTarget:d,output:d.texture,isIntersecting:T,DOMRects:p,intersections:_.current}]};var sn=`precision mediump float;
531531
532532
varying vec2 vUv;
533533

packages/use-shader-fx/build/use-shader-fx.umd.cjs.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/use-shader-fx/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/use-shader-fx/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@hmng8/use-shader-fx",
3-
"version": "1.0.40",
3+
"version": "1.0.41",
44
"description": "The only difficult part is coding the shaders",
55
"main": "./build/use-shader-fx.umd.cjs",
66
"module": "./build/use-shader-fx.js",

packages/use-shader-fx/src/hooks/useDomSyncer/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ export type DomSyncerObject = {
3838
* @param once - If set to true, it will continue to return true once crossed.
3939
*/
4040
isIntersecting: IsIntersecting;
41-
/** Returns the target's DOMRect[] */
41+
/** target's DOMRect[] */
4242
DOMRects: DOMRect[];
43+
/** target's intersetions boolean[] */
44+
intersections: boolean[];
4345
};
4446

4547
export const DOMSYNCER_PARAMS: DomSyncerParams = {
@@ -143,6 +145,7 @@ export const useDomSyncer = (
143145
output: renderTarget.texture,
144146
isIntersecting: isIntersecting,
145147
DOMRects: DOMRects,
148+
intersections: isIntersectingRef.current,
146149
},
147150
];
148151
};

packages/use-shader-fx/types/hooks/useDomSyncer/index.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ export type DomSyncerObject = {
2828
* @param once - If set to true, it will continue to return true once crossed.
2929
*/
3030
isIntersecting: IsIntersecting;
31-
/** Returns the target's DOMRect[] */
31+
/** target's DOMRect[] */
3232
DOMRects: DOMRect[];
33+
/** target's intersetions boolean[] */
34+
intersections: boolean[];
3335
};
3436
export declare const DOMSYNCER_PARAMS: DomSyncerParams;
3537
/**

0 commit comments

Comments
 (0)