diff --git a/README.md b/README.md index 52468b1c..161bd741 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ yarn add @react-native-community/hooks - [useCameraRoll](https://github.com/react-native-community/hooks#usecameraroll) - [useClipboard](https://github.com/react-native-community/hooks#useclipboard) - [useDimensions](https://github.com/react-native-community/hooks#usedimensions) +- [useImageDimensions](https://github.com/react-native-community/hooks#useImageDimensions) - [useKeyboard](https://github.com/react-native-community/hooks#usekeyboard) - [useInteractionManager](https://github.com/react-native-community/hooks#useinteractionmanager) - [useDeviceOrientation](https://github.com/react-native-community/hooks#usedeviceorientation) @@ -104,6 +105,23 @@ const { width, height } = useDimensions().window const screen = useDimensions().screen ``` +### `useImageDimensions` + +```js +import {useImageDimensions} from '@react-native-community/hooks' + +const source = require('./assets/yourImage.png') +// or +const source = {uri: 'https://your.image.URI'} + +const {dimensions, loading, error} = useImageDimensions(source) + +if(loading || error || !dimensions) { + return null +} +const {width, height, aspectRatio} = dimensions +``` + ### `useKeyboard` ```js diff --git a/src/index.ts b/src/index.ts index d8dc4d6f..a81ef316 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,6 +8,7 @@ import {useKeyboard} from './useKeyboard' import {useInteractionManager} from './useInteractionManager' import {useDeviceOrientation} from './useDeviceOrientation' import {useLayout} from './useLayout' +import {useImageDimensions} from './useImageDimensions' export { useDimensions, @@ -20,4 +21,5 @@ export { useInteractionManager, useDeviceOrientation, useLayout, + useImageDimensions, } diff --git a/src/useImageDimensions.ts b/src/useImageDimensions.ts new file mode 100644 index 00000000..60972d77 --- /dev/null +++ b/src/useImageDimensions.ts @@ -0,0 +1,59 @@ +import {useEffect, useState} from 'react' +import {Image, ImageRequireSource} from 'react-native' + +export interface URISource { + uri: string +} + +export type Source = ImageRequireSource | URISource + +export interface ImageDimensions { + dimensions?: {width: number; height: number; aspectRatio: number} + error?: Error + loading: boolean +} + +/** + * @param source either a remote URL or a local file resource. + * @returns original image dimensions (width, height and aspect ratio). + */ +export function useImageDimensions(source: Source): ImageDimensions { + const [result, setResult] = useState({loading: true}) + + useEffect(() => { + try { + if (typeof source === 'number') { + const {width, height} = Image.resolveAssetSource(source) + + setResult({ + dimensions: {width, height, aspectRatio: width / height}, + loading: false, + }) + + return + } + + if (typeof source === 'object' && source.uri) { + setResult({loading: true}) + + Image.getSize( + source.uri, + (width, height) => + setResult({ + dimensions: {width, height, aspectRatio: width / height}, + loading: false, + }), + (error) => setResult({error, loading: false}), + ) + + return + } + + throw new Error('not implemented') + } catch (error) { + setResult({error, loading: false}) + } + }, [source]) + + return result +}