Skip to content

Commit

Permalink
feat: add VFXProps.intersection
Browse files Browse the repository at this point in the history
  • Loading branch information
fand committed Jul 23, 2024
1 parent e8d6432 commit c305973
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 9 deletions.
9 changes: 9 additions & 0 deletions packages/vfx-js/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ export type VFXProps = {
*/
overlay?: true | number;

intersection?: {
threshold?: number;
};

/**
* Allow shader outputs to oveflow the original element area. (Default: `0`)
*
Expand Down Expand Up @@ -183,6 +187,11 @@ export type VFXElement = {
isGif: boolean;
isFullScreen: boolean;
overflow: Rect;
intersection: VFXElementIntersection;
originalOpacity: number;
zIndex: number;
};

export type VFXElementIntersection = {
threshold: number;
};
43 changes: 34 additions & 9 deletions packages/vfx-js/src/vfx-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,15 @@ import {
VFXElementType,
VFXUniformValue,
VFXWrap,
VFXElementIntersection,
} from "./types";
import { createRect, growRect, Rect, RECT_ZERO } from "./rect.js";
import {
createRect,
getIntersection,
growRect,
Rect,
RECT_ZERO,
} from "./rect.js";

const gifFor = new Map<HTMLElement, GIFData>();

Expand Down Expand Up @@ -165,8 +172,15 @@ export class VFXPlayer {

const rect = element.getBoundingClientRect();
const [isFullScreen, overflow] = sanitizeOverflow(opts.overflow);
const intersection = sanitizeIntersection(opts.intersection);
const isInViewport =
isFullScreen || isRectInViewport(this.#viewport, rect, overflow);
isFullScreen ||
isRectInViewport(
this.#viewport,
rect,
overflow,
intersection.threshold,
);

const originalOpacity =
element.style.opacity === ""
Expand Down Expand Up @@ -276,6 +290,7 @@ export class VFXPlayer {
isGif,
isFullScreen,
overflow,
intersection,
originalOpacity,
zIndex: opts.zIndex ?? 0,
};
Expand Down Expand Up @@ -352,7 +367,12 @@ export class VFXPlayer {
// Check intersection
const isInViewport =
e.isFullScreen ||
isRectInViewport(this.#viewport, rect, e.overflow);
isRectInViewport(
this.#viewport,
rect,
e.overflow,
e.intersection.threshold,
);

// entering
if (isInViewport && !e.isInViewport) {
Expand Down Expand Up @@ -443,14 +463,10 @@ export function isRectInViewport(
viewport: Rect,
rect: Rect,
overflow: Rect,
threshold: number,
): boolean {
const rect2 = growRect(rect, overflow);
return (
rect2.left <= viewport.right &&
rect2.right >= viewport.left &&
rect2.top <= viewport.bottom &&
rect2.bottom >= viewport.top
);
return getIntersection(viewport, rect2) > threshold;
}

export function sanitizeOverflow(
Expand All @@ -465,6 +481,15 @@ export function sanitizeOverflow(
return [false, createRect(overflow)];
}

export function sanitizeIntersection(
intersectionOpts: VFXProps["intersection"],
): VFXElementIntersection {
const threshold = intersectionOpts?.threshold ?? 0;
return {
threshold,
};
}

function parseWrapSingle(wrapOpt: VFXWrap): THREE.Wrapping {
if (wrapOpt === "repeat") {
return THREE.RepeatWrapping;
Expand Down

0 comments on commit c305973

Please sign in to comment.