基於vue-pdf的PDF預覽,縮放、旋轉、拖拽、下一頁

先說一下利用iframe打開pdf效果如下

代碼如下這種感覺更簡單,打印各方面都可以

    <el-dialog
      v-if="showPdf"
      :visible.sync="showPdf"
      width="800px"
      @close="showPdf=false"
      title="PDF預覽"
    >
      <div class="pdf">
        <iframe :src="pdfHref" frameborder="0" style="width: 100%; height: 600px;"> 
        </iframe>
      </div>
    </el-dialog>

下面說一下基於vue-pdf的二次開發

效果圖如下:因爲上一頁下一頁沒有icon,所以用的旋轉的icon

 

1、安裝vue-pdf

npm install --save vue-pdf

2、具體引用使用

<template>
  <div :class="{ dialog:true, active:show}" @mousewheel="mousewheelFn">
    <a v-if="showClose" class="close" @click="closeFn"></a>
    <div
      class="wrap"
      ref="wrap"
    >
      <div
        class="pdfWrap"
        id="pdfWrap"
        :style="{cursor: 'pointer', transform: `rotate(${rotate}deg)`,width: `${scale}%`}"
      >
        <pdf
          v-if="pdfSrc"
          :src="pdfSrc"
          :page="currentPage"
          ref="pdf"
          @num-pages="pageCount=$event"
          @page-loaded="currentPage=$event"
          @loaded="loadPdfHandler"
        ></pdf>
      </div>
      <div class="control">
        <a
          v-for="(item,index) in ['放大(+)','縮小(-)','原圖(1:1)','向左旋轉90°','向右旋轉90°','上一頁','下一頁']"
          :key="index"
          @click="handle(index)"
          :title="item"
        ></a>
      </div>
      <div :class="{toast:true,showToast,animate}">{{toastScale}}</div>
    </div>
  </div>
</template>

<script>
import { bind, unbind, objDrag } from "js/js";
import pdf from "vue-pdf";
export default {
  data() {
    return {
      initPosX: 0,
      initPosY: 0,
      pdfSrc: "",
      currentPage: 0, // pdf文件頁碼
      pageCount: 0, // pdf文件總頁數
      numPages: 1,
      activeIndex: 0,
      iWidth: document.documentElement.clientWidth,
      iHeight: document.documentElement.clientHeight,
      scale: 50,
      rotate: 0,
      scaleAdd: 10,
      rotateAdd: 90,
      showToast: false,
      animate: false,
      toastTimer1: null,
      toastTimer2: null,
      objDrag: null
    };
  },

  computed: {
    toastScale() {
      let { scale } = this;
      return `${scale}%`;
    }
  },

  props: {
    parent: {
      //父組件的this
      type: Object,
      default: null,
      required: true
    },
    show: {
      //是否顯示組件
      type: Boolean,
      default: false
    },
    showName: {
      //控制顯示組件的名稱
      type: String,
      default: ""
    },
    showClose: {
      //是否顯示組件關閉按鈕
      type: Boolean,
      default: true
    },
    dochref: {
      //pdfurl
      type: String,
      default: ""
    }
  },
  components: {
    pdf
  },
  beforeDestroy() {
    unbind(window, "resize", this.initPos);
  },
  mounted() {
    //圖片加上拖拽
    bind(window, "resize", this.initPos);
    this.pdfSrc = this.dochref;
  },
  methods: {
    initPos() {
      let pdfWrap = document.getElementById("pdfWrap");
      this.iWidth = document.documentElement.clientWidth;
      this.iHeight = document.documentElement.clientHeight;
      let width = pdfWrap.clientWidth;
      let height = pdfWrap.clientHeight;
      this.initPosX = this.iWidth / 4;
      this.initPosY = this.iHeight / 8;
      this.scale = 50;
      this.rotate = 0;
      pdfWrap.style.left = this.initPosX + "px";
      pdfWrap.style.top = this.initPosY + "px";
    },
    changePdfPage(val) {
      if (val === 0 && this.currentPage > 1) {
        this.currentPage--;
      }
      if (val === 1 && this.currentPage < this.pageCount) {
        this.currentPage++;
      }
    },
    loadPdfHandler(e) {
      this.currentPage = 1; // 加載的時候先加載第一頁
      this.drag("pdfWrap");
      this.initPos();
    },
    closeFn() {
      let { parent, showName } = this;
      if (parent && showName && parent[showName]) {
        parent[showName] = false;
        this.scale = 50;
        this.rotate = 0;
      }
    },
    showToastFn() {
      this.showToast = true;
      this.animate = false;
      clearTimeout(this.toastTimer1);
      clearTimeout(this.toastTimer2);
      this.toastTimer1 = setTimeout(() => {
        this.animate = true;
        this.toastTimer2 = setTimeout(() => {
          this.showToast = false;
          this.animate = false;
        }, 300);
      }, 300);
    },
    magnify() {
      let { scale } = this;
      scale += this.scaleAdd;
      scale = scale > 1000 ? 1000 : scale;
      this.showToastFn();
      this.scale = scale;
    },
    shrink() {
      let { scale } = this;
      scale -= this.scaleAdd;
      scale = scale < 10 ? 10 : scale;
      this.showToastFn();
      this.scale = scale;
    },
    handle(index) {
      let { scale, rotate } = this;
      switch (index) {
        case 0:
          this.magnify();
          break;
        case 1:
          this.shrink();
          break;
        case 2:
          this.initPos();
          break;
        case 3:
          this.rotate -= this.rotateAdd;
          break;
        case 4:
          this.rotate += this.rotateAdd;
          break;
        case 5:
          this.changePdfPage(0);
          break;
        case 6:
          this.changePdfPage(1);
          break;
      }
    },
    mousewheelFn(ev) {
      let up = true;
      if (ev.wheelDelta) {
        up = ev.wheelDelta > 0 ? true : false;
      } else {
        up = ev.detail < 0 ? true : false;
      }
      if (up) {
        this.magnify();
      } else {
        this.shrink();
      }
    },
    drag(obj) {
      this.objDrag = new objDrag(obj);
    }
  }
};
</script>

<style lang="scss" scoped>
@import "~css/public.scss";
@mixin close() {
  width: 50px;
  height: 50px;
  background: rgba(255, 255, 255, 0.9)
    url("../../images/imgControl/icon_close.png") no-repeat center center;
  background-size: 16px;
  position: absolute;
  right: 0;
  top: 0;
  z-index: 10;
  cursor: pointer;
}

.dialog {
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.6);
  position: fixed;
  left: 0;
  top: 0;
  z-index: 1999;
  display: none;
  &.active {
    display: block;
  }
  > .close {
    @include close;
    right: 30px;
    top: 30px;
  }
  > .wrap {
    width: 100%;
    height: 100%;
    position: relative;
    .pdfWrap {
      position: absolute;
    }
    > .control {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 300px;
      padding: 5px 0;
      height: 30px;
      background-color: rgba(255, 255, 255, 0.9);
      border-radius: 25px;
      position: absolute;
      left: 50%;
      margin-left: -150px;
      bottom: 10px;
      a {
        width: 20px;
        margin: 0 5px;
        height: 20px;
        background: no-repeat center center;
        background-size: 16px;
        &:nth-of-type(1) {
          background-image: url("../../images/imgControl/icon_enlarge_zxzx.png");
        }
        &:nth-of-type(2) {
          background-image: url("../../images/imgControl/icon_narrow_zxzx.png");
        }
        &:nth-of-type(3) {
          background-image: url("../../images/imgControl/icon_ybl_zxzx.png");
        }
        &:nth-of-type(4) {
          background-image: url("../../images/imgControl/icon_turn_zxzx.png");
        }
        &:nth-of-type(5) {
          background-image: url("../../images/imgControl/icon_turn2_zxzx.png");
        }
        &:nth-of-type(6) {
          background-image: url("../../images/imgControl/icon_turn_zxzx.png");
        }
        &:nth-of-type(7) {
          background-image: url("../../images/imgControl/icon_turn2_zxzx.png");
        }
        &:hover {
          background-color: $main;
          &:nth-of-type(1) {
            background-image: url("../../images/imgControl/icon_enlarge2_zxzx.png");
          }
          &:nth-of-type(2) {
            background-image: url("../../images/imgControl/icon_narrow2_zxzx.png");
          }
          &:nth-of-type(3) {
            background-image: url("../../images/imgControl/icon_ybl2_zxzx.png");
          }
          &:nth-of-type(4) {
            background-image: url("../../images/imgControl/icon_turn3_zxzx.png");
          }
          &:nth-of-type(5) {
            background-image: url("../../images/imgControl/icon_turn4_zxzx.png");
          }
          &:nth-of-type(6) {
            background-image: url("../../images/imgControl/icon_turn3_zxzx.png");
          }
          &:nth-of-type(7) {
            background-image: url("../../images/imgControl/icon_turn4_zxzx.png");
          }
        }
      }
    }
    > .toast {
      width: 100px;
      height: 30px;
      line-height: 30px;
      text-align: center;
      background-color: rgba(255, 255, 255, 0.9);
      border-radius: 15px;
      position: absolute;
      top: 30px;
      left: 50%;
      margin-left: -50px;
      z-index: 10;
      transition: opacity 0.3s ease-out;
      opacity: 1;
      display: none;
      &.showToast {
        display: block;
      }
      &.animate {
        opacity: 0;
      }
    }
  }
}
</style>

bind,unbind,objDrag (這三個函數你也可以自己封裝)

//綁定事件,可重複綁定('事件名稱'必須加引號)
function bind(obj, evname, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(evname, fn, false);
        if (evname == 'mousewheel') {
            obj.addEventListener('DOMMouseScroll', fn, false);
        }
    } else {
        obj.attachEvent('on' + evname, function () {
            fn.call(obj);
        });
    }
};

//取消綁定,可重複取消('事件名稱'必須加引號)
function unbind(obj, evname, fn) {
    if (obj.removeEventListener) {
        obj.removeEventListener(evname, fn, false);
        if (evname == 'mousewheel') {
            obj.removeEventListener('DOMMouseScroll', fn, false);
        }
    } else {
        obj.detachEvent('on' + evname, fn);
    }
};

// 拖拽

function objDrag(id) {
    var _this = this;
    this.oDiv = document.getElementById(id);
    this.oDiv.onmousedown = function (event) {
        _this.fnDown(event);
        return false;
    }
    this.positionArray = []
    this.nX = null;
    this.nY = null;
    this.timer = null;
}

objDrag.prototype.fnDown = function (event) {
    var _this = this;
    var evt = event || window.event;
    this.nX = evt.clientX - this.oDiv.offsetLeft;
    this.nY = evt.clientY - this.oDiv.offsetTop;
    document.onmousemove = function (event) {
        _this.fnMove(event);
    }
    this.oDiv.onmouseup = function (event) {
        _this.fnUp(event)
    };
}

objDrag.prototype.fnMove = function (event) {
    var evt = event || window.event;
    var left = evt.clientX - this.nX;
    var top = evt.clientY - this.nY;
    this.oDiv.style.left = left + 'px';
    this.oDiv.style.top = top + 'px';
    this.positionArray.push({
        left: this.oDiv.offsetLeft,
        top: this.oDiv.offsetTop
    });
}

objDrag.prototype.returnWay = function () { // 拖拽軌跡原路返回
    console.log(this.positionArray.length);
    let positionArray = this.positionArray
    this.positionArray = []
    let _this = this
    console.log(positionArray, 'pos')
    var index = positionArray.length - 1;
    this.timer = setInterval(function () {
        if (index < 0) {
            clearInterval(this.timer);
            return;
        }
        if (positionArray.length) {
            console.log(_this.oDiv, '_this.oDiv')
            if (_this.oDiv.style) {
                _this.oDiv.style.left = positionArray[index--].left + "px";
                _this.oDiv.style.top = positionArray[index--].top + "px";
            }
        }
    }, 1);
}

objDrag.prototype.fnUp = function () {
    document.onmousemove = null;
}

使用方式

    <pdfDialog
      v-if="showPdf"
      :parent="this"
      :show="showPdf"
      :showName="'showPdf'"
      :control="true"
      :dochref="pdfHref"
    >
    </pdfDialog>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章