Skip to content

Commit

Permalink
feat(*): add fast image.
Browse files Browse the repository at this point in the history
  • Loading branch information
shangqunfeng committed Nov 22, 2024
1 parent 6e549b0 commit c307775
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 24 deletions.
6 changes: 5 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"vue": "^2.7.10",
"vue-demi": "^0.14.6",
"vue-i18n": "^8.27.2",
"vue-i18n-bridge": "^9.2.2"
"vue-i18n-bridge": "^9.2.2",
"@d11/react-native-fast-image": "^8.6.12"
},
"peerDependenciesMeta": {
"vue": {
Expand Down Expand Up @@ -83,6 +84,9 @@
},
"react-native-linear-gradient": {
"optional": true
},
"@d11/react-native-fast-image": {
"optional": true
}
},
"publishConfig": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
} from 'react-native'
import useInnerProps, { getCustomEvent } from '../getInnerListeners'
import useNodesRef, { HandlerRef } from '../useNodesRef'
import { useLayout, useTransformStyle } from '../utils'
import { useLayout, useTransformStyle, renderImage } from '../utils'

export type Mode =
| 'scaleToFill'
Expand Down Expand Up @@ -56,6 +56,7 @@ export interface ImageProps {
'enable-var'?: boolean
'external-var-context'?: Record<string, any>
'parent-font-size'?: number
'enable-fast-image'?: boolean
'parent-width'?: number
'parent-height'?: number
bindload?: (evt: NativeSyntheticEvent<ImageLoadEventData> | unknown) => void
Expand Down Expand Up @@ -120,6 +121,7 @@ const Image = forwardRef<HandlerRef<RNImage, ImageProps>, ImageProps>((props, re
'parent-font-size': parentFontSize,
'parent-width': parentWidth,
'parent-height': parentHeight,
'enable-fast-image': enableFastImage,
bindload,
binderror
} = props
Expand Down Expand Up @@ -323,18 +325,18 @@ const Image = forwardRef<HandlerRef<RNImage, ImageProps>, ImageProps>((props, re
return (
<View {...innerProps}>
{
loaded && <RNImage
source={source}
resizeMode={resizeMode}
onLoad={onImageLoad}
onError={onImageError}
style={{
loaded && renderImage({
source,
resizeMode,
onLoad: onImageLoad,
onError: onImageError,
style: {
...StyleSheet.absoluteFillObject,
width: isCropMode ? imageWidth : '100%',
height: isCropMode ? imageHeight : '100%',
...(isCropMode && cropModeStyle)
}}
/>
}
}, enableFastImage, enableFastImage && (!isWidthFixMode || !isHeightFixMode) ? !!(fixedHeight && fixedWidth) : true)
}
</View>
)
Expand Down
55 changes: 42 additions & 13 deletions packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
* ✔ hover-start-time
* ✔ hover-stay-time
*/
import { View, TextStyle, NativeSyntheticEvent, ViewProps, ImageStyle, ImageResizeMode, StyleSheet, Image, LayoutChangeEvent, Text } from 'react-native'
import { useRef, useState, useEffect, forwardRef, ReactNode, JSX, Children, cloneElement } from 'react'
import { View, TextStyle, NativeSyntheticEvent, ViewProps, ImageStyle, StyleSheet, Image, LayoutChangeEvent } from 'react-native'
import { useRef, useState, useEffect, forwardRef, ReactNode, JSX } from 'react'
import useInnerProps from './getInnerListeners'
import Animated from 'react-native-reanimated'
import useAnimationHooks from './useAnimationHooks'
import type { AnimationProp } from './useAnimationHooks'
import { ExtendedViewStyle } from './types/common'
import useNodesRef, { HandlerRef } from './useNodesRef'
import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wrapChildren, useLayout } from './utils'
import { parseUrl, PERCENT_REGEX, splitStyle, splitProps, useTransformStyle, wrapChildren, useLayout, renderImage, pickStyle } from './utils'
import LinearGradient from 'react-native-linear-gradient'

export interface _ViewProps extends ViewProps {
Expand All @@ -24,6 +24,7 @@ export interface _ViewProps extends ViewProps {
'hover-stay-time'?: number
'enable-background'?: boolean
'enable-var'?: boolean
'enable-fast-image'?: boolean
'external-var-context'?: Record<string, any>
'parent-font-size'?: number
'parent-width'?: number
Expand Down Expand Up @@ -76,9 +77,11 @@ type PreImageInfo = {
type ImageProps = {
style: ImageStyle,
src?: string,
source?: {uri: string },
colors: Array<string>,
locations?: Array<number>
angle?: number
resizeMode?: 'cover' | 'stretch'
}

const linearMap = new Map([
Expand Down Expand Up @@ -280,13 +283,14 @@ function backgroundSize (imageProps: ImageProps, preImageInfo: PreImageInfo, ima
if (!dimensions) return
} else { // 数值类型 ImageStyle
// 数值类型设置为 stretch
(imageProps.style as ImageStyle).resizeMode = 'stretch'
imageProps.resizeMode = 'stretch'
dimensions = {
width: isPercent(width) ? width : +width,
height: isPercent(height) ? height : +height
} as { width: NumberVal, height: NumberVal }
}
}

// 样式合并
imageProps.style = {
...imageProps.style as ImageStyle,
Expand All @@ -296,8 +300,9 @@ function backgroundSize (imageProps: ImageProps, preImageInfo: PreImageInfo, ima

// background-image转换为source
function backgroundImage (imageProps: ImageProps, preImageInfo: PreImageInfo) {
if (preImageInfo.src) {
imageProps.src = preImageInfo.src
const src = preImageInfo.src
if (src) {
imageProps.source = { uri: src }
}
}

Expand Down Expand Up @@ -326,8 +331,8 @@ function linearGradient (imageProps: ImageProps, preImageInfo: PreImageInfo, ima
const imageStyleToProps = (preImageInfo: PreImageInfo, imageSize: Size, layoutInfo: Size) => {
// 初始化
const imageProps: ImageProps = {
resizeMode: 'cover',
style: {
resizeMode: 'cover' as ImageResizeMode,
position: 'absolute'
// ...StyleSheet.absoluteFillObject
},
Expand Down Expand Up @@ -533,7 +538,26 @@ function isDiagonalAngle (linearInfo?: LinearInfo): boolean {
return !!(linearInfo?.direction && diagonalAngleMap[linearInfo.direction])
}

function wrapImage (imageStyle?: ExtendedViewStyle) {
function inheritStyle (innerStyle: ExtendedViewStyle = {}) {
const { borderWidth, borderRadius } = innerStyle
const borderStyles = ['borderRadius', 'borderTopLeftRadius', 'borderTopRightRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius']
return pickStyle(innerStyle,
borderStyles,
borderWidth && borderRadius
? (key, val) => {
// 盒子内圆角borderWith与borderRadius的关系
// 当borderRadius 小于 当borderWith 内边框为直角
// 当borderRadius 大于等于 当borderWith 内边框为圆角
if (borderStyles.includes(key)) {
const borderVal = +val - borderWidth
return borderVal > 0 ? borderVal : 0
}
return val
}
: undefined)
}

function wrapImage (imageStyle?: ExtendedViewStyle, innerStyle?: Record<string, any>, enableFastImage?: boolean) {
// 预处理数据
const preImageInfo: PreImageInfo = preParseImage(imageStyle)
// 预解析
Expand Down Expand Up @@ -616,9 +640,9 @@ function wrapImage (imageStyle?: ExtendedViewStyle) {
}
}

return <View key='backgroundImage' {...needLayout ? { onLayout } : null} style={{ ...StyleSheet.absoluteFillObject, overflow: 'hidden' }}>
return <View key='backgroundImage' {...needLayout ? { onLayout } : null} style={{ ...inheritStyle(innerStyle), ...StyleSheet.absoluteFillObject, overflow: 'hidden' }}>
{show && type === 'linear' && <LinearGradient useAngle={true} {...imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size)} /> }
{show && type === 'image' && <Image {...imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size)} />}
{show && type === 'image' && (renderImage(imageStyleToProps(preImageInfo, sizeInfo.current as Size, layoutInfo.current as Size), enableFastImage))}
</View>
}

Expand All @@ -629,9 +653,11 @@ interface WrapChildrenConfig {
backgroundStyle?: ExtendedViewStyle
varContext?: Record<string, any>
textProps?: Record<string, any>
innerStyle?: Record<string, any>
enableFastImage?: boolean
}

function wrapWithChildren (props: _ViewProps, { hasVarDec, enableBackground, textStyle, backgroundStyle, varContext, textProps }: WrapChildrenConfig) {
function wrapWithChildren (props: _ViewProps, { hasVarDec, enableBackground, textStyle, backgroundStyle, varContext, textProps, innerStyle, enableFastImage }: WrapChildrenConfig) {
const children = wrapChildren(props, {
hasVarDec,
varContext,
Expand All @@ -640,7 +666,7 @@ function wrapWithChildren (props: _ViewProps, { hasVarDec, enableBackground, tex
})

return [
enableBackground ? wrapImage(backgroundStyle) : null,
enableBackground ? wrapImage(backgroundStyle, innerStyle, enableFastImage) : null,
children
]
}
Expand All @@ -655,6 +681,7 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
'enable-var': enableVar,
'external-var-context': externalVarContext,
'enable-background': enableBackground,
'enable-fast-image': enableFastImage,
'enable-animation': enableAnimation,
'parent-font-size': parentFontSize,
'parent-width': parentWidth,
Expand Down Expand Up @@ -789,7 +816,9 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
textStyle,
backgroundStyle,
varContext: varContextRef.current,
textProps
textProps,
innerStyle,
enableFastImage
})
return animation?.actions?.length
? (<Animated.View
Expand Down
22 changes: 21 additions & 1 deletion packages/webpack-plugin/lib/runtime/components/react/utils.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useEffect, useCallback, useMemo, useRef, ReactNode, ReactElement, isValidElement, useContext, useState, Dispatch, SetStateAction, Children, cloneElement } from 'react'
import { LayoutChangeEvent, TextStyle } from 'react-native'
import { LayoutChangeEvent, TextStyle, ImageProps, Image } from 'react-native'
import { isObject, hasOwn, diffAndCloneA, error, warn, getFocusedNavigation } from '@mpxjs/utils'
import { VarContext } from './context'
import { ExpressionParser, parseFunc, ReplaceSource } from './parser'
import { initialWindowMetrics } from 'react-native-safe-area-context'
import FastImage, { FastImageProps } from '@d11/react-native-fast-image'
import type { AnyFunc, ExtendedFunctionComponent } from './types/common'

export const TEXT_STYLE_REGEX = /color|font.*|text.*|letterSpacing|lineHeight|includeFontPadding|writingDirection/
Expand Down Expand Up @@ -587,3 +588,22 @@ export function flatGesture (gestures: Array<GestureHandler> = []) {
export function extendObject (...args: Record<string, any>[]) {
return Object.assign({}, ...args)
}

export function renderImage (
imageProps: ImageProps | FastImageProps,
enableFastImage = false,
isRender = true
) {
const Component: React.ComponentType<ImageProps | FastImageProps> = enableFastImage ? FastImage : Image
if (!isRender) return <></>
return <Component {...imageProps} />
}

export function pickStyle (styleObj: Record<string, any> = {}, pickedKeys: Array<string>, callback?: (key: string, val: number | string) => number | string) {
return pickedKeys.reduce<Record<string, any>>((acc, key) => {
if (key in styleObj) {
acc[key] = callback ? callback(key, styleObj[key]) : styleObj[key]
}
return acc
}, {})
}
1 change: 1 addition & 0 deletions packages/webpack-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"react-native-reanimated": "^3.15.2",
"react-native-safe-area-context": "^4.12.0",
"react-native-webview": "^13.12.2",
"@d11/react-native-fast-image": "^8.6.12",
"rimraf": "^6.0.1"
},
"engines": {
Expand Down

0 comments on commit c307775

Please sign in to comment.