插件应用

pdf预览

  • vue-pdf
  • pdf.js

获取pdf文件的两种方式:
- .pdf文件: 两个插件都直接设置url即可
- 文件流: 需要转blob

#vue-pdf

1
npm install --save vue-pdf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
<div>
<pdf
ref="pdf"
:src="url"
>
</pdf>
<!-- 显示多页 -->
<pdf
ref="pdf"
v-for="i in numPages"
:key="i"
:src="url"
:page="i"
></pdf>
<!-- 翻页展示 -->
<el-button-group>
<el-button type="primary" icon="el-icon-arrow-left" size="mini" @click="prePage">上一页</el-button>
<el-button type="primary" size="mini" @click="nextPage">下一页<i class="el-icon-arrow-right el-icon--right"></i></el-button>
</el-button-group>
<div style="marginTop: 10px; color: #409EFF">{{ pageNum }} / {{ pageTotalNum }}</div>
<pdf
:page="pageNum"
:src="url"
@progress="loadedRatio = $event"
@num-pages="pageTotalNum=$event"
></pdf>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<script>
import pdf from 'vue-pdf'
export default {
components:{
pdf
},
data(){
return {
url:"http://image.cache.timepack.cn/nodejs.pdf",
numPages: null, // pdf 总页数
//
pageNum: 1, // 当前页
pageTotalNum: 1, // 总页数
loadedRatio: 0, // 当前页面的加载进度,范围是0-1 ,等于1的时候代表当前页已经完全加载完成了
}
},
mounted() {
this.getNumPages()
},
methods: {
# 计算pdf页码总数
getNumPages() {
let loadingTask = pdf.createLoadingTask(this.url)
loadingTask.promise.then(pdf => {
this.numPages = pdf.numPages
}).catch(err => {
console.error('pdf 加载失败', err);
})
},
// 上一页
prePage() {
let page = this.pageNum
page = page > 1 ? page - 1 : this.pageTotalNum
this.pageNum = page
},

// 下一页
nextPage() {
let page = this.pageNum
page = page < this.pageTotalNum ? page + 1 : 1
this.pageNum = page
}
}
</script>

#pdf.js

  • 下载
  • 将下载的文件(build、web、LICNSE)放到static(能访问的地方)
  • 页面使用
    1
    2
    3
    <iframe :src="url" width="100%" height="100%"></iframe>
    <!-- url = '/web/viewer.html?file=public/嵌入式系统课程教学大纲.pdf -->
    <!-- /web/viewer.html即web文件夹里的html -->

#坑

  • pdf.js处理url中带参数(?id=2001)时需要用encodeURIComponent 进行对url的编码
  • pdf.js处理跨域问题
    1
    2
    3
    4
    5
    // viewer.js
    // 注释掉一下代码
    if (origin !== viewerOrigin && protocol !== "blob:") {
    throw new Error("file origin does not match viewer's");
    }
  • 文件流形式展示pdf
    • 最好用pdf.js,vue-pdf坑很多,比如分页方法会造成浏览器崩溃,字体不全导致pdf展示不全
    • 用pdf.js需要在url上拼接&.pdf

#pdf文件流

1
2
3
4
5
let binaryData = []
binaryData.push(res.data)
let blob = new Blob(binaryData, {type: 'application/pdf'})
this.url = window.URL.createObjectURL(blob)
// <iframe :src="'/web/viewer.html?file='+url+'&.pdf'" width="100%" height="100%"></iframe>

参考

vue-pdf实现pdf文件在线预览
vue项目中使用pdf.js预览pdf文件


word预览

  • npm i docx-preview -S
  • 使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // 获取远程文件
    if (file.fileName.lastIndexOf('doc') !== -1) {
    const xhr = new XMLHttpRequest()
    xhr.open('get', ossSrc.imgURL + file.filePath, true)
    xhr.responseType = 'blob'
    xhr.onload = () => {
    if (xhr.status === 200) {
    console.log('xhr.response', xhr.response)
    // 文件 文件类型 是否远程
    this.$emit('preview', xhr.response, 'word', true)
    }
    }
    xhr.send()
    }

    const docx = require('docx-preview')
    this.$nextTick(() => {
    docx.renderAsync(this.file, this.$refs.fileRef, this.$refs.fileRef) // 渲染到页面
    })

excel预览

  • npm i xlsx -S
  • 使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    // 处理远程文件
    if (file.fileName.lastIndexOf('xlsx') !== -1) {
    this.wb = null
    const xhr = new XMLHttpRequest()
    xhr.open('get', ossSrc.imgURL + file.filePath, true)
    xhr.responseType = 'arraybuffer'
    xhr.onload = () => {
    if (xhr.status === 200) {
    console.log('xhr.response', xhr.response)
    try {
    var binary = ''
    const bytes = new Uint8Array(xhr.response)
    const length = bytes.byteLength
    for (let i = 0; i < length; i++) {
    binary += String.fromCharCode(bytes[i])
    }
    this.wb = XLSX.read(binary, { type: 'binary' })
    console.log(this.wb)
    var wsname = this.wb.SheetNames[0]
    this.activeSheet = wsname
    var ws = this.wb.Sheets[wsname]
    var HTML = XLSX.utils.sheet_to_html(ws)
    console.log(HTML)
    this.$refs.excelRef.innerHTML = HTML
    } catch (error) {
    console.log(error)
    this.$message.error('文件打开失败!')
    }
    // 文件 文件类型 是否远程
    }
    }
    xhr.send()
    }

    <div v-if="fileType === 'excel'" ref="excelRef" class="excel-dom" />
    // sheet切换
    <ul v-if="fileType === 'excel' && wb && wb.SheetNames && wb.SheetNames.length" class="sheet-sty">
    <li v-for="(item, index) in wb.SheetNames" :key="index" @click="handleChangeSheet(item)">
    <el-button :type="activeSheet === item ? 'primary' : ''" size="mini">{{ item }}</el-button>
    </li>
    </ul>

    import * as XLSX from 'xlsx'
    this.$refs.excelRef.innerHTML = this.file

    // sheet切换方法
    handleChangeSheet(sheetName) {
    this.activeSheet = sheetName
    var ws = this.wb.Sheets[sheetName]
    var HTML = XLSX.utils.sheet_to_html(ws)
    if (this.$refs.excelRef) {
    this.$refs.excelRef.innerHTML = HTML
    }
    },

px2rem & lib-flexible & sass || less

#安装依赖

注意,sass-loader和less-loader版本不能太高,上述版本没问题

#配置

  • 引入flexible
    1
    2
    // main.js
    import 'lib-flexible'
  • 配置px2rem||sass||less
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    // vue.config.js
    const path = require('path')

    module.exports = {
    chainWebpack: (config) => {
    config.module
    .rule('scss') // css,less,注意sass用scss
    // .test(/\.css$/) // css时配置此项
    .oneOf('vue')
    .resourceQuery(/\?vue/)
    .use('px2rem-loader')
    .loader('px2rem-loader')
    .before('sass-loader') // before需要在px2rem之前使用
    .options({
    remUnit: 75, // 设计图750px
    remPrecision: 2 // 换算rem后保留几位小数
    })
    config.resolve.alias
    .set('@', path.join(__dirname, 'src'))
    .set('@assets', path.join(__dirname, 'src/assets'))
    },
    css: {
    loaderOptions: {
    sass: { // 配置sass公共样式
    data: `
    @import "~@assets/style/variable.scss";
    @import "~@assets/style/common.scss";
    @import "~@assets/style/mixin.scss";
    `
    }
    }
    }
    }
  • html配置
    1
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

VR全景图预览

  • 首先需要全景图片资源
  • npm i photo-sphere-viewer -S
  • 在页面中使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // 引入依赖
    import { Viewer } from 'photo-sphere-viewer'
    import 'photo-sphere-viewer/dist/photo-sphere-viewer.css'

    // 引入全景图资源
    const vrImgUrl = require('../assets/vr1.jpg')

    // 挂在渲染
    onMounted(() => {
    const viewer = new Viewer({
    container: document.querySelector('#viewer'),
    panorama: vrImgUrl,
    size:{
    width: '100vw',
    height: '50vh',
    },
    });
    console.log(viewer)
    })