feat: change img previewer

This commit is contained in:
seaheart
2023-08-12 16:36:17 +08:00
parent 35b0c8194b
commit 648eb9429a
5 changed files with 125 additions and 58 deletions
+1 -1
View File
@@ -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",
@@ -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 {
@@ -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;
}
}
}
+100 -51
View File
@@ -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<any, any> {
static initialized: boolean = false;
// SVG with outline
html: {
isCustomSVG: true,
inner:
'<path d="M20.5 14.3 17.1 18V10h-2.2v7.9l-3.4-3.6L10 16l6 6.1 6-6.1ZM23 23H9v2h14Z" id="pswp__icn-download"/>',
outlineID: 'pswp__icn-download',
},
onInit: (el, pswp) => {
el.setAttribute('download', '');
el.setAttribute('target', '_blank');
el.setAttribute('rel', 'noopener');
static singletonRef = React.createRef<ImagePreviewer>();
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(
<ImagePreviewer ref={ImagePreviewer.singletonRef} />,
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 (
<Space>
<DownloadOutlined
className="f18 toolbar-icon"
onClick={() => {
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();
}}
/>
<RotateRightOutlined
className="f18 toolbar-icon"
onClick={() => {
overlayProps.onRotate(overlayProps.rotate + 90);
}}
/>
<CloseOutlined
className="f18 toolbar-icon"
onClick={() => overlayProps.onClose()}
/>
</Space>
);
};
return (
<PhotoSlider
className="widget-image-previewer"
images={this.urls.map((item: string) => ({ 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();
}
}
+5 -5
View File
@@ -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"