天天看點

超實用 Vue3 圖檔預覽元件PreviewImage

作者:web前端進階

#頭條創作挑戰賽#

今天給大家分享 vue3.js 開發圖檔切換預覽元件。

超實用 Vue3 圖檔預覽元件PreviewImage

preview-image 圖檔預覽元件支援左右切換、旋轉、放大/縮小、重置等功能。

超實用 Vue3 圖檔預覽元件PreviewImage
超實用 Vue3 圖檔預覽元件PreviewImage
超實用 Vue3 圖檔預覽元件PreviewImage
超實用 Vue3 圖檔預覽元件PreviewImage
超實用 Vue3 圖檔預覽元件PreviewImage
<Preview
    v-model="showPreview"
    :previewSrcList="previewSrcList"
    :current="current"
    :infinite="infinite"
    :opacity="opacity"
    :shadeClose="shadeClose"
    :z-index="zIndex"
    :zoom="zoom"
    :toolbar="toolbar"
    :tooltip="tooltip"
    :anim="anim"
    :appendToBody="appendToBody"
    @close="closePreview"
    @switch="switchPreview"
>
    <!-- 預覽插槽 -->
    <slot name="preview"></slot>
</Preview>           

底部工具欄采用透明磨砂效果,支援tooltip提示。

參數配置

const props = defineProps({
		// 是否顯示
		modelValue: { type: Boolean, default: false },
		// 開啟圖檔預覽功能
		previewSrcList: { type: [String, Array] },
		// 開啟預覽是否展示底部工具欄
		toolbar: { type: [Boolean, String], default: true },
		// 是否展示工具欄的提示
		tooltip: { type: [Boolean, String] },
		// 目前預覽圖檔索引
		current: { type: [Number, String] },
		// 是否可以無限循環預覽
		infinite: { type: [Boolean, String], default: true },
		// 遮罩層透明度
		opacity: { type: [Number, String] },
		// 點選遮罩層關閉預覽
		shadeClose: { type: [Boolean, String], default: true },
		// 縮放比例
		zoom: { type: [Number, String], default: 1.1 },
		// 設定圖檔預覽的z-index
		zIndex: { type: [Number, String], default: 2023 },
		// 預覽彈窗動畫(down / up)
		anim: { type: String, default: 'down' },
		// 預覽圖檔是否插入到body
		appendToBody: { type: [Boolean, String] }
	})           

Image預覽模闆

<template>
    <teleport to="body" :disabled="!appendToBody">
        <transition name="ve-image-preview-fade" mode="out-in" appear>
            <div
                v-if="visible"
                ref="previewImgRef"
                class="ve-image-preview__wrapper"
                :style="[
                    {'z-index': zIndex}
                ]"
            >
                <!-- 遮罩層 -->
                <div class="ve-image-preview__mask" @click.self="handleMask" :style="{opacity}"></div>

                <!-- 工具欄 -->
                <div class="ve-image-preview__toolbar">
                    <Icon name="ve-icon-prev" v-tooltip="{content: '上一張'}" cursor @click="handlePrev" />
                    <Icon name="ve-icon-next" v-tooltip="{content: '下一張'}" cursor @click="handleNext" />
                    <Icon name="ve-icon-rotateLeft" v-tooltip="{content: '向左旋轉'}" cursor @click="handleAction('rotateLeft')" />
                    <Icon name="ve-icon-rotateRight" v-tooltip="{content: '向右旋轉'}" cursor @click="handleAction('rotateRight')" />
                    <Icon name="ve-icon-reset" v-tooltip="{content: '原始尺寸'}" cursor @click="handleAction('reset')" />
                    <Icon name="ve-icon-zoomBig" v-tooltip="{content: '放大'}" cursor @click="handleAction('zoomIn')" />
                    <Icon name="ve-icon-zoomSmall" v-tooltip="{content: '縮小'}" cursor @click="handleAction('zoomOut')" />
                    <Icon name="ve-icon-guanbi" v-tooltip="{content: '關閉'}" cursor @click="handleClose" />
                </div>

                <!-- 預覽圖 -->
                <transition :name="`ve-image-preview-slide-${anim}`" mode="out-in" appear>
                    <div class="ve-image-preview__gallery" :class="{'ve-image-preview__loading': loading}">
                        <img
                            ref="imgRef"
                            class="ve-image-preview__img"
                            :src="activeImg"
                            :style="imgStyle"
                            @load="handleLoad"
                            @error="handleError"
                            @mousedown="handleMousedown"
                            @mousewheel="handleMouseWheel"
                        />
                    </div>
                </transition>
                <!-- 優化拖拽卡頓 -->
                <div ref="dragfixRef" class="ve-image-preview__dragfix"></div>
            </div>
        </transition>
    </teleport>
</template>           
/* 工具欄事件 */
const handleAction = (action) => {
    if(loading.value) return
    switch(action) {
        case 'rotateLeft':
            handleRotateLeft()
            break
        case 'rotateRight':
            handleRotateRight()
            break
        case 'reset':
            handleReset()
            break
        case 'zoomIn':
            handleZoomIn()
            break
        case 'zoomOut':
            handleZoomOut()
            break
    }
    transform.value.enableTransition = true
}
// 上一張
const handlePrev = () => {
    if(isFirst.value && !props.infinite) return
    setActive(activeIndex.value - 1)
}
// 下一張
const handleNext = () => {
    if(isLast.value && !props.infinite) return
    setActive(activeIndex.value + 1)
}
// 向左旋轉
const handleRotateLeft = () => {
    transform.value.deg -= 90
}
// 向右旋轉
const handleRotateRight = () => {
    transform.value.deg += 90
}
// 縮放到原始尺寸
const handleReset = () => {
    transform.value = {
        scale: 1,
        deg: 0,
        offsetX: 0,
        offsetY: 0
    }
}
// 放大
const handleZoomIn = () => {
    if(transform.value.scale < 7) {
        transform.value.scale = Number.parseFloat((transform.value.scale * props.zoom).toFixed(3))
    }
}
// 縮小
const handleZoomOut = () => {
    if(transform.value.scale > .2) {
        transform.value.scale = Number.parseFloat((transform.value.scale / props.zoom).toFixed(3))
    }
}
// 關閉預覽
const handleClose = () => {
    handleReset()
    emit('update:modelValue', false)
    emit('close')
}           

ok,基于vue3開發圖檔預覽元件就分享到這裡。

繼續閱讀