123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- <template>
- <div class="vue-pdf" @scroll="onScroll" ref="myDiv">
- <vue-pdf-embed :source="testpdf1" ref="vuePdfRef" :style="scaleFun" class="vue-pdf-cs" @loaded="onPdfLoaded" :renderPageNumber="true" />
- </div>
- <div class="page-tool">
- <div class="page-tool-item" @click="lastPage">上一页</div>
- <div class="page-tool-item" @click="nextPage">下一页</div>
- <div class="page-tool-item" @click="pageZoomOut">放大</div>
- <div class="page-tool-item" @click="pageZoomIn">缩小</div>
- <div class="page-tool-item" @click="PDFPrint">打印</div>
- <div class="page-tool-item" @click="PDFDownload">下载</div>
- </div>
- <div class="page-tool2">
- <div class="page-tool-item" @click="lastPage">{{scaleData.pageNum}}/{{scaleData.numPages}}</div>
- </div>
- </template>
- <script setup lang="ts">
- import VuePdfEmbed from 'vue-pdf-embed';
- import testpdf1 from '../../assets/testpdf.pdf';
- import {computed, onMounted, reactive, ref} from "vue";
- // 实现pdf缩放
- const scaleFun = computed(() => {
- return {
- transform: `scale(${scaleData.scale})`,
- transition: 'all 0.3s',
- transformOrigin: 'top'
- };
- });
- const scaleData = reactive({
- scale: 0.6, // 缩放比例
- scaleNum: 0.1, // 滚轮缩放比例
- scaleMax: 100, // 最大缩放比例
- scaleMin: 0.1, // 最小缩放比例
- scaleBtn: 0.4, // 缩放按钮缩放比例
- pageNum: 1, // 当前页面
- url: 'http://www.fao.fudan.edu.cn/_upload/article/files/f5/53/8b40af524563b9b60049899b2dd3/c9a205b4-4188-4af3-863e-bc4e56872e33.pdf',
- numPages: 0
- });
- const vuePdfRef = ref<InstanceType<typeof VuePdfEmbed> | null>(null);
- const myDiv = ref(null);
- const lastPage = () => {
- if (scaleData.pageNum > 1) {
- scaleData.pageNum--
- scrollToPage()
- }
- };
- const nextPage = () => {
- if (scaleData.pageNum < scaleData.numPages) {
- scaleData.pageNum++
- scrollToPage()
- }
- };
- const pageZoomOut = () => {
- if (scaleData.scale < scaleData.scaleMax) {
- scaleData.scale += scaleData.scaleNum;
- }
- };
- const pageZoomIn = () => {
- if (scaleData.scale > scaleData.scaleMin) {
- scaleData.scale -= scaleData.scaleNum;
- }
- };
- const PDFPrint = () => {
- vuePdfRef.value?.print(300, getPDFFileName(), true)
- };
- const PDFDownload = () => {
- vuePdfRef.value?.download(getPDFFileName())
- };
- const getPDFFileName = () => {
- const last_index= scaleData.url.lastIndexOf('/');
- return scaleData.url.slice(last_index+ 1);
- };
- const onPdfLoaded = (data: { numPages: number }) => {
- scaleData.numPages = data.numPages
- };
- const scrollToPage = () => {
- const pdfContainer = myDiv.value;
- const pageHeight = pdfContainer.scrollHeight / scaleData.numPages;
- const targetScrollPosition = (scaleData.pageNum-1) * pageHeight;
- pdfContainer.scrollTo({
- top: targetScrollPosition,
- behavior: 'smooth'
- });
- };
- const onScroll = () => {
- const pdfContainer = myDiv.value;
- const scrollTop = pdfContainer.scrollTop+100;
- const pageHeight = pdfContainer.scrollHeight / scaleData.numPages;
- const currentPage = Math.floor(scrollTop / pageHeight) + 1;
- scaleData.pageNum = currentPage;
- };
- </script>
- <style scoped>
- .page-tool2 {
- position: absolute;
- bottom: 18%;
- padding-left: 10px;
- padding-right: 10px;
- align-items: center;
- background: rgba(3, 67, 109, 0.075);
- color: rgba(2, 1, 41, 0.507);
- border-radius: 19px;
- z-index: 100;
- cursor: pointer;
- margin-left: 80%;
- margin-right:50px; /* 修改这里 */
- }
- .page-tool {
- position: absolute;
- bottom: 25%;
- padding-left: 15px;
- padding-right: 15px;
- align-items: center;
- background: rgba(3, 67, 109, 0.075);
- color: rgba(2, 1, 41, 0.507);
- border-radius: 19px;
- z-index: 100;
- cursor: pointer;
- margin-left: 80%;
- margin-right:50px; /* 修改这里 */
- }
- .page-tool-item {
- padding: 20px 15px;
- cursor: pointer;
- }
- .vue-pdf{
- margin: 0px auto;
- width: 100%;
- position: relative;
- overflow: auto;
- background: #e3e2e2;
- }
- .vue-pdf-cs{
- width: 100%;
- height: 100%;
- text-align: center;
- display: flex;
- flex-direction: column;
- gap: 20px;
- }
- </style>
|