warn warn warn warn warn import * as React from 'react' ; import { Image , StyleSheet , ImageSourcePropType , LayoutChangeEvent , ImageResolvedAssetSource } from 'react-native' ; import { SvgCssUri , WithLocalSvg } from 'react-native-svg' ; import { noop , omit } from '../../utils' ; import ClickableSimplified from '../ClickableSimplified' ; import { ImageProps , ImageState , ResizeModeMap , ResizeMode } from './PropsType' ; const resizeModeMap = { scaleToFill : 'stretch' , aspectFit : 'contain' , aspectFill : 'cover' , center : 'center' , } ; export class _Image extends React . Component < ImageProps , ImageState > { static defaultProps : ImageProps = { src : '' , mode : 'scaleToFill' } ; hasLayout = false ; state : ImageState = { ratio : 0 , layoutWidth : 0 } ; onError = ( ) : void => { const { onError = noop } = this . props ; onError ( { detail : { errMsg : 'something wrong' } } ) ; } ; onLoad = ( ) : void => { const { src , onLoad } = this . props ; if ( ! onLoad ) return ; if ( typeof src === 'string' ) { Image . getSize ( src as string , ( width , height ) => { onLoad ( { detail : { width , height } } ) ; } , ( ) => { onLoad ( { detail : { width : 0 , height : 0 } } ) ; } ) ; } else { const iras = Image . resolveAssetSource ( typeof src === 'string' ? { uri : src } : src ) ; const { width , height } = iras || { width : 0 , height : 0 } ; onLoad ( { detail : { width , height } } ) ; } } ; onLayout = ( event ) : void => { const { mode , style } = this . props ; const { width : layoutWidth } = event . nativeEvent . layout ; const flattenStyle = StyleSheet . flatten ( style ) || { } ; if ( mode === 'widthFix' && typeof flattenStyle . width === 'string' ) { if ( this . hasLayout ) return ; this . setState ( { layoutWidth } ) ; } if ( this . state . ratio ) { this . hasLayout = true ; } } ; loadImg = ( props ) : void => { const { mode , src } = props ; if ( mode !== 'widthFix' ) return ; if ( typeof src === 'string' ) { Image . getSize ( props . src , ( width , height ) => { if ( this . hasLayout ) return ; this . setState ( { ratio : height / width } ) ; } ) ; } else { const source = typeof props . src === 'string' ? { uri : props . src } : props . src ; const { width , height } = Image . resolveAssetSource ( source ) || { } ; if ( this . hasLayout && ! ! this . state . ratio ) return ; this . setState ( { ratio : height / width } ) ; } } ; componentDidMount ( ) { this . loadImg ( this . props ) ; } shouldComponentUpdate ( nextProps ) { if ( nextProps . src !== this . props . src ) { this . hasLayout = false ; } return true ; } componentDidUpdate ( prevProps ) { if ( prevProps . src !== this . props . src ) { this . loadImg ( this . props ) ; } } render ( ) { const { style , src , mode = 'scaleToFill' , svg = false } = this . props ; const flattenStyle = StyleSheet . flatten ( style ) || { } ; const defaultWidth = flattenStyle . width || 300 ; const defaultHeight = flattenStyle . height || 225 ; const remoteSvgReg = /(https?:\/\/.*\.(?:svg|svgx))/i ; if ( typeof src === 'string' && remoteSvgReg . test ( src ) ) { return ( < SvgCssUri uri = { src } width = { defaultWidth } height = { defaultHeight } / > ) ; } if ( svg ) { return ( < WithLocalSvg asset = { src } width = { defaultWidth } height = { defaultHeight } / > ) ; } const source = typeof src === 'string' ? { uri : src } : src ; const isWidthFix = mode === 'widthFix' ; const rMode = ( resizeModeMap [ mode ] || ( isWidthFix ? undefined : 'stretch' ) ) ; const imageHeight = ( ( ) => { if ( isWidthFix ) { if ( typeof flattenStyle . width === 'string' ) { return this . state . layoutWidth * this . state . ratio ; } else if ( typeof flattenStyle . width === 'number' ) { return flattenStyle . width * this . state . ratio ; } else { return 300 * this . state . ratio ; } } else { return defaultHeight ; } } ) ( ) ; const restImageProps = omit ( this . props , [ 'source' , 'src' , 'resizeMode' , 'onLoad' , 'onError' , 'onLayout' , 'style' ] ) ; return ( < Image source = { source } resizeMode = { rMode } onError = { this . onError } onLoad = { this . onLoad } onLayout = { this . onLayout } style = { [ { width : 300 } , style , { height : imageHeight } ] } { ... restImageProps } />); } } export default ClickableSimplified ( _Image ) ;