【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

相关推荐
大鸡爪几秒前
Vue3 组件库实战(五):Icon 图标组件的设计与实现
前端·vue.js
bluceli几秒前
前端测试实战指南:构建高质量代码的完整体系
前端·测试
行走的陀螺仪1 分钟前
前端公共库开发保姆级路线:从0到1复刻VueUse官方级架构(pnpm+Turbo+VitePress)
前端·架构
顽固_倔强1 分钟前
深入理解 Vue3 数据绑定实现原理
前端·面试
前端付豪1 分钟前
组件拆分重构 App.vue
前端·架构·代码规范
Wect2 分钟前
React 更新触发原理详解
前端·react.js·面试
cxxcode2 分钟前
Web 帧渲染与 DOM 准备
前端
光影少年3 分钟前
React Hooks的理解?常用的有哪些?
前端·react.js·掘金·金石计划
大鸡爪3 分钟前
Vue3 组件库实战(七):从本地到 NPM:版本管理与自动化发布指南(下)
前端·vue.js
幸福摩天轮4 分钟前
记录commonjs的一道面试题
前端