feat: Add ImageViewer component and add ImageViewer demo
This commit is contained in:
parent
a18ad8f4a8
commit
af9fc0a4ad
|
@ -63,6 +63,7 @@ const dialogStyle = computed(() => {
|
||||||
:fullscreen="isFullscreen"
|
:fullscreen="isFullscreen"
|
||||||
destroy-on-close
|
destroy-on-close
|
||||||
lock-scroll
|
lock-scroll
|
||||||
|
draggable
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import ImageViewer from './src/ImageViewer.vue'
|
||||||
|
import { isClient } from '@/utils/is'
|
||||||
|
import { createVNode, render, VNode } from 'vue'
|
||||||
|
import { ImageViewerProps } from './src/types'
|
||||||
|
|
||||||
|
let instance: Nullable<VNode> = null
|
||||||
|
|
||||||
|
export function createImageViewer(options: ImageViewerProps) {
|
||||||
|
if (!isClient) return
|
||||||
|
const {
|
||||||
|
urlList,
|
||||||
|
initialIndex = 0,
|
||||||
|
infinite = true,
|
||||||
|
hideOnClickModal = false,
|
||||||
|
appendToBody = false,
|
||||||
|
zIndex = 2000,
|
||||||
|
show = true
|
||||||
|
} = options
|
||||||
|
|
||||||
|
const propsData: Partial<ImageViewerProps> = {}
|
||||||
|
const container = document.createElement('div')
|
||||||
|
propsData.urlList = urlList
|
||||||
|
propsData.initialIndex = initialIndex
|
||||||
|
propsData.infinite = infinite
|
||||||
|
propsData.hideOnClickModal = hideOnClickModal
|
||||||
|
propsData.appendToBody = appendToBody
|
||||||
|
propsData.zIndex = zIndex
|
||||||
|
propsData.show = show
|
||||||
|
|
||||||
|
document.body.appendChild(container)
|
||||||
|
instance = createVNode(ImageViewer, propsData)
|
||||||
|
render(instance, container)
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ElImageViewer } from 'element-plus'
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import { imageViewerProps } from './props'
|
||||||
|
|
||||||
|
const props = defineProps(imageViewerProps)
|
||||||
|
|
||||||
|
const getBindValue = computed(() => {
|
||||||
|
const propsData: Recordable = { ...props }
|
||||||
|
delete propsData.show
|
||||||
|
return propsData
|
||||||
|
})
|
||||||
|
|
||||||
|
const show = ref(props.show)
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
show.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ElImageViewer v-if="show" v-bind="getBindValue" @close="close" />
|
||||||
|
</template>
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { PropType } from 'vue'
|
||||||
|
|
||||||
|
export const imageViewerProps = {
|
||||||
|
urlList: {
|
||||||
|
type: Array as PropType<string[]>,
|
||||||
|
default: (): string[] => []
|
||||||
|
},
|
||||||
|
zIndex: {
|
||||||
|
type: Number as PropType<number>,
|
||||||
|
default: 2000
|
||||||
|
},
|
||||||
|
initialIndex: {
|
||||||
|
type: Number as PropType<number>,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
infinite: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
hideOnClickModal: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
appendToBody: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
show: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
export interface ImageViewerProps {
|
||||||
|
urlList?: string[]
|
||||||
|
zIndex?: number
|
||||||
|
initialIndex?: number
|
||||||
|
infinite?: boolean
|
||||||
|
hideOnClickModal?: boolean
|
||||||
|
appendToBody?: boolean
|
||||||
|
show?: boolean
|
||||||
|
}
|
|
@ -105,7 +105,8 @@ export default {
|
||||||
defaultTable: 'Basic example',
|
defaultTable: 'Basic example',
|
||||||
editor: 'Editor',
|
editor: 'Editor',
|
||||||
richText: 'Rich text',
|
richText: 'Rich text',
|
||||||
dialog: 'Dialog'
|
dialog: 'Dialog',
|
||||||
|
imageViewer: 'Image viewer'
|
||||||
},
|
},
|
||||||
analysis: {
|
analysis: {
|
||||||
newUser: 'New user',
|
newUser: 'New user',
|
||||||
|
@ -343,5 +344,10 @@ export default {
|
||||||
dialogDes: 'Secondary packaging of Dialog components based on ElementPlus',
|
dialogDes: 'Secondary packaging of Dialog components based on ElementPlus',
|
||||||
open: 'Open',
|
open: 'Open',
|
||||||
close: 'Close'
|
close: 'Close'
|
||||||
|
},
|
||||||
|
imageViewerDemo: {
|
||||||
|
open: 'Open',
|
||||||
|
imageViewer: 'Image viewer',
|
||||||
|
imageViewerDes: 'Secondary packaging of ImageViewer components based on ElementPlus'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,8 @@ export default {
|
||||||
defaultTable: '基础示例',
|
defaultTable: '基础示例',
|
||||||
editor: '编辑器',
|
editor: '编辑器',
|
||||||
richText: '富文本',
|
richText: '富文本',
|
||||||
dialog: '弹窗'
|
dialog: '弹窗',
|
||||||
|
imageViewer: '图片预览'
|
||||||
},
|
},
|
||||||
analysis: {
|
analysis: {
|
||||||
newUser: '新增用户',
|
newUser: '新增用户',
|
||||||
|
@ -340,5 +341,10 @@ export default {
|
||||||
dialogDes: '基于 ElementPlus 的 Dialog 组件二次封装',
|
dialogDes: '基于 ElementPlus 的 Dialog 组件二次封装',
|
||||||
open: '打开',
|
open: '打开',
|
||||||
close: '关闭'
|
close: '关闭'
|
||||||
|
},
|
||||||
|
imageViewerDemo: {
|
||||||
|
open: '打开',
|
||||||
|
imageViewer: '图片预览',
|
||||||
|
imageViewerDes: '基于 ElementPlus 的 ImageViewer 组件二次封装'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,6 +193,14 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
|
||||||
title: t('router.search')
|
title: t('router.search')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'image-viewer',
|
||||||
|
component: () => import('@/views/Components/ImageViewer.vue'),
|
||||||
|
name: 'ImageViewer',
|
||||||
|
meta: {
|
||||||
|
title: t('router.imageViewer')
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'dialog',
|
path: 'dialog',
|
||||||
component: () => import('@/views/Components/Dialog.vue'),
|
component: () => import('@/views/Components/Dialog.vue'),
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
|
import { createImageViewer } from '@/components/ImageViewer'
|
||||||
|
import { ElButton } from 'element-plus'
|
||||||
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const open = () => {
|
||||||
|
createImageViewer({
|
||||||
|
urlList: [
|
||||||
|
'https://img1.baidu.com/it/u=657828739,1486746195&fm=26&fmt=auto&gp=0.jpg',
|
||||||
|
'https://img0.baidu.com/it/u=3114228356,677481409&fm=26&fmt=auto&gp=0.jpg',
|
||||||
|
'https://img1.baidu.com/it/u=508846955,3814747122&fm=26&fmt=auto&gp=0.jpg',
|
||||||
|
'https://img1.baidu.com/it/u=3536647690,3616605490&fm=26&fmt=auto&gp=0.jpg',
|
||||||
|
'https://img1.baidu.com/it/u=4087287201,1148061266&fm=26&fmt=auto&gp=0.jpg',
|
||||||
|
'https://img2.baidu.com/it/u=3429163260,2974496379&fm=26&fmt=auto&gp=0.jpg'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ContentWrap
|
||||||
|
:title="t('imageViewerDemo.imageViewer')"
|
||||||
|
:message="t('imageViewerDemo.imageViewerDes')"
|
||||||
|
>
|
||||||
|
<ElButton type="primary" @click="open">{{ t('imageViewerDemo.open') }}</ElButton>
|
||||||
|
</ContentWrap>
|
||||||
|
</template>
|
Loading…
Reference in New Issue