diff --git a/src/components/image-viewer/demos/demo1.less b/src/components/image-viewer/demos/demo1.less index 8d0a24bf01..939872c1ad 100644 --- a/src/components/image-viewer/demos/demo1.less +++ b/src/components/image-viewer/demos/demo1.less @@ -5,7 +5,7 @@ .footerButton { font-size: var(--adm-font-size-4); - color: #ffffff; + color: #fff; line-height: 1; padding: 10px 16px; background-color: rgba(153, 153, 153, 0.4); @@ -13,3 +13,17 @@ display: inline-block; cursor: pointer; } +.image-render { + width: 100%; + height: 100%; + display: flex; + align-items: center; +} +.custom-render { + color: #1677ff; + background: #fff; + width: 200px; + height: 100px; + border-radius: 2px; + padding: 8px; +} diff --git a/src/components/image-viewer/demos/demo1.tsx b/src/components/image-viewer/demos/demo1.tsx index f329f831dd..b150d7cb2d 100644 --- a/src/components/image-viewer/demos/demo1.tsx +++ b/src/components/image-viewer/demos/demo1.tsx @@ -1,8 +1,8 @@ -import React, { useState } from 'react' -import { ImageViewer, Button } from 'antd-mobile' +import { Button, ImageViewer } from 'antd-mobile' import { DemoBlock } from 'demos' -import { demoImage, demoImages } from './images' +import React, { useState } from 'react' import styles from './demo1.less' +import { demoImage, demoImages } from './images' // 单张图片预览 const Single = () => { @@ -95,6 +95,66 @@ const ViewWithFooter = () => { ) } +const ViewImageRender = () => { + const [visible, setVisible] = useState(false) + + return ( + <> + { + setVisible(true) + }} + > + 显示内容 + + { + setVisible(false) + }} + imageRender={() => ( + + + + )} + /> + > + ) +} + +// 多张图片预览 +const MultiViewImageRender = () => { + const [visible, setVisible] = useState(false) + return ( + <> + { + setVisible(true) + }} + > + 显示图片 + + { + if (index === 1) + return 自定义渲染内容 + }} + defaultIndex={1} + onClose={() => { + setVisible(false) + }} + /> + > + ) +} + export default () => { return ( <> @@ -134,6 +194,13 @@ export default () => { + + + + + + + > ) } diff --git a/src/components/image-viewer/image-viewer.tsx b/src/components/image-viewer/image-viewer.tsx index cf93dc0ed0..9fd8a561e6 100644 --- a/src/components/image-viewer/image-viewer.tsx +++ b/src/components/image-viewer/image-viewer.tsx @@ -1,21 +1,21 @@ +import classNames from 'classnames' +import type { FC, ReactNode } from 'react' import React, { forwardRef, + useCallback, useImperativeHandle, useRef, useState, - useCallback, } from 'react' -import type { FC, ReactNode } from 'react' -import { mergeProps } from '../../utils/with-default-props' import { GetContainer, renderToContainer, } from '../../utils/render-to-container' +import { mergeProps } from '../../utils/with-default-props' import Mask from '../mask' import SafeArea from '../safe-area' import { Slide } from './slide' import { Slides, SlidesRef } from './slides' -import classNames from 'classnames' const classPrefix = `adm-image-viewer` @@ -27,6 +27,7 @@ export type ImageViewerProps = { onClose?: () => void afterClose?: () => void renderFooter?: (image: string) => ReactNode + imageRender?: (image?: string) => ReactNode classNames?: { mask?: string body?: string @@ -57,11 +58,12 @@ export const ImageViewer: FC = p => { props?.classNames?.body )} > - {props.image && ( + {(props.image || typeof props.imageRender === 'function') && ( )} @@ -80,12 +82,13 @@ export type MultiImageViewerRef = SlidesRef export type MultiImageViewerProps = Omit< ImageViewerProps, - 'image' | 'renderFooter' + 'image' | 'renderFooter' | 'imageRender' > & { images?: string[] defaultIndex?: number onIndexChange?: (index: number) => void renderFooter?: (image: string, index: number) => ReactNode + imageRender?: (image: string, index: number) => ReactNode } const multiDefaultProps = { @@ -140,6 +143,7 @@ export const MultiImageViewer = forwardRef< images={props.images} onTap={props.onClose} maxZoom={props.maxZoom} + imageRender={props.imageRender} /> )} diff --git a/src/components/image-viewer/index.en.md b/src/components/image-viewer/index.en.md index 5d864f8b94..2ab3dc8b5a 100644 --- a/src/components/image-viewer/index.en.md +++ b/src/components/image-viewer/index.en.md @@ -21,6 +21,7 @@ You need to click on the picture to view the details and use it with the thumbna | maxZoom | The maximum zoom ratio | `number \| 'auto'` | `3` | | onClose | Triggered when it is closed | `() => void` | - | | renderFooter | Render extra content on footer | `(image: string) => ReactNode` | - | +| imageRender | Custom rendering content | `(image?: string) => ReactNode` | - | | visible | Whether to show or hide | `boolean` | `false` | ## ImageViewer.Multi @@ -34,6 +35,7 @@ On the basis of `ImageViewer`, the following props have been added: | images | Url list of image resources | `string[]` | - | | onIndexChange | Triggered when the picture is switched | `(index: number) => void` | - | | renderFooter | Render extra content on footer | `(image: string, index: number) => ReactNode` | - | +| imageRender | Custom rendering content | `(image: string, index: number) => ReactNode` | - | At the same time, the `image` prop is removed. diff --git a/src/components/image-viewer/index.zh.md b/src/components/image-viewer/index.zh.md index aa1023e8e1..968c7d3230 100644 --- a/src/components/image-viewer/index.zh.md +++ b/src/components/image-viewer/index.zh.md @@ -21,6 +21,7 @@ | maxZoom | 最大缩放比例 | `number \| 'auto'` | `3` | | onClose | 关闭时触发 | `() => void` | - | | renderFooter | 渲染底部额外内容 | `(image: string) => ReactNode` | - | +| imageRender | 自定义渲染内容 | `(image?: string) => ReactNode` | - | | visible | 是否显示 | `boolean` | `false` | ## ImageViewer.Multi @@ -32,6 +33,7 @@ | images | 图片资源的 url 列表 | `string[]` | - | | onIndexChange | 切换图片时触发 | `(index: number) => void` | - | | renderFooter | 渲染底部额外内容 | `(image: string, index: number) => ReactNode` | - | +| imageRender | 自定义渲染内容 | `(image: string, index: number) => ReactNode` | - | 其他属性同 `ImageViewer`,但是去掉了 `image` 属性。 diff --git a/src/components/image-viewer/slide.tsx b/src/components/image-viewer/slide.tsx index 50e680fa14..c8e09a8b5d 100644 --- a/src/components/image-viewer/slide.tsx +++ b/src/components/image-viewer/slide.tsx @@ -1,25 +1,27 @@ -import React, { useRef } from 'react' -import type { FC, MutableRefObject } from 'react' -import { useSpring, animated } from '@react-spring/web' +import { animated, useSpring } from '@react-spring/web' import { useSize } from 'ahooks' -import { rubberbandIfOutOfBounds } from '../../utils/rubberband' -import { useDragAndPinch } from '../../utils/use-drag-and-pinch' +import type { FC, MutableRefObject, ReactNode } from 'react' +import React, { useRef } from 'react' import { bound } from '../../utils/bound' import type { Matrix } from '../../utils/matrix' import * as mat from '../../utils/matrix' +import { rubberbandIfOutOfBounds } from '../../utils/rubberband' +import { useDragAndPinch } from '../../utils/use-drag-and-pinch' const classPrefix = `adm-image-viewer` type Props = { - image: string + image?: string maxZoom: number | 'auto' onTap?: () => void onZoomChange?: (zoom: number) => void dragLockRef?: MutableRefObject + imageRender?: (image: string, index: number) => ReactNode + index?: number } export const Slide: FC = props => { - const { dragLockRef, maxZoom } = props + const { dragLockRef, maxZoom, imageRender, index } = props const initialMartix = useRef([]) const controlRef = useRef(null) const imgRef = useRef(null) @@ -295,6 +297,10 @@ export const Slide: FC = props => { } ) + const customRendering = + typeof imageRender === 'function' && + imageRender?.(props.image as string, index as number) + return ( @@ -304,12 +310,16 @@ export const Slide: FC = props => { matrix, }} > - + {customRendering ? ( + customRendering + ) : ( + + )} diff --git a/src/components/image-viewer/slides.tsx b/src/components/image-viewer/slides.tsx index 37837074af..6420e7141b 100644 --- a/src/components/image-viewer/slides.tsx +++ b/src/components/image-viewer/slides.tsx @@ -1,9 +1,14 @@ -import React, { forwardRef, useImperativeHandle, useRef } from 'react' +import { animated, useSpring } from '@react-spring/web' import { useDrag } from '@use-gesture/react' -import { useSpring, animated } from '@react-spring/web' -import { Slide } from './slide' -import { convertPx } from '../../utils/convert-px' +import React, { + ReactNode, + forwardRef, + useImperativeHandle, + useRef, +} from 'react' import { bound } from '../../utils/bound' +import { convertPx } from '../../utils/convert-px' +import { Slide } from './slide' const classPrefix = `adm-image-viewer` @@ -13,6 +18,7 @@ export type SlidesType = { maxZoom: number defaultIndex: number onIndexChange?: (index: number) => void + imageRender?: (image: string, index: number) => ReactNode } export type SlidesRef = { swipeTo: (index: number, immediate?: boolean) => void @@ -95,6 +101,8 @@ export const Slides = forwardRef((props, ref) => { image={image} onTap={props.onTap} maxZoom={props.maxZoom} + imageRender={props.imageRender} + index={index} onZoomChange={zoom => { if (zoom !== 1) { const index: number = Math.round(x.get() / slideWidth)