Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ImageViewer preview component supports self-defined preview content #6825

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/components/image-viewer/demos/demo1.less
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@

.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);
border-radius: 100px;
display: inline-block;
cursor: pointer;
}
.render-content {
display: flex;
height: 200px;
align-items: center;
justify-content: center;
color: #1677ff;
}
47 changes: 42 additions & 5 deletions src/components/image-viewer/demos/demo1.tsx
Original file line number Diff line number Diff line change
@@ -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, { ReactNode, useState } from 'react'
import styles from './demo1.less'
import { demoImage, demoImages } from './images'

// 单张图片预览
const Single = () => {
Expand Down Expand Up @@ -58,7 +58,7 @@ const Multi = () => {
const ViewWithFooter = () => {
const [visible, setVisible] = useState(false)

const renderFooter = (image: string, index: number) => {
const renderFooter = (image: ReactNode, index: number) => {
return (
<div className={styles.footer}>
<div
Expand All @@ -67,7 +67,7 @@ const ViewWithFooter = () => {
console.log('Loading...')
}}
>
查看原图{index + 1}
{`查看${typeof image === 'string' ? '原图' : '自定义内容'}${index + 1}`}
</div>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

直接改名叫 查看图片 吧,这里去做分支会把 Demo 变得复杂

</div>
)
Expand Down Expand Up @@ -95,6 +95,40 @@ const ViewWithFooter = () => {
)
}

const ImageViewerRender = () => {
const [visible, setVisible] = useState(false)

return (
<>
<Button
onClick={() => {
setVisible(true)
}}
>
显示内容
</Button>
<ImageViewer
visible={visible}
onClose={() => {
setVisible(false)
}}
image={
<div
style={{ height: '100%', display: 'flex', alignItems: 'center' }}
>
<video
muted
width='100%'
controls
src='https://mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*uYT7SZwhJnUAAAAAAAAAAAAADgCCAQ'
/>
</div>
}
/>
</>
)
}

export default () => {
return (
<>
Expand Down Expand Up @@ -134,6 +168,9 @@ export default () => {
<DemoBlock title='自定义底部额外内容'>
<ViewWithFooter />
</DemoBlock>
<DemoBlock title='自定义预览内容'>
<ImageViewerRender />
</DemoBlock>
</>
)
}
8 changes: 7 additions & 1 deletion src/components/image-viewer/demos/images.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import React from 'react'
import styles from './demo1.less'

export const demoImages = [
'https://images.unsplash.com/photo-1620476214170-1d8080f65cdb?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=3150&q=80',
'https://images.unsplash.com/photo-1601128533718-374ffcca299b?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=3128&q=80',
'https://images.unsplash.com/photo-1567945716310-4745a6b7844b?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=3113&q=80',
'https://images.unsplash.com/photo-1624993590528-4ee743c9896e?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=200&h=1000&q=80',
<div key={Math.random()} className={styles['render-content']}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个不要改,要用到自定义内容的地方复制一下数组加一个数据即可

自定义内容
</div>,
]

export const demoImage = demoImages[0]
export const demoImage = demoImages[0] as string
31 changes: 16 additions & 15 deletions src/components/image-viewer/image-viewer.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
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`

export type ImageViewerProps = {
image?: string
image?: ReactNode
maxZoom?: number | 'auto'
getContainer?: GetContainer
visible?: boolean
onClose?: () => void
afterClose?: () => void
renderFooter?: (image: string) => ReactNode
renderFooter?: (image: ReactNode) => ReactNode
classNames?: {
mask?: string
body?: string
Expand Down Expand Up @@ -57,13 +57,11 @@ export const ImageViewer: FC<ImageViewerProps> = p => {
props?.classNames?.body
)}
>
{props.image && (
<Slide
image={props.image}
onTap={props.onClose}
maxZoom={props.maxZoom}
/>
)}
<Slide
image={props.image}
onTap={props.onClose}
maxZoom={props.maxZoom}
/>
</div>
{props.image && (
<div className={`${classPrefix}-footer`}>
Expand All @@ -82,10 +80,13 @@ export type MultiImageViewerProps = Omit<
ImageViewerProps,
'image' | 'renderFooter'
> & {
images?: string[]
images?: (string | ReactNode)[]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#6801 里不是这个意思,是渲染内容可以改,不是数据层给的就是 ReactNode。否则在组件载入的时候就需要把节点都生成一遍。参考一下 antd pc 侧的:
https://ant-design.antgroup.com/components/image-cn#image-demo-imagerender

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我一开改的确实是不动image类型,参考antd的直接在单张图片渲染模式下加一个自定义渲染方法。很简单,但是感觉我现在这种方式更加灵活,应用场景更多。 可以支持图片与其他类型的混合渲染。

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#6801 里不是这个意思,是渲染内容可以改,不是数据层给的就是 ReactNode。否则在组件载入的时候就需要把节点都生成一遍。参考一下 antd pc 侧的: https://ant-design.antgroup.com/components/image-cn#image-demo-imagerender

已修改

defaultIndex?: number
onIndexChange?: (index: number) => void
renderFooter?: (image: string, index: number) => ReactNode
renderFooter?: (
image: string | ReactNode | undefined,
index: number
) => ReactNode
}

const multiDefaultProps = {
Expand Down
4 changes: 2 additions & 2 deletions src/components/image-viewer/index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
| afterClose | 完全关闭后触发 | `() => void` | - |
| classNames | 语义化 class | `{ mask?:string,body?:string }` | - | 5.33.1 |
| getContainer | 指定挂载的 HTML 节点,默认为 `null` 渲染到当前节点 | `HTMLElement \| () => HTMLElement \| null` | `null` |
| image | 图片资源的 `url` | `string` | - |
| image | 图片资源的 `url`或自定义内容 | `ReactNode` | - |
| maxZoom | 最大缩放比例 | `number \| 'auto'` | `3` |
| onClose | 关闭时触发 | `() => void` | - |
| renderFooter | 渲染底部额外内容 | `(image: string) => ReactNode` | - |
Expand All @@ -29,7 +29,7 @@
| --- | --- | --- | --- | --- |
| classNames | 语义化 class | `{ mask?:string,body?:string }` | - | 5.33.1 |
| defaultIndex | 默认显示第几张图片 | `number` | `0` |
| images | 图片资源的 url 列表 | `string[]` | - |
| images | 图片资源的 `url`或自定义内容 | `ReactNode[]` | - |
| onIndexChange | 切换图片时触发 | `(index: number) => void` | - |
| renderFooter | 渲染底部额外内容 | `(image: string, index: number) => ReactNode` | - |

Expand Down
28 changes: 16 additions & 12 deletions src/components/image-viewer/slide.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
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: ReactNode
maxZoom: number | 'auto'
onTap?: () => void
onZoomChange?: (zoom: number) => void
Expand Down Expand Up @@ -304,12 +304,16 @@
matrix,
}}
>
<img
ref={imgRef}
src={props.image}
draggable={false}
alt={props.image}
/>
{typeof props.image === 'string' ? (
<img
ref={imgRef}
src={props.image as string}
draggable={false}
alt={props.image as string}
/>
) : (
props.image

Check warning on line 315 in src/components/image-viewer/slide.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/image-viewer/slide.tsx#L315

Added line #L315 was not covered by tests
)}
</animated.div>
</div>
</div>
Expand Down
15 changes: 10 additions & 5 deletions src/components/image-viewer/slides.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
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`

export type SlidesType = {
images: string[]
images: ReactNode[]
onTap?: () => void
maxZoom: number
defaultIndex: number
Expand Down
Loading