expo-duooomi-app/@share/components/Img.tsx

97 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Image as ExpoImage, type ImageProps as ExpoImageProps } from 'expo-image'
import React, { forwardRef, memo, useMemo } from 'react'
import tw from 'twrnc'
interface ImgProps extends ExpoImageProps {
className?: string
src?: string | number
width?: number
isWebP?: boolean
errorSource?: string | number
isCompression?: boolean
/** 自定义缓存键,用于需要重定向的 URL */
cacheKey?: string
}
// ExpoImage.clearDiskCache()
// ExpoImage.clearMemoryCache()
// cloudflare 图片优化服务示例地址
const ImageOrigin = `https://bowong.cc/cdn-cgi/image/width=128,quality=75,format=webp/https://cdn.roasmax.cn/material/b59b75841c484d8bafec9c5636930b69.webp`
const Img = forwardRef<ExpoImage, ImgProps>((props, ref) => {
const {
className = '',
style = {},
src,
errorSource,
source: propSource,
cacheKey,
width = 256,
isCompression = false,
isWebP = true,
...reset
} = props
const imageStyle = tw`${className}`
// 静态图全部压缩jpg
const compressionUrl = useMemo(() => {
const f = isWebP ? 'webp' : 'jpg'
return `https://bowong.cc/cdn-cgi/image/width=${width},quality=75,format=${f}/${src}`
}, [width, isWebP, src])
// 判断是否为网络图片
const isNetworkImage = (uri: string | number): boolean => {
if (typeof uri !== 'string') return false
return uri.startsWith('http://') || uri.startsWith('https://')
}
// 构建图片源
const imageSource = useMemo(() => {
// 如果提供了source属性优先使用
if (propSource) return propSource
if (!src) return undefined
if (typeof src === 'number') {
// 本地图片资源require导入的资源ID
return src
} else {
// 网络图片或本地文件路径
if (isNetworkImage(src)) {
const finalUrl = isCompression ? compressionUrl : src
// console.log('finalUrl-------------', finalUrl)
return {
uri: finalUrl,
cacheKey: cacheKey || finalUrl,
}
} else {
// 本地文件路径
return { uri: src }
}
}
}, [src, propSource, cacheKey, isCompression, compressionUrl])
const imgProps = {
style: [style, imageStyle],
ref,
source: imageSource,
// 使用 disk 缓存策略,减少内存占用
cachePolicy: 'disk' as const,
// 添加内存缓存上限,当内存紧张时优先释放
recyclingKey: typeof src === 'string' ? src : undefined,
errorSource,
transition: { duration: 200, effect: 'cross-dissolve' as const },
...reset,
}
return <ExpoImage {...imgProps} />
// return <Image style={[style, imageStyle]} source={{ uri: compressionUrl(src as string) }} />
})
Img.displayName = 'Img'
export default memo(Img)