设置pdf的放大缩小

<template>
  <div class="view">
    <!-- <template v-for="item in pageNum" :key="item"> -->
    <!-- :id="`pdf-canvas-${item}`" -->
    <canvas
      id="pdf-canvas"
      class="pdf-page"
      @touchstart="touchstart"
      @touchmove="touchmove"
      @touchend="touchend($event, 1)"
    />
    <!-- @touchend="touchend($event, item)" -->
    <!-- </template> -->
    <div class="footer">
      <Button
        size="mini"
        color="#006BE1"
        type="primary"
        @click="changeCurrentPage('previousPage')"
      >
        上一页
      </Button>
      <div class="pageNum">{{ currentPage }}/{{ pageNum }}</div>
      <Button
        size="mini"
        color="#006BE1"
        type="primary"
        @click="changeCurrentPage('nextPage')"
      >
        下一页
      </Button>
    </div>
  </div>
  <!-- <div class="footer">
    <Button color="#006BE1" type="primary" @click="downLoadPDF" class="btn">
      下载文件
    </Button>
  </div> -->
</template>

<script setup lang="ts">
import { reactive, toRefs, nextTick, watchEffect, defineProps } from "vue";
//@ts-ignore
import * as pdfjs from "pdfjs-dist";
//@ts-ignore
import pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";
import { Toast, Button } from "vant";
// import { downloadFile } from "@/utils";
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
const props = defineProps({
  url: { type: String, default: "" }, // pdf文件路径
});

const emit = defineEmits(["onRendered"]);
const state = reactive<any>({
  currentPage: 1,
  pageNum: 0,
  pdfCtx: null,

  touchDistance: 0,
  previousPinchScale: 1,
  startTime: 0,
  startX: null,
  startY: null,
  moveX: null,
  moveY: null,
  eLen: 0,

  width: 0,
  height: 0,
});

const changeCurrentPage = (type: "nextPage" | "previousPage") => {
  if (type === "nextPage") {
    if (state.currentPage === state.pageNum) {
      return;
    } else {
      state.currentPage++;
    }
  } else {
    if (state.currentPage === 1) {
      return;
    } else {
      state.currentPage--;
    }
  }
  renderPdf(state.currentPage, 1);
};

const resolvePdf = (url: string) => {
  const loadingTask = pdfjs.getDocument(url);
  loadingTask.promise.then((pdf: any) => {
    state.pdfCtx = pdf;
    state.pageNum = pdf.numPages;
    nextTick(() => {
      renderPdf(1, 1);
    });
  });
};

const renderPdf = (num: number, scale: number) => {
  state.pdfCtx.getPage(num).then((page: any) => {
    // const canvas: any = document.getElementById(`pdf-canvas-${num}`);
    const canvas: any = document.getElementById(`pdf-canvas`);
    const ctx = canvas.getContext("2d");
    // test
    let dpr = window.devicePixelRatio || 1;
    let bsr =
      ctx.webkitBackingStorePixelRatio ||
      ctx.mozBackingStorePixelRatio ||
      ctx.msBackingStorePixelRatio ||
      ctx.oBackingStorePixelRatio ||
      ctx.backingStorePixelRatio ||
      1;
    let ratio = dpr / bsr;
    let scalNum = scale || 1;
    let viewport = page.getViewport({
      scale: screen.availWidth / page.getViewport({ scale: 1 }).width,
    });

    canvas.width = viewport.width * ratio * scalNum;
    canvas.height = viewport.height * ratio * scalNum;

    state.width = viewport.width * ratio * scalNum;
    state.height = viewport.height * ratio * scalNum;

    canvas.style.width = viewport.width * scalNum + "px";
    canvas.style.height = viewport.height * scalNum + "px";
    let renderContext = {
      //这里transform比较关键 保证根据手势缩放后的清晰度和等比例
      transform: [ratio * scalNum, 0, 0, ratio * scalNum, 0, 0],
      canvasContext: ctx,
      viewport: viewport,
    };
    page.render(renderContext).promise.then(() => {
      // 渲染水印
      renderWatermark(num);
    });

    /**开始 */
    // const viewport = page.getViewport({ scale: 1 });

    // // 画布大小,默认值是width:300px,height:150px
    // canvas.height = viewport.height;
    // canvas.width = viewport.width;
    // // 画布的dom大小, 设置移动端,宽度设置铺满整个屏幕
    // const clientWidth = document.body.clientWidth;
    // canvas.style.width = clientWidth + "px";
    // // 根据pdf每页的宽高比例设置canvas的高度
    // canvas.style.height =
    //   clientWidth * (viewport.height / viewport.width) + "px";
    // page.render({
    //   canvasContext: ctx,
    //   viewport,
    // });
    /**结束 */
    /**渲染一张即可 */
    // if (num < state.pageNum) {
    //   renderPdf(num + 1, 1);
    // } else {
    emit("onRendered");
    Toast.clear(); // 取消加载loading
    // }
  });
};

const _getDistance = (xLen: any, yLen: any) => {
  return Math.sqrt(xLen * xLen + yLen * yLen);
};
const touchstart = (e: any) => {
  state.startTime = _getTime();
  console.log("e.touches", e.touches);

  state.startX = e.touches[0].pageX;
  state.startY = e.touches[0].pageY;
  if (e.touches.length > 1) {
    let point1 = e.touches[0];
    let point2 = e.touches[1];
    let xLen = Math.abs(point2.pageX - point1.pageX);
    let yLen = Math.abs(point2.pageY - point1.pageY);
    state.touchDistance = _getDistance(xLen, yLen);
  }
};
const touchmove = (e: any) => {
  state.moveX = e.touches[0].pageX;
  state.moveY = e.touches[0].pageY;
  state.eLen = e.touches.length;
  if (e.touches.length > 1) {
    let xLen = Math.abs(e.touches[0].pageX - e.touches[1].pageX);
    let yLen = Math.abs(e.touches[0].pageY - e.touches[1].pageY);
    let touchDistance = _getDistance(xLen, yLen);
    if (state.touchDistance) {
      let pinchScale = touchDistance / state.touchDistance;
      state.previousPinchScale = pinchScale > 1 ? pinchScale : 1;
    }
  }
};
const _getTime = () => {
  return new Date().getTime();
};
const touchend = (e: any, num: number) => {
  let timestamp = _getTime();
  if (
    (state.moveX !== null && Math.abs(state.moveX - state.startX) > 10) ||
    (state.moveY !== null && Math.abs(state.moveY - state.startY) > 10)
  ) {
    if (timestamp - state.startTime < 500 && state.eLen >= 2) {
      //手指移动的位移要大于10像素并且手指和屏幕的接触时间要短于500毫秒
      renderPdf(num, state.previousPinchScale);
      state.eLen = 0;
    }
  }
};

const initWatermark = () => {
  let canvas = document.createElement("canvas");
  canvas.width = 300;
  canvas.height = 200;

  const ctx = canvas.getContext("2d");
  if (ctx) {
    ctx.rotate((-18 * Math.PI) / 180);
    ctx.scale(2, 2);
    ctx.font = `18px Vedana`;
    ctx.fillStyle = "rgba(200, 200, 200, .3)";
    ctx.textAlign = "left";
    ctx.textBaseline = "middle";
    ctx.fillText("雷神大哥大", 50, 50);
  }

  return canvas;
};

const renderWatermark = (index: number) => {
  // let canvas = document.querySelector(`#pdf-canvas-${index}`);
  let canvas = document.querySelector(`#pdf-canvas`);
  if (canvas) {
    //@ts-ignore
    let ctx = canvas.getContext("2d");

    // 平铺水印
    let pattern = ctx.createPattern(initWatermark(), "repeat");
    ctx.rect(0, 0, state.width, state.height);
    ctx.fillStyle = pattern;
    ctx.fill();
  }
};

watchEffect(() => {
  if (props.url) {
    // 展示加载loading
    Toast.loading({
      message: "加载中...",
      overlay: true,
      forbidClick: true,
      duration: 0,
    });

    resolvePdf(props.url);
  }
});

const { pageNum, pdfCtx, currentPage } = toRefs(state);
</script>
<style scoped>
/* .view {
  padding-bottom: 1.5rem;
}
.footer {
  position: fixed;
  bottom: 0;
  width: 100%;
  padding: 0.16rem 0.4rem 0.6rem;
  display: flex;
  align-items: center;
  height: 1.5rem;
  box-shadow: 0px -1px 0px rgba(49, 69, 106, 0.164254);
  background-color: #fff;
}
.btn {
  width: 100%;
}
.van-button {
  border-radius: 0.1rem;
} */
.footer {
  position: fixed;
  bottom: 0;
  width: 100%;
  padding: 0.16rem 0.4rem 0.8rem;
  display: flex;
  align-items: center;
  height: 1.4rem;
  background-color: #fff;
  justify-content: center;
}
.pageNum {
  margin: 0 12px;
}
</style>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用pdfjs-dist库来预览和操作PDF文件。要实现放大缩小功能,你可以使用scale属性来调整PDF的缩放级别。下面是一个示例代码: ```javascript import PDFJS from 'pdfjs-dist'; // 加载PDF文件 PDFJS.getDocument('path/to/pdf/file.pdf').promise.then(function(pdf) { // 获取第一页 pdf.getPage(1).then(function(page) { var scale = 1.5; // 设置缩放级别 // 获取页面的宽度和高度 var viewport = page.getViewport({ scale: scale }); // 创建一个canvas元素来显示PDF内容 var canvas = document.getElementById('pdf-canvas'); var context = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; // 渲染PDF内容到canvas上 var renderContext = { canvasContext: context, viewport: viewport }; page.render(renderContext); }); }); // 放大按钮点击事件 document.getElementById('zoom-in').addEventListener('click', function() { scale += 0.1; // 增加缩放级别 renderPage(scale); }); // 缩小按钮点击事件 document.getElementById('zoom-out').addEventListener('click', function() { scale -= 0.1; // 减小缩放级别 renderPage(scale); }); // 渲染页面 function renderPage(scale) { pdf.getPage(1).then(function(page) { var viewport = page.getViewport({ scale: scale }); canvas.height = viewport.height; canvas.width = viewport.width; var renderContext = { canvasContext: context, viewport: viewport }; page.render(renderContext); }); } ``` 在上面的代码中,我们首先加载PDF文件并获取第一页。然后,我们创建一个canvas元素来显示PDF内容,并根据缩放级别调整canvas的大小。最后,我们使用render方法将PDF内容渲染到canvas上。 你可以通过点击放大缩小按钮来增加或减小缩放级别,并重新渲染页面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值