【sgPhotoPlayer】自定义组件:图片预览,支持点击放大、缩小、旋转图片

特性:

  1. 支持设置初始索引值
  2. 支持显示标题、日期、大小、当前图片位置
  3. 支持无限循环切换轮播
  4. 支持鼠标滑轮滚动、左右键、上下键、PageUp、PageDown、Home、End操作切换图片
  5. 支持Esc关闭窗口

sgPhotoPlayer源码

html 复制代码
<template>
  <div :class="$options.name" v-if="visible">
    <div class="swiper-container">
      <el-carousel
        class="image-swiper"
        ref="carousel"
        :initial-index="currentIndex"
        :autoplay="false"
        :height="'100%'"
        :indicator-position="swiperItems.length <= 1 ? 'none' : ''"
        :arrow="swiperItems.length <= 1 ? 'never' : ''"
        @change="(idx) => (currentIndex = idx)"
      >
        <el-carousel-item v-for="(a, $i) in swiperItems" :key="$i">
          <el-image
            draggable="false"
            style="width: 600px; height: 400px"
            :src="a.sm"
            :preview-src-list="swiperItems.map((v) => v.lg)"
            :initial-index="$i"
            :fit="'cover'"
          >
          </el-image>
        </el-carousel-item>
      </el-carousel>
      <div class="desc">
        <label class="number"
          >当前位置:{{ currentIndex + 1 }}/{{ swiperItems.length }}</label
        >
        <label
          class="title"
          :title="`${swiperItems[currentIndex].title}(${swiperItems[currentIndex].size})`"
          >{{ swiperItems[currentIndex].title }}({{ swiperItems[currentIndex].size }})
        </label>
        <label class="date">{{ swiperItems[currentIndex].date }}</label>
      </div>
    </div>

    <el-tooltip
      :content="`关闭`"
      :effect="`light`"
      :enterable="false"
      :placement="`top-start`"
      :popper-class="`sg-el-tooltip`"
      :transition="`none`"
      ><el-button
        class="sg-closeModalBtn"
        type="primary"
        icon="el-icon-close"
        @click="visible = false"
        circle
      />
    </el-tooltip>
    <div class="bg" @click="visible = false"></div>
  </div>
</template>

<script>
export default {
  name: "sgPhotoPlayer",
  data() {
    return {
      currentIndex: 0,
      showBigImg: false,
      loading: false, //是否加载中
      visible: false, //是否显示
      swiperItems: [
        /*  {
          title:`标题`,
          date:`时间`,
          size:`文件大小`,
          sm: "static/img/sm/1.jpg",//小图路径
          lg: "static/img/lg/1.jpg",//大图路径
        }, */
      ],
    };
  },
  props: [
    "data",
    "value", //是否显示
  ],
  watch: {
    value: {
      handler(d) {
        this.visible = d;
      },
      deep: true,
      immediate: true,
    },
    visible(d) {
      this.$emit("input", d);
      if (d) {
        this.$nextTick(() => {
          this.addEvents();
        });
      } else {
        this.removeEvents();
      }
    },
    data: {
      handler(newValue, oldValue) {
        if (newValue && Object.keys(newValue).length) {
          this.currentIndex = newValue.currentIndex; //默认显示的图片索引
          this.swiperItems = newValue.photos;
        }
      },
      deep: true, //深度监听
      immediate: true, //立即执行
    },
  },
  mounted() {},
  destroyed() {
    this.removeEvents();
  },

  methods: {
    addEvents(d) {
      this.removeEvents();
      addEventListener("mousewheel", this.mousewheel);
      addEventListener("keydown", this.keydown);
      addEventListener("keyup", this.keyup);
    },
    removeEvents(d) {
      removeEventListener("mousewheel", this.mousewheel);
      removeEventListener("keydown", this.keydown);
      removeEventListener("keyup", this.keyup);
    },
    mousewheel(e) {
      this.showBigImg = Boolean(document.querySelector(`.el-image-viewer__mask`));
      if (this.showBigImg) return;
      if (e.deltaY < 0) return this.$refs.carousel.prev();
      if (e.deltaY > 0) return this.$refs.carousel.next();
    },
    keydown(e) {
      let key = e.key.toLocaleLowerCase();
      if (
        [
          "escape",
          "home",
          "end",
          "pageup",
          "arrowup",
          "arrowleft",
          "pagedown",
          "arrowdown",
          "arrowright",
        ].includes(key)
      ) {
        e.preventDefault();
        return false;
      }
    },
    keyup(e) {
      this.showBigImg = Boolean(document.querySelector(`.el-image-viewer__mask`));
      let key = e.key.toLocaleLowerCase();
      if (
        ["escape", "home", "end", "pageup", "arrowup", "pagedown", "arrowdown"].includes(
          key
        ) &&
        this.showBigImg
      )
        return;
      switch (key) {
        case "escape":
          this.visible = false;
          break;
        case "home":
          this.$refs.carousel.setActiveItem(0);
          break;
        case "end":
          this.$refs.carousel.setActiveItem(this.swiperItems.length - 1);
          break;
        case "pageup":
        case "arrowup":
        case "arrowleft":
          this.$refs.carousel.prev();
          break;
        case "pagedown":
        case "arrowdown":
        case "arrowright":
          this.$refs.carousel.next();
          break;
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.sgPhotoPlayer {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 2000;
  display: flex;
  justify-content: center;
  align-items: center;
  .swiper-container {
    position: absolute;
    width: 600px;
    height: 450px;
    margin: auto;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    >>> .image-swiper {
      width: 100%;
      height: 100%;
      overflow: hidden;
      .el-carousel__indicators {
        bottom: revert;
        top: 400px;
        margin-top: 10px;
        display: flex;
        justify-content: center;
        flex-wrap: wrap;
        width: 100%;
        li {
          padding: 2px;
        }
      }
      .el-carousel__container {
        margin-top: -30px;
        .el-carousel__arrow,
        .el-carousel__item {
          transition: 0.382s !important;
        }
        .el-carousel__arrow {
          // transform: translateY(-40px);
        }
        .el-carousel__item {
          display: flex;
          justify-content: center;
          flex-direction: column;
        }
      }
    }

    .desc {
      width: 100%;
      display: flex;
      justify-content: space-between;
      align-items: center;
      flex-wrap: nowrap;
      box-sizing: border-box;
      margin: auto;
      /*文本阴影*/
      color: white;
      text-shadow: 1px 1px 1px black;
      line-height: 1.6;
      & > * {
        font-family: "Microsoft YaHei", "DIN-Light";
        font-weight: normal;
        font-size: 14px !important;
        white-space: nowrap;
        /*单行省略号*/
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }

      .number {
        flex-shrink: 0;
        width: 140px;
      }
      .title {
        box-sizing: border-box;
        padding: 0 10px;
      }
      .date {
        flex-shrink: 0;
        width: 140px;
      }
    }
  }
  .bg {
    background-color: #000000cc;
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    top: 0;
    z-index: -1;
  }
}
</style>

应用

javascript 复制代码
    // 打开图片
    openPhoto(d) {

      this.photoData= {
        currentIndex: this.photos.findIndex((v) => v.ID == d.ID), //当前图片索引值
        photos: this.photos.map((v) => ({
          sm: v.smURL,//小图路径
          lg: v.lgURL,//大图路径
          title: this.$g.getFileFullName(v),//标题
          date: v.GXSJ,//时间
          size: this.$g.getFileSize(v),//文件大小
        })),
      };
      this.showPhotoPlayer = true;

    },

基于elment-UI的el-carousel和el-image组件el-carousel和el-image组合实现swiper左右滑动图片,点击某张图片放大预览的效果_el-carousel 配合el-image preview-src-list-CSDN博客文章浏览阅读970次。【代码】el-carousel和el-image组合实现swiper左右滑动图片,点击某张图片放大预览的效果。_el-carousel 配合el-image preview-src-listhttps://blog.csdn.net/qq_37860634/article/details/131516077

相关推荐
Leyla12 分钟前
【代码重构】好的重构与坏的重构
前端
影子落人间15 分钟前
已解决npm ERR! request to https://registry.npm.taobao.org/@vant%2farea-data failed
前端·npm·node.js
世俗ˊ39 分钟前
CSS入门笔记
前端·css·笔记
子非鱼92139 分钟前
【前端】ES6:Set与Map
前端·javascript·es6
6230_44 分钟前
git使用“保姆级”教程1——简介及配置项设置
前端·git·学习·html·web3·学习方法·改行学it
想退休的搬砖人1 小时前
vue选项式写法项目案例(购物车)
前端·javascript·vue.js
加勒比海涛1 小时前
HTML 揭秘:HTML 编码快速入门
前端·html
啥子花道1 小时前
Vue3.4 中 v-model 双向数据绑定新玩法详解
前端·javascript·vue.js
麒麟而非淇淋1 小时前
AJAX 入门 day3
前端·javascript·ajax
茶茶只知道学习2 小时前
通过鼠标移动来调整两个盒子的宽度(响应式)
前端·javascript·css