import React, { useState, useEffect } from 'react'
import { Image, View, StyleSheet } from 'react-native'
interface Props {
uri: string
originalWidth?: number
originalHeight?: number
minWidth?: number
maxWidth?: number
minHeight?: number
maxHeight?: number
borderRadius?: number
style?: object
}
function computeDimensions(
srcWidth: number,
srcHeight: number,
minWidth: number,
maxWidth: number,
minHeight: number,
maxHeight: number,
): { width: number; height: number } {
if (srcWidth <= 0 || srcHeight <= 0) {
return { width: minWidth, height: minHeight }
}
const aspectRatio = srcWidth / srcHeight
// Start from maxWidth and compute height
let width = maxWidth
let height = width / aspectRatio
// If height exceeds maxHeight, clamp by height
if (height > maxHeight) {
height = maxHeight
width = height * aspectRatio
}
// Enforce minimums
if (width < minWidth) {
width = minWidth
height = width / aspectRatio
}
if (height < minHeight) {
height = minHeight
width = height * aspectRatio
}
// Final clamp to maximums after minimum adjustments
width = Math.min(width, maxWidth)
height = Math.min(height, maxHeight)
return { width: Math.round(width), height: Math.round(height) }
}
export function ScaledImage(props: Props): JSX.Element {
const {
uri,
originalWidth,
originalHeight,
minWidth = 120,
maxWidth = 240,
minHeight = 80,
maxHeight = 320,
borderRadius,
style,
} = props
const [dimensions, setDimensions] = useState<{ width: number; height: number } | null>(() => {
if (originalWidth !== undefined && originalHeight !== undefined) {
return computeDimensions(originalWidth, originalHeight, minWidth, maxWidth, minHeight, maxHeight)
}
return null
})
useEffect(() => {
if (originalWidth !== undefined && originalHeight !== undefined) {
setDimensions(
computeDimensions(originalWidth, originalHeight, minWidth, maxWidth, minHeight, maxHeight),
)
return
}
// Use Image.getSize to determine dimensions at runtime
Image.getSize(
uri,
(w, h) => {
setDimensions(computeDimensions(w, h, minWidth, maxWidth, minHeight, maxHeight))
},
() => {
// Fallback to min dimensions on error
setDimensions({ width: minWidth, height: minHeight })
},
)
}, [uri, originalWidth, originalHeight, minWidth, maxWidth, minHeight, maxHeight])
if (!dimensions) {
// Placeholder while size is being resolved
return
}
return (
)
}
const styles = StyleSheet.create({
placeholder: {
backgroundColor: '#e0e0e0',
},
})