最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue中的ofd/pdf預(yù)覽實(shí)現(xiàn)過(guò)程

 更新時(shí)間:2025年10月25日 09:05:29   作者:Qredsun  
這篇文章主要介紹了vue中的ofd/pdf預(yù)覽實(shí)現(xiàn)過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

背景

實(shí)現(xiàn)預(yù)覽ofd/pdf超鏈接功能

業(yè)務(wù)實(shí)現(xiàn)

1.pdf的預(yù)覽

實(shí)現(xiàn)方式:

1.直接使用 <iframe :src="${url}#navpanes=0&toolbar=0" /> 實(shí)現(xiàn)pdf的預(yù)覽。

  • navpanes=0 隱藏側(cè)邊欄
  • toolbar=0 隱藏頂部工具欄

2.使用pdf.js,代碼先行:

<template>
  <a-tabs
    v-if="props.urls.length > 0"
    :default-active-key="activateTab"
    type="card"
    class="pdf-tabs"
    @change="tabChangeHandler"
  >
    <a-tab-pane v-for="url in props.urls" :key="url" :tab="fileName(url)">
      <div class="pdf-container">
        <canvas
          v-if="url.endsWith('.pdf')"
          class="canvas"
          :ref="(el) => (canvasRefs[url] = el)"
        ></canvas>
        <a-button class="mb-2" type="link" @click="handleDownload(url)">
          {{ fileName(url) }}
        </a-button>
      </div>
    </a-tab-pane>
  </a-tabs>
</template>

<script lang="ts" setup>
import { ref, watch, nextTick } from 'vue'
import * as pdfjsLib from 'pdfjs-dist'
import { debounce } from 'lodash-es'
import { saveAs } from 'file-saver'
import EasyOFD from 'easyofd'

interface Props {
  urls?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  urls: () => [],
})
const url = ref<string>('')
const activateTab = ref<string>('')
const canvasRefs = ref<Record<string, HTMLCanvasElement | null>>({})

// 文件類型判斷
const ext = ref<string>('pdf')
const isOfd = ref<boolean>(false)
const isPdf = ref<boolean>(false)

//  設(shè)置 PDF.js worker 路徑(推薦方式)
pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdf.worker.min.mjs'

//  從 URL 中提取文件名
function fileName(url: string): string {
  try {
    const decodeURL = decodeURIComponent(url).split('/')
    const lastSegment = decodeURL[decodeURL.length - 1]

    const firstIndex = lastSegment.indexOf('-')
    const lastIndex = lastSegment.lastIndexOf('-')

    if (firstIndex === -1 || lastIndex === -1 || lastIndex <= firstIndex) {
      return lastSegment.split('.')[0] // fallback 文件名
    }

    const name = lastSegment.substring(firstIndex + 1, lastIndex)
    const ext = name.split('.').pop()

    if (['pdf', 'ofd'].includes(ext ?? '')) {
      return name.substring(0, name.lastIndexOf('.'))
    }

    return name
  } catch {
    return 'unknown'
  }
}

// 獲取文件類型
const getFileType = (url: string) => {
  const decodeURL = decodeURIComponent(url)
  ext.value = decodeURL.endsWith('.pdf') ? 'pdf' : 'ofd'
  isPdf.value = ext.value === 'pdf'
  isOfd.value = ext.value === 'ofd'
  isPdf.value ? loadAndRenderPdf(url) : loadAndRenderOfd(url)
}
//  下載文件
const handleDownload = debounce((url: string) => {
  saveAs(url, `${fileName(url)}.${ext.value}`)
}, 300)

//  加載并渲染 PDF
async function loadAndRenderPdf(pdfUrl: string) {
  try {
    const canvas = canvasRefs.value[pdfUrl]
    if (!canvas) return

    const loadingTask = pdfjsLib.getDocument(pdfUrl)
    const pdf = await loadingTask.promise
    const page = await pdf.getPage(1)

    const viewport = page.getViewport({ scale: 1.3 })

    canvas.height = viewport.height
    canvas.width = viewport.width

    const context = canvas.getContext('2d')
    if (!context) return

    const renderContext = {
      canvasContext: context,
      viewport,
    }

    await page.render(renderContext).promise
  } catch (error) {
    console.error('PDF 渲染失敗:', error)
  }
}

//  標(biāo)簽頁(yè)切換時(shí)加載 PDF
async function tabChangeHandler(key: string) {
  url.value = key
  activateTab.value = fileName(key)

  await nextTick() // 等待 DOM 更新
  if (key.endsWith('.pdf')) {
    await loadAndRenderPdf(key)
  }
}

//  頁(yè)面初始化時(shí)自動(dòng)加載第一個(gè) PDF
watch(
  () => props.urls,
  async (newUrls) => {
    if (newUrls && newUrls.length > 0) {
      console.log('newUrls:', newUrls)
      url.value = newUrls[0]
      activateTab.value = fileName(newUrls[0])
      await nextTick()
      getFileType(newUrls[0])
    }
  },
  { immediate: true },
)
</script>

<style lang="less" scoped>
.canvas {
  border: 1px solid #000;
  width: 100%; // 響應(yīng)式寬度
  border: 1px solid #000;
}
.pdf-container {
  display: flex;
  flex-direction: column;
  align-items: start;
  gap: 12px;
  max-width: 100%; // 限制最大寬度
  max-height: 400px;
  overflow: auto;
}
</style>

說(shuō)一下重點(diǎn):

問(wèn)題一: 通過(guò)命令pnpm install pdf.js安裝后,通常出現(xiàn)引用問(wèn)題;Cannot resolve pdf.worker.entry。代碼中使用的版本"pdfjs-dist": "^5.2.133"

import * as pdfjsLib from 'pdfjs-dist';
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry';

pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;

解決方案:

ps: 上面的代碼中包含了文件的下載功能,需要安裝 "file-saver": "^2.0.5",

將文件從node_modules/pdfjs-dist/build/pdf.worker.min.mjs移動(dòng)至項(xiàng)目的public/pdf.worker.min.mjs,可以使用命令 cp node_modules/pdfjs-dist/build/pdf.worker.min.mjs public/pdf.worker.min.mjs

修改引用:

import * as pdfjsLib from 'pdfjs-dist';

pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdf.worker.min.mjs'

2.ofd的預(yù)覽

實(shí)現(xiàn)方式:http://www.easyofd.cn/

安裝的依賴:

pnpm -i jszip x2js jb2 opentype.js easyofd

業(yè)務(wù)實(shí)現(xiàn):

<template>
  <div ref="containerRef" style="width: 100%; height: 800px;"></div>
</template>

<script setup>
import EasyOFD from "easyofd"
import { ref, onMounted } from 'vue'

const containerRef = ref(null)

onMounted(async () => {
  if (!containerRef.value) {
    console.error('OFD 容器不存在')
    return
  }

  const ofd = new EasyOFD('myOFD', containerRef.value)

  try {
    const response = await fetch('/files/sample.ofd')
    const blob = await response.blob()
    ofd.loadFromBlob(blob)
  } catch (e) {
    console.error('OFD 加載失敗:', e)
  }
})
</script>
	
<style lang="less" scoped>
// 隱藏右側(cè)的ppi模塊,減少空白
:deep(#myOFD-ppi) {
  display: none;
}
// 增加邊框
:deep(#myOFD-ofd-canvas) {
  border: 1px solid #000;
}
// 隱藏頂部按鈕
:deep(.OfdButton) {
  display: none !important;
}
</style>

官網(wǎng)效果:(easyOfd官網(wǎng)手冊(cè))

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

哈巴河县| 广汉市| 吉水县| 封开县| 崇信县| 积石山| 湖北省| 本溪| 桂平市| 平湖市| 襄垣县| 巴彦淖尔市| 泰来县| 凤阳县| 获嘉县| 防城港市| 舟山市| 大方县| 洛浦县| 台州市| 绵阳市| 铅山县| 南召县| 万安县| 鹤岗市| 察雅县| 大竹县| 莱西市| 塔河县| 阿荣旗| 酉阳| 嵊州市| 象州县| 长沙县| 中牟县| 平湖市| 太湖县| 丹凤县| 宿迁市| 渑池县| 兰州市|