You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
2.4 KiB
96 lines
2.4 KiB
import {FC, useEffect, useState} from "react";
|
|
import {Image, ImageProps, View} from "@tarojs/components";
|
|
import shard from '@/static/img/shard.png'
|
|
import styles from './image.module.scss'
|
|
import Taro from "@tarojs/taro";
|
|
import avatar from '@/static/img/avatar.png'
|
|
|
|
interface Props extends ImageProps {
|
|
width?: number | string
|
|
height?: number | string
|
|
fallback?: string
|
|
errorType?: "acquiesce" | 'avatar'
|
|
}
|
|
|
|
const Img: FC<Props> = ({src, mode = 'aspectFill', width, height, fallback = shard, ...props}) => {
|
|
const [isError, setIsError] = useState(false)
|
|
const [loading, setLoading] = useState(true)
|
|
const [errorUrl, setErrorUrl] = useState(fallback)
|
|
|
|
const imgAnimation = Taro.createAnimation({duration: 0}).opacity(0).step()
|
|
const [animationData, setAnimationData] = useState<TaroGeneral.IAnyObject>(imgAnimation.export())
|
|
|
|
useEffect(() => {
|
|
setIsError(!src)
|
|
setLoading(!!src)
|
|
}, [src])
|
|
|
|
useEffect(() => {
|
|
switch (props.errorType) {
|
|
case undefined:
|
|
case "acquiesce":
|
|
setErrorUrl(fallback)
|
|
break
|
|
case "avatar":
|
|
setErrorUrl(avatar)
|
|
break
|
|
}
|
|
}, [props.errorType])
|
|
|
|
// 图片加载失败
|
|
function onErrorHandler() {
|
|
setLoading(false)
|
|
setIsError(true)
|
|
}
|
|
|
|
function onLoadHandler() {
|
|
setLoading(false)
|
|
setIsError(false)
|
|
imgAnimation.opacity(1).step({duration: 200})
|
|
setAnimationData(imgAnimation.export())
|
|
}
|
|
|
|
return (
|
|
<View
|
|
style={{
|
|
width: `${width}rpx`,
|
|
height: `${height}rpx`,
|
|
backgroundColor: (isError || !loading) ? 'transparent' : '#F8F8F8'
|
|
}}
|
|
className={`${props?.className} ${styles.imgBox}`}>
|
|
{!isError &&
|
|
<View animation={animationData}>
|
|
<Image
|
|
{...props}
|
|
src={src}
|
|
mode={mode}
|
|
lazyLoad
|
|
fadeIn
|
|
defaultSource={errorUrl}
|
|
style={{
|
|
width: width ? `${width}rpx` : "100%",
|
|
height: height ? `${height}rpx` : "100%",
|
|
verticalAlign: 'middle'
|
|
}}
|
|
onError={onErrorHandler}
|
|
onLoad={onLoadHandler}/>
|
|
</View>
|
|
}
|
|
{
|
|
isError && !loading &&
|
|
<Image
|
|
className={styles.imgError}
|
|
mode='aspectFill'
|
|
src={errorUrl}
|
|
lazyLoad
|
|
fadeIn
|
|
style={{
|
|
width: "100%",
|
|
height: "100%",
|
|
}}/>
|
|
}
|
|
</View>
|
|
)
|
|
}
|
|
|
|
export default Img
|
|
|