美文网首页
Vue3中使用图片查看组件 支持vue3的图片组件

Vue3中使用图片查看组件 支持vue3的图片组件

作者: zhoulh_cn | 来源:发表于2022-01-05 23:04 被阅读0次

安装/Installation

npm i vue3-image-viewer
或者/or
yarn add vue3-image-viewer

引入/Import

import { Image } from 'vue3-image-viewer';
import 'vue3-image-viewer/dist/style.css';

使用示例/Example

<template>
  <div class="vue3-image-viewer">
    <section class="image">
      <div class="image-wrap" v-for="(item, index) in images" :key="item.url">
        <Image
          :base="base"
          :src="item.url"
          :token="token"
          :aspectRatio="3 / 4"
          fit="contain"
          lazy
          hideOnClickModal
          :initialIndex="index"
          preview
          :images="images"
          loop
          :preload="[-2, 2]"
          width="220px"
          alt="图片组件测试"
          bgColor="lightpink"
          @error="imageError"
          @load="imageLoad"
          @close="imageClose"
          @switch="ImageSwitch"
        >
          <template v-slot:footer>footer</template>
          <template v-slot:loading>LOADING</template>
          <template v-slot:error>ERROR</template>
        </Image>
      </div>
    </section>
    <section class="viewer">
      <div class="preview">
        <div class="item" v-for="(item, index) in current.marks" :key="index">
          <Viewer
            :base="base"
            :token="token"
            :image="current"
            :mark="item"
            focus
          >
            <template v-slot:loading>LOADING</template>
            <template v-slot:error>ERROR</template>
          </Viewer>
        </div>
      </div>
      <!-- 自定义 -->
      <div class="tools">
        <div @click="toolBtn('fit')">适应窗口</div>
        <div @click="toolBtn('prev')">上一个</div>
        <div @click="toolBtn('next')">下一个</div>
        <div @click="toolBtn('reset')">重置</div>
      </div>
      <div class="viewer-wrap">
        <!-- 如果传入了markList则不取images中的marks -->
        <Viewer
          ref="viewer"
          :base="base"
          :token="token"
          :scaleMax="20"
          :scaleMin="0.1"
          :scaleStep="1.2"
          :initialScale="1"
          :imageList="images"
          :markList="current.marks"
          :initialIndex="currentIndex"
          loop
          navigation
          toolbar
          drawable
          deleteable
          :keyboard="['A', 'D', 'Space', 'Esc']"
          @error="onError"
          @load="onLoad"
          @switch="onSwitch"
          @drawEnd="drawEnd"
          @resize="onResize"
          @delete="onDelete"
          @zoom="onZoom"
        >
          <template v-slot:loading>LOADING</template>
          <template v-slot:error>ERROR</template>
        </Viewer>
      </div>
    </section>
  </div>
</template>

<script setup lang="ts">
import { Image, Viewer } from 'vue3-image-viewer';
import { reactive, ref, computed } from 'vue';
const viewer = ref(null);
const currentIndex = ref(0);
const base = 'https://cube.elemecdn.com/';
const token = 'token';
const images = reactive([
  {
    title: '1',
    desc: 'A',
    url: 'a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
    thumbnail: 'a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
    marks: [
      {
        id: '1',
        left: 0,
        top: 0,
        width: 100,
        height: 100,
      },
      {
        id: '2',
        left: 200,
        top: 200,
        width: 50,
        height: 100,
      },
    ],
  },
  {
    title: '2',
    desc: 'B',
    url: 'd/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg',
    thumbnail: 'd/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg',
  },
  {
    title: '3',
    desc: 'C',
    url: '1/8e/aeffeb4de74e2fde4bd74fc7b4486jpeg.jpeg1',
    thumbnail:
      '1/8e/aeffeb4de74e2fde4bd74fc7b4486jpeg.jpeg1',
  },
  {
    title: '4',
    desc: 'B',
    url: 'a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
    thumbnail: 'a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
  },
  {
    title: '5',
    desc: 'B',
    url: 'a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
    thumbnail: 'a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
  },
  {
    title: '6',
    desc: 'B',
    url: 'a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
    thumbnail: 'a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
  },
  {
    title: '7',
    desc: 'B',
    url: 'a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
    thumbnail: 'a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
  },
  {
    title: '8',
    desc: 'B',
    url: '6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg',
    thumbnail: '6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg',
  },
  {
    title: '9',
    desc: 'B',
    url: '9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg',
    thumbnail: '9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg',
  },
  {
    title: '10',
    desc: 'B',
    url: '3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
    thumbnail: '3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
  },
]);
const current = computed(() => {
  return images[currentIndex.value];
});

function onError(err) {
  // console.log(err);
}
function onLoad(ev) {
  // console.log(ev);
}
function onSwitch(index) {
  // console.log(index);
  currentIndex.value = index;
}
function drawEnd(item) {
  const { left, top, width, height } = item;
  if (!current.value.marks) {
    current.value.marks = [];
  }
  current.value.marks.push({
    id: current.value.marks.length + 1 + '',
    left,
    top,
    width,
    height,
  });
}
function onResize({ target, detail }) {
  const { left, top, width, height } = detail;
  console.log(left, top, width, height);
  const mark = { ...target };
  mark.left = left;
  mark.top = top;
  mark.width = width;
  mark.height = height;
  const idx = current.value.marks.indexOf(target);
  if (idx > -1) {
    current.value.marks.splice(idx, 1, mark);
  }
}
function onDelete({ target }) {
  const idx = current.value.marks.indexOf(target);
  if (idx > -1) {
    current.value.marks.splice(idx, 1);
  }
}
function onZoom(zoom) {
  // console.log(zoom);
}

function imageError(err) {
  // console.log(err);
}
function imageLoad(ev) {
  // console.log(ev);
}
function imageClose() {
  // console.log('close');
}
function ImageSwitch(idx) {
  // console.log(idx);
}

function toolBtn(type) {
  if (!viewer.value) {
    return;
  }
  if (type === 'fit') {
    viewer.value.toggleFit();
  }
  if (type === 'next') {
    viewer.value.next();
  }
  if (type === 'prev') {
    viewer.value.prev();
  }
  if (type === 'reset') {
    viewer.value.reset();
  }
}
</script>

<style lang="less" scoped>
.vue3-image-viewer {
  .image {
    width: 750px;
    margin: 20px auto;
    padding: 0 10px;
    max-height: 200px;
    overflow-y: auto;
    .image-wrap {
      float: left;
      margin: 10px;
    }
  }
  .viewer {
    margin-bottom: 50px;
    .preview {
      display: flex;
      // flex-wrap: wrap;
      .item {
        width: 200px;
        margin: 10px;
      }
    }
    .tools {
      width: 400px;
      margin: 20px auto;
      display: flex;
      justify-content: space-around;
      div {
        cursor: pointer;
        height: 22px;
        line-height: 22px;
        padding: 0 10px;
        border-radius: 2px;
        background-color: #333;
        color: #fff;
      }
    }
    padding: 0 20px;
    .viewer-wrap {
      width: 100%;
      height: 500px;
    }
  }
}
</style>

Image 组件说明

传参/Props

参数 说明 类型 默认值
base 地址前缀 string ""
src 图片地址 string ""
token token 参数 string ""
aspectRatio 固定宽高比 number 0
fit object-fit string "fill"
lazy 懒加载 boolean false
hideOnClickModal 点击遮罩关闭预览 boolean false
initialIndex 在预览数组中的位置 number 0
preview 是否开启预览 boolean false
images 预览列表 array []
loop 开启循环 boolean false
preload 预览预加载 array or boolean [0,2]
width 盒子宽度 string ""
height 盒子高度 string ""
alt alt string ""
referrerPolicy referrerPolicy string ""
bgColor 背景颜色 string "black"

参数说明/Props Explanation

  • src: 如果 src 是绝对地址,则 base, token 不生效,如果是相对地址,返回 base+src+?token="abc"
  • width&height: 可以设置固定 px 值或者百分比值,等同于原生 css 属性
  • aspectRatio: 如果设置了 aspectRatio,则高度由宽度和 aspectRatio 决定,height 不再生效
  • preload: 如果设置为 false 则关闭预加载,如果设置为[1,2],则在查看当前图片的同时会同时加载左边 1 张右边 2 张图片

组件事件/Event

  • error: 图片加载出错事件/ Same as native error
  • load: 图片加载完成事件/ Same as native load
  • close: 关闭预览事件 / Emit when close the preview
  • switch: 切换预览图片事件,返回下标 / Emit when switch the preview, return current index

支持插槽/Slot

  • error:加载出错占位/ Triggers when image load failed
  • loading:加载中占位/ Triggers when image is loading
  • footer:图片底部占位/ Placeholder on the bottom

Viewer 组件说明

传参/Props

参数 说明 类型 默认值
base 地址前缀 string ""
token token 参数 string ""
scaleMax 最大缩放倍数 number 15
scaleMin 最小缩放倍数 number 1
scaleStep 缩放步进 number 1.1
initialScale 初始缩放倍数 number 1
imageList 图片列表 array []
markList 标记框列表 array []
initialIndex 初始展示图片下标 number 0
loop 开启循环 boolean 0
navigation 底部预览条 boolean false
toolbar 工具栏 boolean false
keyboard 开启快捷键 array ['A', 'D']
fit object-fit string "contain"
preload 图片预加载 array or boolean [0,2]
fixed 禁止缩放 boolean false
focus 锁定标记框的展示模式 boolean false
drawable 是否开启标记功能 boolean false
deleteable 是否显示移除标记框的按钮 boolean false
image 单张图片 object null
mark 单个标记框 object null

参数说明/Props Explanation

  • scaleStep: 按倍数缩进
  • keyboard: 支持的快捷键有上一项: A,下一项: D,锁定标记框: Space,取消框图锁定: Esc
  • imageList: 数据结构请参考示例代码,优先使用imageList,其次使用image
  • markList: 数据结构请参考示例代码,标记框优先使用markList,其次是image的marks字段,再次是mark字段
  • focus: focus模式下,不可缩放,锁定标记框,不可调整大小
  • drawable: 开启绘制标记框的功能

组件事件/Event

  • error: 图片加载出错事件/ Same as native error
  • load: 图片加载完成事件/ Same as native load
  • switch: 切换预览图片事件,返回下标 / Emit when switch the preview, return current index
  • drawEnd: 绘制结束时的事件,返回标记框图的关键信息
  • resize: 调整大小结束时的事件,返回resize的关键信息
  • delete: 点击移除按钮时触发的事件,返回点击的对象
  • zoom: 缩放时触发的事件,返回当前的缩放倍数

组件方法/Methods

  • clear: 清除绘制的标记框图
  • switch: 切换图片,传入图片下标值
  • toggleFit: 切换contain和cover模式
  • unFocusMark: 取消框图锁定
  • focusMark: 锁定框图
  • reset: 重置图片状态(缩放、移动等)
  • download: 下载图片
  • zoomOut: 放大
  • zoomIn: 缩小
  • prev: 上一张
  • next: 下一张

支持插槽/Slot

  • error: 加载出错占位/ Triggers when image load failed
  • loading: 加载中占位/ Triggers when image is loading
  • toolbar: 图片底部工具栏的占位

预览效果/Preview

图片列表
图片预览
绘图
调整大小

补充说明

联系我/Contact me

相关文章

网友评论

      本文标题:Vue3中使用图片查看组件 支持vue3的图片组件

      本文链接:https://www.haomeiwen.com/subject/qqflcrtx.html