-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPhotoView.tsx
104 lines (95 loc) · 2.22 KB
/
PhotoView.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import type React from 'react'
import { Children, cloneElement, useContext, useEffect, useMemo, useRef } from 'react'
import useInitial from './hooks/useInitial'
import useMethods from './hooks/useMethods'
import type { PhotoContextType } from './photo-context'
import PhotoContext from './photo-context'
import type { PhotoRenderParams } from './types'
export interface PhotoViewProps {
/**
* 图片地址
*/
src?: string
/**
* 自定义渲染,优先级比 src 低
*/
render?: (props: PhotoRenderParams) => React.ReactNode
/**
* 自定义覆盖节点
*/
overlay?: React.ReactNode
/**
* 自定义渲染节点宽度
*/
width?: number
/**
* 自定义渲染节点高度
*/
height?: number
/**
* 子节点,一般为缩略图
*/
children?: React.ReactElement
/**
* 触发的事件
*/
triggers?: ('onClick' | 'onDoubleClick')[]
}
const PhotoView: React.FC<PhotoViewProps> = ({
src,
render,
overlay,
width,
height,
triggers = ['onClick'],
children,
}) => {
const photoContext = useContext<PhotoContextType>(PhotoContext)
const key = useInitial(() => photoContext.nextId())
const originRef = useRef<HTMLElement>(null)
useEffect(() => {
return () => {
photoContext.remove(key)
}
}, [])
function invokeChildrenFn(eventName: string, e: React.SyntheticEvent) {
if (children) {
const eventFn = children.props[eventName]
if (eventFn) {
eventFn(e)
}
}
}
const fn = useMethods({
render(props: PhotoRenderParams) {
return render && render(props)
},
show(eventName: string, e: React.MouseEvent) {
photoContext.show(key)
invokeChildrenFn(eventName, e)
},
})
const eventListeners = useMemo(() => {
const listener: Record<string, any> = {}
triggers.forEach(eventName => {
listener[eventName] = fn.show.bind(null, eventName)
})
return listener
}, [])
useEffect(() => {
photoContext.update({
key,
src,
originRef,
render: fn.render,
overlay,
width,
height,
})
}, [src])
if (children) {
return Children.only(cloneElement(children, { ...eventListeners, ref: originRef }))
}
return null
}
export default PhotoView