【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

相关推荐
GISer_Jing2 小时前
前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
前端·react.js·面试
落霞的思绪3 小时前
CSS复习
前端·css
咖啡の猫5 小时前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲7 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5818 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路8 小时前
GeoTools 读取影像元数据
前端
ssshooter8 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
你的人类朋友8 小时前
【Node.js】什么是Node.js
javascript·后端·node.js
Jerry9 小时前
Jetpack Compose 中的状态
前端
dae bal10 小时前
关于RSA和AES加密
前端·vue.js