1. 首页
  2. 技术知识

「前端」有空来撸一只图片浏览器?power by vue.js

废话不多说,先看东西

支持1~9宫格


左右可以切换,点击底部的列表也可以切换。


点击中间收起,顶部可以旋转,查看原图等功能。


这个其实就是我们摸鱼模块里的图片预览组件。


接下来,我们就是要写这么个玩意。


环境

这个是nuxt.js项目+element-ui


element-ui 主要是用了几个图标,也没使用啥。


所以还是靠纯手工撸码吧


分析

这个控件,有三个状态

  • 普通的预览状态
  • 详情浏览状态
  • 原图查看状态

第一和第二个状态互斥,第二和第三个状态可以共存


所以我们在div结构上可以分三个。


通过状态来控制显示和隐藏即可。


再细分:


普通预览状态

这个没有难度,就是图片渲染,然后根据不同的图片数量控制大小样式之类的。而类名可以动态根据图片的数量生成。


共同样式的进行抽取即可。


详情页面

  • 收起功能,其实就是改变状态,控制显示即可。
  • 查看大图,就是显示当前的图片的原图即可,不改变大小。写个样式,显示一下就可以了。
  • 左右旋转,旋转我们通过修改translate里的rotate即可,再通过计算一下偏移量,重新修正大小,并且动态改变容器的大小。
  • 左右切换,本质上就是移动下标,然后更新数据源。这里要注意的是界限和重置旋转后的状态。

以上分析就可以完成这个功能了。在摸鱼君的课程里不会详细讲此课程,这只是作为了个组件模块讲解,跟表情控制面板一样。


在摸鱼君课程中,直接使用该控件。


布局代码

先看看整体的布局代码

<div id=”image-viewer”>    <div class=”preview clear-fix” v-show=”isPreview”>      <!–遍历内容显示–>      <div :class=”‘image-item image-item-‘+targetImages.length” v-for=”(item,index) in targetImages” :key=”index”>        <img :src=”item” alt=”image” @click=”toDetailPage(index)”>      </div>    </div>    <div class=”detail” v-show=”!isPreview”>      <!–顶部的控制栏–>      <div class=”iv-viewer-action-bar”>        <span class=”el-icon-zoom-out” @click=”toPreviewPage”>收起</span>        <span class=”el-icon-search” @click=”showOriginalIv”>查看大图</span>        <span class=”el-icon-refresh-left” @click=”doRotate(-1)”>向左旋转</span>        <span class=”el-icon-refresh-right” @click=”doRotate(1)”>向右旋转</span>      </div>      <div class=”iv-detail-part” id=”iv-detail-part”>        <img id=”detail-iv” :src=”detailSrc” @click=”toPreviewPage”>        <div id=”iv-left-arrow” @click=”leftMove”></div>        <div id=”iv-right-arrow” @click=”rightMove”></div>      </div>      <div class=”iv-list-part”>              </div>    </div>    <div class=”original-view” v-if=”isOriginalIvShow”>      <div class=”image-container”>                <span class=”image-close” @click=”closeOriginalIv”>X</span>      </div>    </div>  </div>
这里是三部分的内容了

  • preview 预览部分
  • detail 详情部分
  • original 原图显示部分

data() {      return {        image1: [‘/images/1.png’],        images2: [‘/images/1.png’, ‘/images/2.png’],        images3: [‘/images/1.png’, ‘/images/2.png’, ‘/images/3.jpeg’],        images4: [‘/images/1.png’, ‘/images/2.png’, ‘/images/3.jpeg’, ‘/images/4.jpeg’],        images5: [‘/images/1.png’, ‘/images/2.png’, ‘/images/3.jpeg’, ‘/images/4.jpeg’, ‘/images/5.jpeg’],        images6: [‘/images/1.png’, ‘/images/2.png’, ‘/images/3.jpeg’, ‘/images/4.jpeg’, ‘/images/5.jpeg’, ‘/images/6.jpeg’],        images7: [‘/images/1.png’, ‘/images/2.png’, ‘/images/3.jpeg’, ‘/images/4.jpeg’, ‘/images/5.jpeg’, ‘/images/6.jpeg’, ‘/images/7.jpeg’],        images8: [‘/images/1.png’, ‘/images/2.png’, ‘/images/3.jpeg’, ‘/images/4.jpeg’, ‘/images/5.jpeg’, ‘/images/6.jpeg’, ‘/images/7.jpeg’, ‘/images/8.jpeg’],        images9: [‘/images/1.png’, ‘/images/2.png’, ‘/images/3.jpeg’, ‘/images/4.jpeg’, ‘/images/5.jpeg’, ‘/images/6.jpeg’, ‘/images/7.jpeg’, ‘/images/8.jpeg’, ‘/images/9.png’],        targetImages: [],        detailSrc: ”,        isPreview: true,        currentActiveIndex: 0,        isOriginalIvShow: false,        currentDeg: 0,        originalWidth: 0,        originalHeight: 0      }    },
从预览到详情页面

toDetailPage(index) {    this.currentActiveIndex = index;    this.isPreview = false;    this.updateArrowPartVisibility();    this.updateDetailImage();},
旋转

doRotate(direction) {  let detailIv = document.getElementById(‘detail-iv’);  if (this.currentDeg === 0) {    this.originalWidth = detailIv.width;    this.originalHeight = detailIv.height;    console.log(“this.originalWidth ==> ” + this.originalWidth);    console.log(“this.originalHeight ==> ” + this.originalHeight);  }  if (direction > 0) {    //向右转    this.currentDeg += 90;    if (this.currentDeg >= 360) {      this.currentDeg = 0;    }  } else {    //向左转    this.currentDeg -= 90;    if (this.currentDeg <= -360) {      this.currentDeg = 0;    }  }  //重新计算高度  let detailIvContainer = document.getElementById(‘iv-detail-part’);  //获取当前IV的宽高,然后宽高对调,调整容器  let ivWidth = detailIv.width;  let ivHeight = detailIv.height;  let ctWidth = detailIvContainer.offsetWidth;  if (this.currentDeg === 90 || this.currentDeg === -270) {    //横向    //如果高度大于容器的宽度,那么需要对图片进行缩放,并且计算宽高    if (ivHeight > ctWidth) {      detailIv.style.height = ctWidth + ‘px’;      ivHeight = detailIv.height;      ivWidth = detailIv.width;    }    let targetTranslate = (ivWidth – ivHeight) / 2 + 10;    detailIv.style.transform = ‘rotate(‘ + this.currentDeg + ‘deg) translate(‘ + targetTranslate + ‘px, 0)’;    detailIvContainer.style.height = ivWidth + 10 + ‘px’;  } else if (this.currentDeg === 180) {    //宽高复原    detailIv.style.height = this.originalHeight + ‘px’;    ivHeight = detailIv.height;    ivWidth = detailIv.width;    //纵向,相反    detailIv.style.transform = ‘rotate(‘ + this.currentDeg + ‘deg)’;    detailIvContainer.style.height = ivHeight + 10 + ‘px’;  } else if (this.currentDeg === 270 || this.currentDeg === -90) {    //横向    if (ivHeight > ctWidth) {      detailIv.style.height = ctWidth + ‘px’;      ivHeight = detailIv.height;      ivWidth = detailIv.width;    }    detailIvContainer.style.height = ivWidth + 10 + ‘px’;    let targetTranslate = (ivHeight – ivWidth) / 2 – 10;    console.log(“targetTranslate  ==> ” + targetTranslate);    detailIv.style.transform = ‘rotate(‘ + this.currentDeg + ‘deg) translate(‘ + targetTranslate + ‘px, 0)’;  } else {    detailIv.style.height = this.originalHeight + ‘px’;    ivHeight = detailIv.height;    ivWidth = detailIv.width;    detailIv.style.transform = ‘rotate(‘ + this.currentDeg + ‘deg)’;    detailIvContainer.style.height = ivHeight + 10 + ‘px’;  }},
控制左右切换的边界

updateArrowPartVisibility() {  //如果是第0个,左边不显示  //如果是最后一个,右边不显示  if (this.currentActiveIndex === 0) {    document.getElementById(‘iv-left-arrow’).style.display = ‘none’;  } else {    document.getElementById(‘iv-left-arrow’).style.display = ‘block’;  }  if (this.currentActiveIndex === this.targetImages.length – 1) {    document.getElementById(‘iv-right-arrow’).style.display = ‘none’;  } else {    document.getElementById(‘iv-right-arrow’).style.display = ‘block’;  }},
更新图片的显示

  updateDetailImage() {        this.detailSrc = this.targetImages[this.currentActiveIndex];        let detailIv = document.getElementById(‘detail-iv’);        let detailIvContainer = document.getElementById(‘iv-detail-part’);        detailIvContainer.style.height = ”;        detailIv.style.transform = ”;        detailIv.style.height = ”;        this.currentDeg = 0;     }
显示原图

      showOriginalIv() {        this.isOriginalIvShow = true;      },
关闭原图

      closeOriginalIv() {        this.isOriginalIvShow = false;      },
左右切换

leftMove() {        this.currentActiveIndex–;        if (this.currentActiveIndex < 0) {          this.currentActiveIndex = 0;        }        this.updateArrowPartVisibility();        this.updateDetailImage();      },      rightMove() {        this.currentActiveIndex++;        if (this.currentActiveIndex > this.targetImages.length – 1) {          this.currentActiveIndex = this.targetImages.length – 1;        }        this.updateArrowPartVisibility();        this.updateDetailImage();      },
样式代码就不贴了,自己写吧。


做这种东西,看完分析应该就可以自己写出来了。不能完全了白嫖,嫖思想就行了,哈哈。


相关推荐

本文和表情组件一样,只是一个模块,作为摸鱼君的模块功能,直接使用。


相关的内容

JavaWeb微服务项目-摸鱼君

原创文章,作者:starterknow,如若转载,请注明出处:https://www.starterknow.com/126797.html

联系我们