mirror of
https://github.com/eyebluecn/tank-front
synced 2024-04-21 12:31:55 +00:00
feat: change img previewer
This commit is contained in:
+1
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user