提交 e6093aa4 作者: 陈文彬

feat(img-preview): add imgPreview componnt

上级 2f268ca8
...@@ -26,11 +26,11 @@ ...@@ -26,11 +26,11 @@
"lodash-es": "^4.17.15", "lodash-es": "^4.17.15",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"path-to-regexp": "^6.1.0", "path-to-regexp": "^6.2.0",
"qrcode": "^1.4.4", "qrcode": "^1.4.4",
"vue": "^3.0.0", "vue": "^3.0.0",
"vue-i18n": "^9.0.0-beta.3", "vue-i18n": "^9.0.0-beta.4",
"vue-router": "^4.0.0-beta.12", "vue-router": "^4.0.0-beta.13",
"vuex": "^4.0.0-beta.4", "vuex": "^4.0.0-beta.4",
"vuex-module-decorators": "^1.0.1", "vuex-module-decorators": "^1.0.1",
"zxcvbn": "^4.4.2" "zxcvbn": "^4.4.2"
...@@ -51,8 +51,8 @@ ...@@ -51,8 +51,8 @@
"@types/rollup-plugin-visualizer": "^2.6.0", "@types/rollup-plugin-visualizer": "^2.6.0",
"@types/shelljs": "^0.8.8", "@types/shelljs": "^0.8.8",
"@types/zxcvbn": "^4.4.0", "@types/zxcvbn": "^4.4.0",
"@typescript-eslint/eslint-plugin": "^4.2.0", "@typescript-eslint/eslint-plugin": "^4.4.0",
"@typescript-eslint/parser": "^4.2.0", "@typescript-eslint/parser": "^4.4.0",
"@vue/compiler-sfc": "^3.0.0", "@vue/compiler-sfc": "^3.0.0",
"autoprefixer": "^9.8.6", "autoprefixer": "^9.8.6",
"babel-plugin-import": "^1.13.0", "babel-plugin-import": "^1.13.0",
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
"eslint": "^7.10.0", "eslint": "^7.10.0",
"eslint-config-prettier": "^6.12.0", "eslint-config-prettier": "^6.12.0",
"eslint-plugin-prettier": "^3.1.4", "eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-vue": "^7.0.0-beta.4", "eslint-plugin-vue": "^7.0.1",
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"husky": "^4.3.0", "husky": "^4.3.0",
"inquirer": "^7.3.3", "inquirer": "^7.3.3",
......
@import (reference) '../../../design/index.less'; @import (reference) '../../../design/index.less';
@header-height: 50px; @header-height: 40px;
@footer-height: 60px; @footer-height: 60px;
.basic-drawer { .basic-drawer {
......
import { defineComponent, ref, unref, computed, reactive, watch } from 'vue'; import { defineComponent, ref, unref, computed, reactive, watchEffect } from 'vue';
import { FadeTransition } from '/@/components/Transition/index';
import { basicProps } from './props'; import { basicProps } from './props';
import { Props } from './types'; import { Props } from './types';
...@@ -11,9 +9,9 @@ import { CloseOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons-vu ...@@ -11,9 +9,9 @@ import { CloseOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons-vu
import resumeSvg from '/@/assets/svg/preview/resume.svg'; import resumeSvg from '/@/assets/svg/preview/resume.svg';
import rotateSvg from '/@/assets/svg/preview/p-rotate.svg'; import rotateSvg from '/@/assets/svg/preview/p-rotate.svg';
import scaleSvg from '/@/assets/svg/preview/scale.svg'; import scaleSvg from '/@/assets/svg/preview/scale.svg';
import unscaleSvg from '/@/assets/svg/preview/unscale.svg'; import unScaleSvg from '/@/assets/svg/preview/unscale.svg';
import loadingSvg from '/@/assets/images/loading.svg'; import loadingSvg from '/@/assets/images/loading.svg';
import unrotateSvg from '/@/assets/svg/preview/unrotate.svg'; import unRotateSvg from '/@/assets/svg/preview/unrotate.svg';
enum StatueEnum { enum StatueEnum {
LOADING, LOADING,
DONE, DONE,
...@@ -29,6 +27,7 @@ interface ImgState { ...@@ -29,6 +27,7 @@ interface ImgState {
status: StatueEnum; status: StatueEnum;
moveX: number; moveX: number;
moveY: number; moveY: number;
show: boolean;
} }
const prefixCls = 'img-preview'; const prefixCls = 'img-preview';
...@@ -46,7 +45,9 @@ export default defineComponent({ ...@@ -46,7 +45,9 @@ export default defineComponent({
currentIndex: 0, currentIndex: 0,
moveX: 0, moveX: 0,
moveY: 0, moveY: 0,
show: props.show,
}); });
const wrapElRef = ref<HTMLDivElement | null>(null); const wrapElRef = ref<HTMLDivElement | null>(null);
const imgElRef = ref<HTMLImageElement | null>(null); const imgElRef = ref<HTMLImageElement | null>(null);
...@@ -133,16 +134,15 @@ export default defineComponent({ ...@@ -133,16 +134,15 @@ export default defineComponent({
} }
// 关闭 // 关闭
function handleClose() { function handleClose(e: MouseEvent) {
const { instance } = props; e && e.stopPropagation();
if (instance) { imgState.show = false;
instance.show = false;
}
// 移除火狐浏览器下的鼠标滚动事件 // 移除火狐浏览器下的鼠标滚动事件
document.body.removeEventListener('DOMMouseScroll', scrollFunc); document.body.removeEventListener('DOMMouseScroll', scrollFunc);
// 恢复火狐及Safari浏览器下的图片拖拽 // 恢复火狐及Safari浏览器下的图片拖拽
document.ondragstart = null; document.ondragstart = null;
} }
// 图片复原 // 图片复原
function resume() { function resume() {
initState(); initState();
...@@ -202,26 +202,15 @@ export default defineComponent({ ...@@ -202,26 +202,15 @@ export default defineComponent({
const { imageList } = props; const { imageList } = props;
return imageList.length > 1; return imageList.length > 1;
}); });
watch(
() => props.show, watchEffect(() => {
(show) => { if (props.show) {
if (show) { init();
init();
}
},
{
immediate: true,
} }
); if (props.imageList) {
watch(
() => props.imageList,
() => {
initState(); initState();
},
{
immediate: true,
} }
); });
const renderClose = () => { const renderClose = () => {
return ( return (
...@@ -247,7 +236,7 @@ export default defineComponent({ ...@@ -247,7 +236,7 @@ export default defineComponent({
return ( return (
<div class={`${prefixCls}__controller`}> <div class={`${prefixCls}__controller`}>
<div class={`${prefixCls}__controller-item`} onClick={() => scaleFunc(-0.15)}> <div class={`${prefixCls}__controller-item`} onClick={() => scaleFunc(-0.15)}>
<img src={unscaleSvg} /> <img src={unScaleSvg} />
</div> </div>
<div class={`${prefixCls}__controller-item`} onClick={() => scaleFunc(0.15)}> <div class={`${prefixCls}__controller-item`} onClick={() => scaleFunc(0.15)}>
<img src={scaleSvg} /> <img src={scaleSvg} />
...@@ -256,7 +245,7 @@ export default defineComponent({ ...@@ -256,7 +245,7 @@ export default defineComponent({
<img src={resumeSvg} /> <img src={resumeSvg} />
</div> </div>
<div class={`${prefixCls}__controller-item`} onClick={() => rotateFunc(-90)}> <div class={`${prefixCls}__controller-item`} onClick={() => rotateFunc(-90)}>
<img src={unrotateSvg} /> <img src={unRotateSvg} />
</div> </div>
<div class={`${prefixCls}__controller-item`} onClick={() => rotateFunc(90)}> <div class={`${prefixCls}__controller-item`} onClick={() => rotateFunc(90)}>
<img src={rotateSvg} /> <img src={rotateSvg} />
...@@ -277,41 +266,32 @@ export default defineComponent({ ...@@ -277,41 +266,32 @@ export default defineComponent({
}; };
return () => { return () => {
return ( return (
<FadeTransition> imgState.show && (
{() => <div class={prefixCls} ref={wrapElRef} onMouseup={handleMouseUp}>
props.show && ( <div class={`${prefixCls}-content`}>
<div class={prefixCls} ref={wrapElRef} onMouseup={handleMouseUp}> <img
<div class={`${prefixCls}-content`}> width="32"
<img src={loadingSvg}
width="32" class={[
src={loadingSvg} `${prefixCls}-image`,
v-show={imgState.status === StatueEnum.LOADING} imgState.status === StatueEnum.LOADING ? '' : 'hidden',
class={`${prefixCls}-image`} ]}
/> />
<img <img
v-show={imgState.status === StatueEnum.DONE} style={unref(getImageStyle)}
style={unref(getImageStyle)} class={[`${prefixCls}-image`, imgState.status === StatueEnum.DONE ? '' : 'hidden']}
class={`${prefixCls}-image`} ref={imgElRef}
ref={imgElRef} src={imgState.currentUrl}
src={imgState.currentUrl} onMousedown={handleAddMoveListener}
onMousedown={handleAddMoveListener} />
/> {renderClose()}
<img {renderIndex()}
width="32" {renderController()}
src={loadingSvg} {renderArrow('left')}
v-show={imgState.status === StatueEnum.LOADING} {renderArrow('right')}
class={`${prefixCls}-image`} </div>
/> </div>
{renderClose()} )
{renderIndex()}
{renderController()}
{renderArrow('left')}
{renderArrow('right')}
</div>
</div>
)
}
</FadeTransition>
); );
}; };
}, },
......
import { PropType } from 'vue'; import { PropType } from 'vue';
import { Props } from './types';
export const basicProps = { export const basicProps = {
show: { show: {
type: Boolean as PropType<boolean>, type: Boolean as PropType<boolean>,
default: false, default: false,
}, },
instance: {
type: Object as PropType<Props>,
default: null,
},
imageList: { imageList: {
type: [Array] as PropType<string[]>, type: [Array] as PropType<string[]>,
default: null, default: null,
......
...@@ -13,10 +13,10 @@ const menu: MenuModule = { ...@@ -13,10 +13,10 @@ const menu: MenuModule = {
path: '/context-menu', path: '/context-menu',
name: '右键菜单', name: '右键菜单',
}, },
// { {
// path: '/img-preview', path: '/img-preview',
// name: '图片预览', name: '图片预览',
// }, },
{ {
path: '/i18n', path: '/i18n',
name: '国际化', name: '国际化',
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
<div class="flex justify-center mt-4"> <div class="flex justify-center mt-4">
<img :src="img" v-for="img in imgList" :key="img" class="mr-2" @click="handleClick(img)" /> <img :src="img" v-for="img in imgList" :key="img" class="mr-2" @click="handleClick(img)" />
</div> </div>
<Alert message="无预览图" type="info" />
<a-button @click="handlePreview" type="primary" class="mt-4">预览图片</a-button>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
...@@ -21,7 +23,11 @@ ...@@ -21,7 +23,11 @@
function handleClick(img: string) { function handleClick(img: string) {
createImgPreview({ imageList: [img] }); createImgPreview({ imageList: [img] });
} }
return { imgList, handleClick };
function handlePreview() {
createImgPreview({ imageList: imgList });
}
return { imgList, handleClick, handlePreview };
}, },
}); });
</script> </script>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论