From c918df01f7bfb192fc48fc74ccfff1ea3a051d51 Mon Sep 17 00:00:00 2001 From: Antoine BERNIER Date: Tue, 25 Apr 2023 23:11:34 +0200 Subject: [PATCH] feat(Resize): new component (#1420) --- .storybook/stories/Resize.stories.tsx | 45 ++++++++++++++++++++++++ README.md | 35 +++++++++++++++++++ src/core/Resize.tsx | 49 +++++++++++++++++++++++++++ src/core/index.ts | 1 + 4 files changed, 130 insertions(+) create mode 100644 .storybook/stories/Resize.stories.tsx create mode 100644 src/core/Resize.tsx diff --git a/.storybook/stories/Resize.stories.tsx b/.storybook/stories/Resize.stories.tsx new file mode 100644 index 000000000..c5a00bea4 --- /dev/null +++ b/.storybook/stories/Resize.stories.tsx @@ -0,0 +1,45 @@ +import * as THREE from 'three' +import * as React from 'react' +import { withKnobs } from '@storybook/addon-knobs' + +import { Setup } from '../Setup' + +import { Box, Resize, ResizeProps } from '../../src' + +export default { + title: 'Staging/Resize', + component: Resize, + decorators: [ + withKnobs, + (storyFn) => ( + + {storyFn()} + + ), + ], +} + +export const ResizeSt = ({ width, height, depth }: ResizeProps) => ( + <> + + + + + + + + +) +ResizeSt.args = { + width: undefined, + height: undefined, + depth: undefined, +} + +ResizeSt.argTypes = { + width: { control: { type: 'boolean' } }, + height: { control: { type: 'boolean' } }, + depth: { control: { type: 'boolean' } }, +} + +ResizeSt.storyName = 'Default' diff --git a/README.md b/README.md index d1e6f9d33..42d9710b1 100644 --- a/README.md +++ b/README.md @@ -3122,6 +3122,41 @@ function ScaledModel() { ``` +#### Resize + +[![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.pmnd.rs/?path=/story/staging-resize) + +Calculates a boundary box and scales its children so the highest dimension is constrained by 1. NB: proportions are preserved. + +```tsx +export type ResizeProps = JSX.IntrinsicElements['group'] & { + /** constrained by width dimension (x axis), undefined */ + width?: boolean + /** constrained by height dimension (y axis), undefined */ + height?: boolean + /** constrained by depth dimension (z axis), undefined */ + depth?: boolean + /** You can optionally pass the Box3, otherwise will be computed, undefined */ + box3?: THREE.Box3 + /** See https://threejs.org/docs/index.html?q=box3#api/en/math/Box3.setFromObject */ + precise?: boolean +} +``` + +```jsx + + + +``` + +You can also specify the dimension to be constrained by: + +```jsx + + + +``` + #### BBAnchor [![](https://img.shields.io/badge/-storybook-%23ff69b4)](https://drei.vercel.app/?path=/story/misc-bbanchor--bb-anchor-with-html) diff --git a/src/core/Resize.tsx b/src/core/Resize.tsx new file mode 100644 index 000000000..50f6e8412 --- /dev/null +++ b/src/core/Resize.tsx @@ -0,0 +1,49 @@ +import * as THREE from 'three' +import * as React from 'react' + +export type ResizeProps = JSX.IntrinsicElements['group'] & { + /** Whether to fit into width (x axis), undefined */ + width?: boolean + /** Whether to fit into height (y axis), undefined */ + height?: boolean + /** Whether to fit into depth (z axis), undefined */ + depth?: boolean + /** You can optionally pass the Box3, otherwise will be computed, undefined */ + box3?: THREE.Box3 + /** See https://threejs.org/docs/index.html?q=box3#api/en/math/Box3.setFromObject */ + precise?: boolean +} + +export const Resize = React.forwardRef( + ({ children, width, height, depth, box3, precise = true, ...props }, fRef) => { + const ref = React.useRef(null!) + const outer = React.useRef(null!) + const inner = React.useRef(null!) + + React.useLayoutEffect(() => { + outer.current.matrixWorld.identity() + + box3 ||= new THREE.Box3().setFromObject(inner.current, precise) + const w = box3.max.x - box3.min.x + const h = box3.max.y - box3.min.y + const d = box3.max.z - box3.min.z + + let dimension = Math.max(w, h, d) + if (width) dimension = w + if (height) dimension = h + if (depth) dimension = d + + outer.current.scale.setScalar(1 / dimension) + }, [width, height, depth, box3, precise]) + + React.useImperativeHandle(fRef, () => ref.current, []) + + return ( + + + {children} + + + ) + } +) diff --git a/src/core/index.ts b/src/core/index.ts index 8370c5348..35124fda6 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -93,6 +93,7 @@ export * from './ScreenQuad' // Staging/Prototyping export * from './Center' +export * from './Resize' export * from './Bounds' export * from './CameraShake' export * from './Float'