0.0.13 • Published 1 year ago

vue3-image-viewer v0.0.13

Weekly downloads
-
License
-
Repository
github
Last release
1 year ago

安装/Installation

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

引入/Import

import { Image } from 'vue3-image-viewer';

效果预览/Preview

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

使用示例/Example

<template>
  <div class="image">
    <div class="item" v-for="(item, index) in images" :key="item.url">
      <Image
        width="270px"
        height="300px"
        :src="item.url"
        preview
        :images="images"
        :initialIndex="index"
      >
        <template #footer>footer</template>
        <template #loading>LOADING</template>
        <template #error>ERROR</template>
      </Image>
    </div>
  </div>
</template>

<script setup>
import { Image } from 'vue3-image-viewer'
import 'vue3-image-viewer/dist/style.css'
const images = [
  {
    title: 'title',
    desc: 'desc',
    url: 'http://iph.href.lu/800x540',
  },
  {
    title: 'title',
    desc: 'desc',
    url: 'https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg',
  },
  {
    title: 'title',
    desc: 'desc',
    url: 'https://fuss10.elemecdn.com/1/8e/aeffeb4de74e2fde4bd74fc7b4486jpeg.jpeg',
  },
  {
    title: 'title',
    desc: 'desc',
    url: '',
  },
];
</script>

<style lang="less" scoped>
.image {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  justify-content: space-between;
  width: 1200px;
  margin: 0 auto;
}
</style>
<template>
  <div class="viewer">
    <div class="viewer-wrap">
      <!-- 如果传入了markList则不取images中的marks -->
      <Viewer
        ref="viewerRef"
        :imageList="images"
        navigation
        toolbar
        drawable
        deleteable
        :scaleMin="1"
        @drawEnd="drawEnd"
        @resize="onResize"
        @delete="onDelete"
        @switch="onSwitch"
        :initialIndex="currentIndex"
      >
        <template #loading>LOADING</template>
        <template #error>ERROR</template>
      </Viewer>
      <!-- 自定义 -->
      <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>
    <div class="preview">
      <div class="item" v-for="(item, index) in current.marks" :key="index">
        <Viewer :image="current" :mark="item" focus>
          <template #loading>LOADING</template>
          <template #error>ERROR</template>
        </Viewer>
      </div>
    </div>
  </div>
</template>

<script setup>
import { Viewer } from 'vue3-image-viewer'
import 'vue3-image-viewer/dist/style.css'
import { reactive, ref, computed, unref } from 'vue';
const images = reactive([
  {
    title: 'title',
    desc: 'desc',
    url: 'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
    thumbnail:
      'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
    marks: [],
  },
  {
    title: 'title',
    desc: 'desc',
    url: 'https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg',
    thumbnail:
      'https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg',
    marks: [
      {
        width: 220,
        height: 220,
        left: 470,
        top: 230,
      },
    ],
  },
  {
    title: 'title',
    desc: 'desc',
    url: 'https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
    thumbnail:
      'https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
    marks: [
      {
        width: 80,
        height: 40,
        left: 320,
        top: 220,
      },
    ],
  },
  {
    title: 'title',
    desc: 'desc',
    url: '',
    thumbnail: '',
    marks: [],
  },
]);
const currentIndex = ref(1);
const current = computed(() => images[currentIndex.value]);
const viewerRef = ref(null);

function onSwitch(index) {
  currentIndex.value = index;
}
function onResize({ target, detail }) {
  const { left, top, width, height } = detail;
  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 drawEnd(item) {
  const { left, top, width, height } = item;
  if (!current.value.marks) {
    current.value.marks = [];
  }
  const newMark = {
    id: current.value.marks.length + 1 + '',
    left,
    top,
    width,
    height,
  };

  current.value.marks.unshift(newMark);
}
function toolBtn(type) {
  const viewer = unref(viewerRef);
  if (!viewer) {
    return;
  }
  if (type === 'fit') {
    viewer.toggleFit();
  }
  if (type === 'next') {
    viewer.next();
  }
  if (type === 'prev') {
    viewer.prev();
  }
  if (type === 'reset') {
    viewer.reset();
  }
}
</script>

<style lang="less" scoped>
.viewer {
  width: 1200px;
  margin: 0 auto;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  .viewer-wrap {
    width: 1000px;
    height: 600px;
    .tools {
      display: flex;
      justify-content: center;
      gap: 10px;
      margin-top: 10px;
      div {
        border: 1px solid #ccc;
        border-radius: 4px;
        cursor: pointer;
        padding: 0 5px;
        font-size: 14px;
        line-height: 22px;
      }
    }
  }
  .preview {
    width: 200px;
    margin-left: 20px;
    height: 600px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 10px;
    .item {
      width: 100%;
      height: 150px;
    }
  }
}
</style>

Image 组件说明

传参/Props

参数说明类型默认值
base地址前缀string""
src图片地址string""
tokentoken 参数string""
aspectRatio固定宽高比number0
fitobject-fitstring"fill"
lazy懒加载booleanfalse
hideOnClickModal点击遮罩关闭预览booleanfalse
initialIndex在预览数组中的位置number0
preview是否开启预览booleanfalse
images预览列表array[]
loop开启循环booleanfalse
preload预览预加载array or boolean0,2
width盒子宽度string""
height盒子高度string""
altaltstring""
referrerPolicyreferrerPolicystring""
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""
tokentoken 参数string""
scaleMax最大缩放倍数number15
scaleMin最小缩放倍数number1
scaleStep缩放步进number1.1
initialScale初始缩放倍数number1
imageList图片列表array[]
markList标记框列表array[]
initialIndex初始展示图片下标number0
loop开启循环boolean0
navigation底部预览条booleanfalse
toolbar工具栏booleanfalse
keyboard开启快捷键array'A', 'D'
fitobject-fitstring"contain"
preload图片预加载array or boolean0,2
fixed禁止缩放booleanfalse
focus锁定标记框的展示模式booleanfalse
drawable是否开启标记功能booleanfalse
deleteable是否显示移除标记框的按钮booleanfalse
image单张图片objectnull
mark单个标记框objectnull

参数说明/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

  • clearDraw: 清除绘制的标记框图
  • switchIndex: 切换图片,传入图片下标值
  • 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: 图片底部工具栏的占位

补充说明

联系我/Contact me

0.0.11

1 year ago

0.0.12

1 year ago

0.0.13

1 year ago

0.0.10

2 years ago

0.0.3

2 years ago

0.0.9

2 years ago

0.0.8

2 years ago

0.0.5

2 years ago

0.0.4

2 years ago

0.0.7

2 years ago

0.0.6

2 years ago

5.0.3

3 years ago

5.0.2

3 years ago

5.0.1

3 years ago

0.0.1

3 years ago

0.0.2

2 years ago

5.0.0

3 years ago

4.5.0

3 years ago

4.3.28

3 years ago

4.4.46

3 years ago

4.4.45

3 years ago

4.4.44

3 years ago

4.4.43

3 years ago

4.4.42

3 years ago

4.4.41

3 years ago

4.4.40

3 years ago

4.4.39

3 years ago

4.4.38

3 years ago

4.4.37

3 years ago

4.4.36

3 years ago

4.4.35

3 years ago

4.4.34

3 years ago

4.4.33

3 years ago

4.4.32

3 years ago

4.4.31

3 years ago

4.4.30

3 years ago

4.4.29

3 years ago

4.4.28

3 years ago

4.4.27

3 years ago

4.3.27

3 years ago

4.3.26

3 years ago

4.3.25

3 years ago

4.3.24

3 years ago

4.2.24

3 years ago

4.2.23

3 years ago

4.2.22

3 years ago

4.2.21

3 years ago

4.1.21

3 years ago

4.1.20

3 years ago

4.1.19

3 years ago

4.1.18

3 years ago

4.1.17

3 years ago

4.1.16

3 years ago

4.1.15

3 years ago

4.1.14

3 years ago

4.1.13

3 years ago

3.1.13

3 years ago

3.1.12

3 years ago

3.1.11

3 years ago

2.0.12

3 years ago

1.1.12

3 years ago

1.1.11

3 years ago

1.1.10

3 years ago

1.1.9

3 years ago

1.1.8

3 years ago

1.1.7

3 years ago

1.1.6

3 years ago

1.1.5

3 years ago

1.1.4

3 years ago

1.1.3

3 years ago

1.0.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago