<template>
  <div :style="maskContainer"
       id="vue-picture-viewer">
    <!-- 头部 -->
    <flexbox class="perview-header">
      <div class="left">{{imgIndex + 1}} / {{imgLength}}</div>
      <div class="center">{{bigImgName.slice(0,bigImgName.indexOf('.'))}}</div>
      <img class="close"
           @click="closeViewer"
           src="./img/pre_close.png" />
    </flexbox>
    <!-- 图片容器 -->
    <div class="imgContainer"
         ref="imgContainer"
         :style="imgContainer">
      <img :src="bigImgUrl"
           v-if="bigShowType.isImage"
           ref="bigImg"
           :style="bigImgStyle"
           alt="">
      <flexbox class="file-show"
               v-if="!bigShowType.isImage">
        <div class="file-icon">
          <img :src="bigShowType.icon" />
        </div>
        <div class="file-handle">
          <el-button type="primary"
                     @click.native="fileHandle('download')"
                     plain>下载</el-button>
        </div>
      </flexbox>
      <!-- tips -->
      <transition name="fade">
        <div v-show="showTips"
             class="tips">{{tipsText}}</div>
      </transition>
    </div>
    <div class="fixedHandle">
      <!-- 操作按钮 -->
      <flexbox v-if="bigShowType.isImage"
               class="handleContainer">
        <img @click="enlarge"
             src="./img/pre_max.png" />
        <img @click="reduce"
             src="./img/pre_min.png" />
        <img style="padding: 4.5px;"
             @click="rotate"
             src="./img/pre_rotate.png" />
        <img @click="downloadImg(bigImgUrl, bigImgName)"
             src="./img/pre_down.png" />
      </flexbox>
      <!-- 缩略图容器 -->
      <div class="thumbnailContainer"
           v-if="imgLength > 1">
        <ul>
          <li ref="thumbnailItem"
              v-for="(item, index) in this.imgData"
              @click="switchImgUrl(index, $event)"
              :key="index">
            <img :src="item.url"
                 v-if="isShowImage(item.url)"
                 alt="">
            <img :src="getFileTypeIconWithSuffix(item.url)"
                 v-if="!isShowImage(item.url)"
                 alt="">
          </li>
        </ul>
      </div>
    </div>
    <!-- 左边箭头 -->
    <div class="leftArrowCon"
         @click="handlePrev"
         @mouseenter="enterLeft"
         @mouseout="outLeft">
      <img class="leftArrow"
           v-show="leftArrowShow"
           @click="enlarge"
           src="./img/pre_left.png" />
    </div>
    <!-- 右边箭头 -->
    <div class="rightArrowCon"
         @click="handleNext"
         @mouseenter="enterRight"
         @mouseout="outRight">
      <img class="rightArrow"
           v-show="rightArrowShow"
           src="./img/pre_right.png" />
    </div>
  </div>
</template>

<script>
var env = require('zrender/lib/core/env')
import { getMaxIndex, downloadImage } from '@/utils'

export default {
  name: 'vue-picture-viewer',
  props: {
    imgData: {
      type: Array,
      default: () => {
        return []
      }
    },
    background: {
      type: String,
      default: 'rgba(0,0,0,0.4)'
    },
    // 选择的索引
    selectIndex: {
      type: Number,
      default: -1
    }
  },
  data() {
    return {
      // 默认不显示左右切换箭头
      leftArrowShow: false,
      rightArrowShow: false,
      // 图片容器数据
      rotateDeg: 0,
      bigImgUrl: '',
      bigShowType: { isImage: true, icon: '' }, //不是图片的时候 展示 icon
      bigImgName: '',
      imgLength: 0,
      imgIndex: 0,
      showTips: false,
      tipsText: '',
      bigImgConWidth: '',
      bigImgConHeight: '',
      maskContainer: {
        width: '100%',
        height: '100%',
        background: this.background,
        position: 'fixed',
        top: 0,
        left: 0,
        right: 0,
        bottom: 0
      },
      imgContainer: {
        width: 'auto',
        height: 'auto',
        position: 'absolute',
        top: '50%',
        left: '50%',
        'z-index': 100,
        transform: 'translate(-50%, -50%)'
      },
      bigImgStyle: {
        display: 'block',
        width: '80px',
        height: '80px',
        position: 'absolute',
        top: 50 + '%',
        left: 50 + '%',
        marginLeft: '',
        marginTop: '',
        userSelect: 'none'
      }
    }
  },
  mounted() {
    document
      .getElementById('vue-picture-viewer')
      .addEventListener('click', e => {
        e.stopPropagation()
      })

    this.imgLength = this.imgData.length
    this.imgIndex = this.selectIndex
    this.$nextTick(() => {
      this.bigImgUrl = this.imgData[this.imgIndex].url
      this.getShowTypeInfo(this.bigImgUrl)
      this.bigImgName = this.imgData[this.imgIndex].name
      if (this.imgLength > 1) {
        // 大于1的时候才会展示缩略图
        var item = this.$refs.thumbnailItem
        item[this.imgIndex].className = 'borderActive'
      }
    })
    var self = this
    this.$refs.bigImg.onload = () => {
      self.init()
    }

    this.maskContainer['z-index'] = getMaxIndex()
  },
  methods: {
    // init
    init() {
      let screenW =
        document.documentElement.offsetWidth || document.body.offsetWidth
      let screenH =
        document.documentElement.scrollHeight || document.body.scrollHeight
      this.$nextTick(function() {
        const ratio = [0.1, 0.2, 0.3, 0.4, 0.5, 0.7, 0.8, 0.9]
        for (let item of ratio) {
          if (
            this.$refs.bigImg.naturalWidth * item < screenW &&
            this.$refs.bigImg.naturalHeight * item < screenH - 200
          ) {
            this.bigImgConWidth = this.$refs.bigImg.naturalWidth * item
            this.bigImgConHeight = this.$refs.bigImg.naturalHeight * item
            this.imgContainer.width = this.bigImgConWidth + 'px'
            this.imgContainer.height = this.bigImgConHeight + 'px'
            this.bigImgStyle.width = this.bigImgConWidth + 'px'
            this.bigImgStyle.height = this.bigImgConHeight + 'px'
            this.bigImgStyle.marginLeft = -(this.bigImgConWidth / 2) + 'px'
            this.bigImgStyle.marginTop = -(this.bigImgConHeight / 2) + 'px'
          }
        }
      })
    },
    // rotate init
    rotateInit() {
      let screenW =
        document.documentElement.offsetWidth || document.body.offsetWidth
      let screenH =
        document.documentElement.scrollHeight || document.body.scrollHeight
      const ratio = [0.1, 0.2, 0.3, 0.4, 0.5, 0.7, 0.8, 0.9]
      for (let item of ratio) {
        if (this.$refs.bigImg.naturalWidth * item < screenH - 160) {
          this.bigImgConWidth = this.$refs.bigImg.naturalWidth * item
          this.bigImgConHeight = this.$refs.bigImg.naturalHeight * item
          this.imgContainer.width = this.bigImgConWidth + 'px'
          this.imgContainer.height = this.bigImgConHeight + 'px'
          this.bigImgStyle.width = this.bigImgConWidth + 'px'
          this.bigImgStyle.height = this.bigImgConHeight + 'px'
          this.bigImgStyle.marginLeft = -(this.bigImgConWidth / 2) + 'px'
          this.bigImgStyle.marginTop = -(this.bigImgConHeight / 2) + 'px'
        }
      }
    },
    // 放大
    enlarge() {
      this.$nextTick(function() {
        let screenW =
          document.documentElement.offsetWidth || document.body.offsetWidth
        let screenH =
          document.documentElement.scrollHeight || document.body.scrollHeight
        if (
          (this.$refs.bigImg.offsetWidth >= this.$refs.bigImg.offsetHeight &&
            this.$refs.bigImg.offsetHeight * 2 < screenH * 2) ||
          (this.$refs.bigImg.offsetHeight >= this.$refs.bigImg.offsetWidth &&
            this.$refs.bigImg.offsetWidth * 2 < screenW * 2)
        ) {
          this.$refs.bigImg.style.width =
            this.$refs.bigImg.offsetWidth * 1.3 + 'px'
          this.$refs.bigImg.style.height =
            this.$refs.bigImg.offsetHeight * 1.3 + 'px'
          this.$refs.bigImg.style.left = '50%'
          this.$refs.bigImg.style.top = '50%'
          this.bigImgStyle.marginLeft =
            -this.$refs.bigImg.offsetWidth / 2 + 'px'
          this.bigImgStyle.marginTop =
            -this.$refs.bigImg.offsetHeight / 2 + 'px'
        }
      })
    },
    // 缩小
    reduce() {
      if (this.$refs.bigImg.offsetWidth > 80) {
        /** 
           * clientWidth = width + padding
             offsetWidth = width + padding + border  */
        this.$refs.bigImg.style.width =
          this.$refs.bigImg.offsetWidth * 0.7 + 'px'
        this.$refs.bigImg.style.height =
          this.$refs.bigImg.offsetHeight * 0.7 + 'px'
        this.$refs.bigImg.style.left = '50%'
        this.$refs.bigImg.style.top = '50%'
        this.bigImgStyle.marginLeft = -this.$refs.bigImg.offsetWidth / 2 + 'px'
        this.bigImgStyle.marginTop = -this.$refs.bigImg.offsetHeight / 2 + 'px'
      }
    },
    // 旋转
    rotate() {
      if (this.rotateDeg === 0) {
        this.$refs.bigImg.style.transform = 'rotate(90deg)'
        this.rotateInit()
        this.rotateDeg++
      } else if (this.rotateDeg === 1) {
        this.$refs.bigImg.style.transform = 'rotate(180deg)'
        this.init()
        this.rotateDeg++
      } else if (this.rotateDeg === 2) {
        this.$refs.bigImg.style.transform = 'rotate(270deg)'
        this.rotateInit()
        this.rotateDeg++
      } else if (this.rotateDeg === 3) {
        this.$refs.bigImg.style.transform = 'rotate(360deg)'
        this.init()
        this.rotateDeg = 0
      }
    },
    // 点击缩略图切换图片
    switchImgUrl(num, e) {
      var item = this.$refs.thumbnailItem
      item.forEach(function(i) {
        i.className = ''
      })
      this.imgIndex = num
      this.bigImgUrl = this.imgData[num].url
      this.getShowTypeInfo(this.bigImgUrl)
      this.bigImgName = this.imgData[num].name
      e.currentTarget.className = 'borderActive'
      if (this.bigShowType.isImage) {
        this.init()
      }
    },
    // 切换到上一张
    handlePrev() {
      if (this.imgIndex <= 0) {
        this.tips('已经是第一张了!')
        this.imgIndex = 0
      } else {
        if (this.$refs.bigImg) {
          this.$refs.bigImg.style.transform = 'rotate(0deg)'
          this.rotateDeg = 0
        }

        this.imgIndex--
        this.bigImgUrl = this.imgData[this.imgIndex].url
        this.getShowTypeInfo(this.bigImgUrl)
        this.bigImgName = this.imgData[this.imgIndex].name
        var item = this.$refs.thumbnailItem
        item.forEach(function(i) {
          i.className = ''
        })
        item[this.imgIndex].className = 'borderActive'
        if (this.bigShowType.isImage) {
          this.init()
        }
      }
    },
    // 切换到下一张
    handleNext() {
      if (this.imgIndex + 1 >= this.imgData.length) {
        this.tips('已经是最后一张了!')
      } else {
        if (this.$refs.bigImg) {
          this.$refs.bigImg.style.transform = 'rotate(0deg)'
          this.rotateDeg = 0
        }

        this.imgIndex++
        this.bigImgUrl = this.imgData[this.imgIndex].url
        this.getShowTypeInfo(this.bigImgUrl)
        this.bigImgName = this.imgData[this.imgIndex].name

        var item = this.$refs.thumbnailItem
        item.forEach(function(i) {
          i.className = ''
        })
        item[this.imgIndex].className = 'borderActive'
        if (this.bigShowType.isImage) {
          this.init()
        }
      }
    },
    // 提示框
    tips(msg) {
      this.showTips = true
      this.tipsText = msg
      let _this = this
      setTimeout(function() {
        _this.showTips = false
      }, 10000)
    },
    // 下载图片
    downloadImg(data, filename) {
      downloadImage(data, filename)
    },
    // 鼠标左移
    enterLeft() {
      this.leftArrowShow = true
    },
    outLeft() {
      this.leftArrowShow = false
    },
    // 鼠标右移
    enterRight() {
      this.rightArrowShow = true
    },
    outRight() {
      this.rightArrowShow = false
    },
    // 关闭查看器
    closeViewer() {
      this.$emit('close-viewer')
    },
    /** 附件逻辑 */
    fileHandle(type) {
      var a = document.createElement('a')
      a.href = this.bigImgUrl
      a.download = this.bigImgName ? this.bigImgName : '文件'
      a.target = '_black'
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
    },
    getShowTypeInfo(url) {
      let temps = url ? url.split('.') : []
      var ext = ''
      if (temps.length > 0) {
        ext = temps[temps.length - 1]
      } else {
        ext = ''
      }
      var icon = ''
      var isImage = true
      if (this.arrayContain(['jpg', 'png', 'gif', 'jpeg'], ext)) {
        isImage = true
        icon = require('@/assets/img/file_img.png')
      } else if (this.arrayContain(['mp4', 'mp3', 'avi'], ext)) {
        isImage = false
        icon = require('@/assets/img/file_excle.png')
      } else if (this.arrayContain(['xlsx', 'xls', 'XLSX', 'XLS'], ext)) {
        isImage = false
        icon = require('@/assets/img/file_excle.png')
      } else if (this.arrayContain(['doc', 'docx', 'DOC', 'DOCX'], ext)) {
        isImage = false
        icon = require('@/assets/img/file_word.png')
      } else if (this.arrayContain(['rar', 'zip'], ext)) {
        isImage = false
        icon = require('@/assets/img/file_zip.png')
      } else if (ext === 'pdf') {
        isImage = false
        icon = require('@/assets/img/file_pdf.png')
      } else if (ext === 'ppt' || ext === 'pptx') {
        isImage = false
        icon = require('@/assets/img/file_ppt.png')
      } else if (this.arrayContain(['txt', 'text'], ext)) {
        isImage = false
        icon = require('@/assets/img/file_txt.png')
      } else {
        isImage = false
        icon = require('@/assets/img/file_unknown.png')
      }
      this.bigShowType = { isImage: isImage, icon: icon }
    },
    getFileTypeIconWithSuffix(url) {
      let temps = url ? url.split('.') : []
      var ext = ''
      if (temps.length > 0) {
        ext = temps[temps.length - 1]
      } else {
        ext = ''
      }
      if (this.arrayContain(['jpg', 'png', 'gif', 'jpeg'], ext)) {
        return require('@/assets/img/file_img.png')
      } else if (this.arrayContain(['mp4', 'mp3', 'avi'], ext)) {
        return require('@/assets/img/file_excle.png')
      } else if (this.arrayContain(['xlsx', 'xls', 'XLSX', 'XLS'], ext)) {
        return require('@/assets/img/file_excle.png')
      } else if (this.arrayContain(['doc', 'docx', 'DOC', 'DOCX'], ext)) {
        return require('@/assets/img/file_word.png')
      } else if (this.arrayContain(['rar', 'zip'], ext)) {
        return require('@/assets/img/file_zip.png')
      } else if (ext === 'pdf') {
        return require('@/assets/img/file_pdf.png')
      } else if (ext === 'ppt' || ext === 'pptx') {
        return require('@/assets/img/file_ppt.png')
      } else if (this.arrayContain(['txt', 'text'], ext)) {
        return require('@/assets/img/file_txt.png')
      }
      return require('@/assets/img/file_unknown.png')
    },
    isShowImage(url) {
      let temps = url ? url.split('.') : []
      var ext = ''
      if (temps.length > 0) {
        ext = temps[temps.length - 1]
      } else {
        ext = ''
      }
      if (this.arrayContain(['jpg', 'png', 'gif', 'jpeg'], ext)) {
        return true
      }
      return false
    },
    arrayContain(array, string) {
      return array.some(item => {
        return item === string
      })
    }
  },
  beforeDestroy() {
    if (document.getElementById('vue-picture-viewer')) {
      document
        .getElementById('vue-picture-viewer')
        .removeEventListener('click', e => {
          e.stopPropagation()
        })
    }
  }
}
</script>

<style lang="scss" scoped>
.perview-header {
  width: 100%;
  height: 40px;
  background: rgba(0, 0, 0, 0.6);
  color: rgba(255, 255, 255, 0.8);
  line-height: 40px;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 101;
  padding: 10px;
  .left {
    flex-shrink: 0;
    font-size: 14px;
  }
  .center {
    text-align: center;
    flex: 1;
    padding: 0 20px;
  }
  .close {
    display: block;
    padding: 8px;
    width: 40px;
    height: 40px;
    cursor: pointer;
  }
}

.leftArrowCon {
  width: 30%;
  height: calc(100% - 40px);
  background: transparent;
  position: absolute;
  top: 40px;
  left: 0;
  z-index: 98;
  cursor: pointer;
}
.rightArrowCon {
  width: 30%;
  height: calc(100% - 40px);
  background: transparent;
  position: absolute;
  top: 40px;
  right: 0;
  z-index: 99;
  cursor: pointer;
}
.leftArrow {
  position: absolute;
  top: 50%;
  left: 30px;
  margin-top: -60px;
  transition: all 0.5s;
  width: 50px;
  height: 50px;
  pointer-events: none;
}
.rightArrow {
  position: absolute;
  top: 50%;
  right: 30px;
  margin-top: -60px;
  width: 50px;
  height: 50px;
  transition: all 0.5s;
  pointer-events: none;
}
.imgContainer .tips {
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  text-align: center;
  line-height: 40px;
  position: absolute;
  left: 50%;
  top: 50%;
  min-width: 150px;
  margin-left: -60px;
  margin-top: -20px;
  border-radius: 6px;
  padding: 4px 4px;
  font-size: 14px;
}
.fixedHandle {
  width: 800px;
  height: 140px;
  position: fixed;
  left: 50%;
  bottom: 0;
  margin-left: -400px;
  overflow: hidden;
  z-index: 100;
}
.handleContainer {
  width: 210px;
  height: 40px;
  background: rgba(0, 0, 0, 0.6);
  line-height: 40px;
  border-radius: 20px;
  position: absolute;
  left: 50%;
  bottom: 100px;
  padding: 0 14px;
  margin-left: -100px;

  img {
    display: block;
    width: 40px;
    height: 40px;
    padding: 8px;
    margin: 0 2px;
    cursor: pointer;
  }
}
.handleItem {
  width: 28px;
  height: 28px;
  color: white;
}
ul {
  padding: 0;
  margin: 0;
}
ul li {
  list-style: none;
  display: inline-block;
  width: 30px;
  height: 30px;
  margin-left: 20px;
  cursor: pointer;
}

.thumbnailContainer {
  max-width: 800px;
  background: rgba(255, 255, 255, 0.7);
  position: absolute;
  left: 50%;
  bottom: 0;
  border-top-left-radius: 5px;
  border-top-right-radius: 5px;
  transform: translate(-50%, 0%);
  overflow-x: auto;
  overflow-y: hidden;
}

.thumbnailContainer ul {
  padding-top: 10px;
  padding-bottom: 10px;
  text-align: center;
  white-space: nowrap;
}
.thumbnailContainer ul li {
  display: inline-block;
  width: 38px;
  height: 38px;
  box-sizing: content-box;
  margin-left: 10px;
  user-select: none;
}
.thumbnailContainer ul li:last-child {
  margin-right: 10px;
}
.thumbnailContainer ul li img {
  display: inline-block;
  width: 38px;
  height: 38px;
  border-radius: 3px;
  box-sizing: content-box;
}
.fade-enter-active,
.fade-leave-active {
  transition: opacity 1s;
}
.fade-enter,
.fade-leave-to {
  opacity: 0;
}

/* 添加border */
.borderActive {
  box-shadow: 0px 4px 7px 0px rgb(241, 140, 112);
}
/* 修改原生的滚动条 */
::-webkit-scrollbar {
  /* 血槽宽度 */
  width: 8px;
  height: 8px;
}
::-webkit-scrollbar-thumb {
  /* 拖动条 */
  background: rgba(0, 0, 0, 0.3);
  border-radius: 6px;
}
::-webkit-scrollbar-track {
  /* 背景槽 */
  background: #ddd;
  border-radius: 6px;
}
/** 文件展示*/
.file-show {
  position: absolute;
  top: 60%;
  left: 50%;
  width: 450px;
  height: 260px;
  margin-top: -150px;
  margin-left: -225px;
  background-color: white;
  border-radius: 3px;
  padding: 0 80px;
  .file-icon {
    flex: 1;
    img {
      display: block;
      width: 100px;
    }
  }

  .file-handle {
    button {
      display: block;
      width: 120px;
      margin-left: 0;
      margin-right: 0;
      height: 34px;
    }
    button:first-child {
      margin-bottom: 20px;
    }
  }
}
</style>
