From 648eb9429a840af504603bbc84c14388ee462a35 Mon Sep 17 00:00:00 2001 From: seaheart Date: Sat, 12 Aug 2023 16:36:17 +0800 Subject: [PATCH] feat: change img previewer --- package.json | 2 +- .../widget/previewer/BrowserPreviewer.less | 2 +- .../widget/previewer/ImagePreviewer.less | 18 +++ src/pages/widget/previewer/ImagePreviewer.tsx | 151 ++++++++++++------ yarn.lock | 10 +- 5 files changed, 125 insertions(+), 58 deletions(-) create mode 100644 src/pages/widget/previewer/ImagePreviewer.less diff --git a/package.json b/package.json index 05c5812..1346457 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,10 @@ "craco-less": "2.0.0", "echarts": "4.8.0", "echarts-for-react": "2.0.16", - "photoswipe": "^5.3.8", "qs": "^6.10.3", "react": "17.0.2", "react-dom": "17.0.2", + "react-photo-view": "^1.2.3", "react-router": "^5.2.0", "react-router-dom": "^5.2.0", "react-scripts": "5.0.0", diff --git a/src/pages/widget/previewer/BrowserPreviewer.less b/src/pages/widget/previewer/BrowserPreviewer.less index 00921a4..beeac19 100644 --- a/src/pages/widget/previewer/BrowserPreviewer.less +++ b/src/pages/widget/previewer/BrowserPreviewer.less @@ -6,7 +6,7 @@ bottom: 0; left: 0; padding: 24px; - background: rgba(0,0,0,0.3); + background: rgba(0,0,0,0.6); z-index: 1000; .browser-previewer { diff --git a/src/pages/widget/previewer/ImagePreviewer.less b/src/pages/widget/previewer/ImagePreviewer.less new file mode 100644 index 0000000..a3740bc --- /dev/null +++ b/src/pages/widget/previewer/ImagePreviewer.less @@ -0,0 +1,18 @@ +.widget-image-previewer{ + .PhotoView-Slider__toolbarIcon { + display: none; + } + + .toolbar-icon { + width: 44px; + height: 44px; + display: flex; + align-items: center; + justify-content: center; + opacity: 0.7; + font-weight: 600; + &:hover { + opacity: 1; + } + } +} \ No newline at end of file diff --git a/src/pages/widget/previewer/ImagePreviewer.tsx b/src/pages/widget/previewer/ImagePreviewer.tsx index 6344148..5ed0384 100644 --- a/src/pages/widget/previewer/ImagePreviewer.tsx +++ b/src/pages/widget/previewer/ImagePreviewer.tsx @@ -1,45 +1,45 @@ -import PhotoSwipe from 'photoswipe'; -import 'photoswipe/style.css'; -import { UIElementData } from 'photoswipe/dist/types/ui/ui'; +import React from 'react'; +import { PhotoSlider } from 'react-photo-view'; +import 'react-photo-view/dist/react-photo-view.css'; +import ReactDOM from 'react-dom'; +import { OverlayRenderProps } from 'react-photo-view/dist/types'; +import { + CloseOutlined, + DownloadOutlined, + RotateRightOutlined, +} from '@ant-design/icons'; +import TankComponent from '../../../common/component/TankComponent'; +import { Space } from 'antd'; +import './ImagePreviewer.less'; /** * 图片预览器 * 支持预览一张图片或者多张图片 + * 参考文档:https://zhuanlan.zhihu.com/p/473554342 + * https://gitee.com/MinJieLiu/react-photo-view */ -export default class ImagePreviewer { - static downloadElement: UIElementData = { - name: 'download-button', - order: 8, - isButton: true, - tagName: 'a', +export default class ImagePreviewer extends TankComponent { + static initialized: boolean = false; - // SVG with outline - html: { - isCustomSVG: true, - inner: - '', - outlineID: 'pswp__icn-download', - }, - onInit: (el, pswp) => { - el.setAttribute('download', ''); - el.setAttribute('target', '_blank'); - el.setAttribute('rel', 'noopener'); + static singletonRef = React.createRef(); - pswp.on('change', () => { - (el as HTMLAnchorElement).href = pswp.currSlide?.data.src!; - }); - }, - }; + //组件的私有变量 + visible: boolean = true; + urls: string[] = []; + index: number = 0; - static getImageSize( - url: string - ): Promise<{ width?: number; height?: number }> { - return new Promise((resolve) => { - const img = new Image(); - img.onload = () => resolve({ width: img.width, height: img.height }); - img.onerror = () => resolve({ width: undefined, height: undefined }); - img.src = url; - }); + //初始化 + private static init() { + let div: HTMLElement = document.createElement('div'); + div.id = 'photo-container'; + + //添加到body + document.body.appendChild(div); + + ReactDOM.render( + , + document.getElementById('photo-container') + ); } //展示一张图片 @@ -47,23 +47,72 @@ export default class ImagePreviewer { ImagePreviewer.showMultiPhoto([url], 0); } - static async showMultiPhoto(urls: string[], index: number = 0) { - const sizes = await Promise.all( - urls.map((url) => ImagePreviewer.getImageSize(url)) + //展示一系列图片 + static showMultiPhoto(urls: string[], index: number = 0) { + if (!ImagePreviewer.initialized) { + ImagePreviewer.initialized = true; + ImagePreviewer.init(); + } + + ImagePreviewer.singletonRef.current?.show(urls, index); + } + + show(urls: string[], index: number = 0) { + this.urls = urls; + this.index = index; + this.visible = true; + this.updateUI(); + } + + render() { + let toolBar: (overlayProps: OverlayRenderProps) => React.ReactNode = ( + overlayProps: OverlayRenderProps + ) => { + return ( + + { + const a = document.createElement('a'); + a.setAttribute('download', ''); + a.setAttribute('target', '_blank'); + a.setAttribute('rel', 'noopener'); + a.href = overlayProps.images[overlayProps.index].src!; + document.body.appendChild(a); + a.click(); + a.remove(); + }} + /> + { + overlayProps.onRotate(overlayProps.rotate + 90); + }} + /> + overlayProps.onClose()} + /> + + ); + }; + + return ( + ({ src: item, key: item }))} + visible={this.visible} + onClose={() => { + this.visible = false; + this.updateUI(); + }} + index={this.index} + onIndexChange={(index: number) => { + this.index = index; + this.updateUI(); + }} + toolbarRender={toolBar} + /> ); - - const pswp = new PhotoSwipe({ - dataSource: urls.map((url, index) => ({ - src: url, - width: sizes[index].width, - height: sizes[index].height, - })), - index, - }); - - pswp.on('uiRegister', () => { - pswp.ui?.registerElement(ImagePreviewer.downloadElement); - }); - pswp.init(); } } diff --git a/yarn.lock b/yarn.lock index ada30ed..72900d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6761,11 +6761,6 @@ performance-now@^2.1.0: resolved "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== -photoswipe@^5.3.8: - version "5.3.8" - resolved "https://registry.npmmirror.com/photoswipe/-/photoswipe-5.3.8.tgz#bea7db18e79383833f85c005b833da2029f0daee" - integrity sha512-4vTzOQt8GP4Chsm0s+8j2xDtVHAEN252PxrU12A1zXauNn0zD5HRHgjALKO2GKTyBnTnOrJUOxbV8LTrFIMrYw== - picocolors@^0.2.1: version "0.2.1" resolved "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" @@ -7928,6 +7923,11 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.npmmirror.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== +react-photo-view@^1.2.3: + version "1.2.3" + resolved "https://registry.npmmirror.com/react-photo-view/-/react-photo-view-1.2.3.tgz#436f81ad0a611dfaa43bbc72a4fef26a057b5aef" + integrity sha512-dtaFjU8nAB/rD8mxBaaJcvESlDOweAd1tmvXujS/d3oh1QyGew3xD4C02l46E6Dhn3Tshzl2+IM1h0MWV9nG7g== + react-refresh@^0.11.0: version "0.11.0" resolved "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"