医学道
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.
 
 
 
video/src/components/image/image.tsx

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