使用html2Canvas和jspdf
安装这两个
npm i jspdf html2canvas
uniapp在小程序无法获取dom,app端可在renderjs中获取 dom,小程序需要使用web-view导入一个h5页面,实现转pdf
H5和小程序
<template>
<div>
<div id="content">
要转换的内容
</div>
<button type="button" class="btn btn-primary" @click="getPdf()">导出PDF</button>
</div>
</template>
<script>
import html2Canvas from 'html2canvas'
import { jsPDF } from 'jspdf'
let BaseUrl = 'url' //域名
export default{
methods:{
getPdf(){
let that = this
var shareContent = document.getElementById('content');
var width = shareContent.offsetWidth / 4;
var height = shareContent.offsetHeight / 4;
html2Canvas(shareContent , {
dpi: 900,
scrolly: 0,
// width:eleW,//生成后的宽度
// height:eleH,//生成后的高度
scrollx: -10,
useCORS: true, //允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
// backgroundColor: null //避免图片有白色边框
}).then((canvas) => {
var context = canvas.getContext('2d');
context.mozImageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
context.msImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
var pageData = canvas.toDataURL('image/jpeg', 1.0);
var img = new Image();
img.src = pageData;
img.onload = () => {
// 获取dom高度、宽度
img.width = img.width / 2;
img.height = img.height / 2;
console.log(img.width, '------ img.width');
console.log(img.height, '------img.height');
img.style.transform = 'scale(0.5)';
if (width > height) {
// 此可以根据打印的大小进行自动调节
// eslint-disable-next-line
var pdf = new jsPDF('l', 'mm', [width * 0.505, height * 0.545]);
} else {
// eslint-disable-next-line
var pdf = new jsPDF('p', 'mm', [width * 0.505, height * 0.545]);
}
pdf.addImage(pageData, 'jpeg', 0, 0, width * 0.505, height * 0.545);
pdf.save('安全服务协议' + '.pdf'); //h5在这就可以保存pdf
//内嵌到微信小程序
var blob = pdf.output("datauristring");
console.log(wx,'wx')
wx.miniProgram.getEnv(function (res) {
console.log("当前环境:" + JSON.stringify(res));
});
wx.miniProgram.postMessage({
data: {
imageData:blob
},
});
wx.miniProgram.navigateBack()
};
}).catch((r) => {
console.log(r);
})
},
},
onLoad(e) {
this.id = e.id
}
}
</script>
其中通过web-view导入到微信小程序的话,需要导入微信的sdk
在index.html中导入也不知道咋回事,有wx,但是wx.miniProgram是undefined
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
然后网上找到大佬的方法
在App.vue里面写
onLaunch: function() {
console.log('App Launch')
// #ifdef H5
var script = document.createElement('script');
script.src = "https://res.wx.qq.com/open/js/jweixin-1.4.0.js";
script.type = 'text/javascript';
document.body.appendChild(script);
// #endif
},
然后在小程序中使用web-view导入这个h5
<template>
<view class="">
<web-view :src="url" @message="message"></web-view>
</view>
</template>
<script>
export default{
data(){
return{
imageData:'',
id:'',
url:''
}
},
methods:{
message(e){
console.log(e,'e')
this.imageData = e.detail.data[0].imageData
let path = this.imageData.split('base64,')[1]
this.download(path)
},
async download(url) {
let result = url.replace(/[\r\n]/g, '');
var fs = wx.getFileSystemManager();
let fileName = '';
var times = new Date().getTime();
url = wx.base64ToArrayBuffer(result);
// console.log(url,'图片临时路径')
const filePath = wx.env.USER_DATA_PATH + '/' + Date.now() + '.pdf'
fs.writeFile({
filePath,
data: url, // 将 base64 转为 arrayuffer
success (res) {
uni.openDocument({
showMenu: true,
fileType: 'pdf',
filePath,
success: function (res) {
console.log('打开文档成功')
}
})
},
fail (err) {
console.log('错误', err)
}
})
},
},
onLoad(e) {
this.id = e.id || 0
this.url = this.$http.BaseUrl+`/h5/#/?id=${this.id}`
console.log(this.url,'url')
}
}
</script>
App端
也可以使用web-view,但我直接在renderjs中写了
<template>
<div>
<div id="content">
要转换的内容
</div>
<button type="button" class="btn btn-primary" @click="canvasImage.save">导出PDF</button>
</div>
</template>
<script>
import { base64ToPath } from '../../../common/imageTools.js';
export default{
methods:{
receiveRenderData(url){
this.loadBase64Url(url)
},
/* 将base64 位的图片路径转换为 临时路径 */
loadBase64Url(url) {
const imageStr = url;
base64ToPath(imageStr)
.then(path => {
console.log(path,'path')
this.saveImage(path);
})
.catch(error => {
console.error('临时路径转换出错了:', error);
});
},
saveImage(url){
uni.saveFile({
tempFilePath:url,
async success(res) {
uni.openDocument({
filePath:res.savedFilePath,
success: function(FileRes) {
console.log('打开成功');
}
});
},
complete(res) {
console.log(res,'res')
}
})
},
}
}
</script>
<script lang="renderjs" module="canvasImage">
import html2Canvas from 'html2canvas'
import { jsPDF } from 'jspdf'
export default {
methods: {
// 生成图片需要调用的方法
generateImage(e, ownerFun) {
return new Promise((resolve, reject) => {
var shareContent = document.getElementById('content');
var width = shareContent.offsetWidth / 4;
var height = shareContent.offsetHeight / 4;
html2Canvas(document.getElementById('content'), {
dpi: 900,
scrolly: 0,
// width:eleW,//生成后的宽度
// height:eleH,//生成后的高度
scrollx: -10,
useCORS: true, //允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
// backgroundColor: null //避免图片有白色边框
}).then((canvas) => {
setTimeout(()=> {
var context = canvas.getContext('2d');
context.mozImageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
context.msImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
var pageData = canvas.toDataURL('image/jpeg', 1.0);
// resolve(pageData)
var img = new Image();
img.src = pageData
img.onload = () => {
// 获取dom高度、宽度
img.width = img.width / 2;
img.height = img.height / 2;
// console.log(img.width, '------ img.width');
// console.log(img.height, '------img.height');
img.style.transform = 'scale(0.5)';
if (width > height) {
// 此可以根据打印的大小进行自动调节
// eslint-disable-next-line
var pdf = new jsPDF('l', 'mm', [width * 0.505, height * 0.545]);
} else {
// eslint-disable-next-line
var pdf = new jsPDF('p', 'mm', [width * 0.505, height * 0.545]);
}
pdf.addImage(pageData, 'jpeg', 0, 0, width * 0.505, height * 0.545);
var url = pdf.output("datauristring");
resolve(url)
};
}, 500);
}).catch((r) => {
console.log(r);
})
})
},
async save(e,ownerFun){
let img = await this.generateImage().then()
ownerFun.callMethod('receiveRenderData',img)
},
},
}
</script>
然后发现在ios中pdf中的网络路径的图片不显示,用过其他方法,太笨还是不行,只能转base64文章来源:https://www.toymoban.com/news/detail-717360.html
urlTobase64(url){
return new Promise((resolve,reject)=>{
uni.request({
url: url,
method:'GET',
responseType:'arraybuffer',
success: res => {
let base64 = wx.arrayBufferToBase64(res.data); //把arraybuffer转成base64
base64 = ('data:image/jpg;base64,' + base64).replace(/[\r\n]/g, "")
resolve(base64)
},fail: (e) => {
resolve(url)
console.log("图片转换失败");
}
})
})
},
资源绑定那个js下载居然还要vip -_-,imageTool.js如下文章来源地址https://www.toymoban.com/news/detail-717360.html
function getLocalFilePath(path) {
if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) {
return path
}
if (path.indexOf('file://') === 0) {
return path
}
if (path.indexOf('/storage/emulated/0/') === 0) {
return path
}
if (path.indexOf('/') === 0) {
var localFilePath = plus.io.convertAbsoluteFileSystem(path)
if (localFilePath !== path) {
return localFilePath
} else {
path = path.substr(1)
}
}
return '_www/' + path
}
function dataUrlToBase64(str) {
var array = str.split(',')
return array[array.length - 1]
}
var index = 0
function getNewFileId() {
return Date.now() + String(index++)
}
function biggerThan(v1, v2) {
var v1Array = v1.split('.')
var v2Array = v2.split('.')
var update = false
for (var index = 0; index < v2Array.length; index++) {
var diff = v1Array[index] - v2Array[index]
if (diff !== 0) {
update = diff > 0
break
}
}
return update
}
export function pathToBase64(path) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
if (typeof FileReader === 'function') {
var xhr = new XMLHttpRequest()
xhr.open('GET', path, true)
xhr.responseType = 'blob'
xhr.onload = function() {
if (this.status === 200) {
let fileReader = new FileReader()
fileReader.onload = function(e) {
resolve(e.target.result)
}
fileReader.onerror = reject
fileReader.readAsDataURL(this.response)
}
}
xhr.onerror = reject
xhr.send()
return
}
var canvas = document.createElement('canvas')
var c2x = canvas.getContext('2d')
var img = new Image
img.onload = function() {
canvas.width = img.width
canvas.height = img.height
c2x.drawImage(img, 0, 0)
resolve(canvas.toDataURL())
canvas.height = canvas.width = 0
}
img.onerror = reject
img.src = path
return
}
if (typeof plus === 'object') {
plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
entry.file(function(file) {
var fileReader = new plus.io.FileReader()
fileReader.onload = function(data) {
resolve(data.target.result)
}
fileReader.onerror = function(error) {
reject(error)
}
fileReader.readAsDataURL(file)
}, function(error) {
reject(error)
})
}, function(error) {
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
wx.getFileSystemManager().readFile({
filePath: path,
encoding: 'base64',
success: function(res) {
resolve('data:image/png;base64,' + res.data)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
export function base64ToPath(base64) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
base64 = base64.split(',')
var type = base64[0].match(/:(.*?);/)[1]
var str = atob(base64[1])
var n = str.length
var array = new Uint8Array(n)
while (n--) {
array[n] = str.charCodeAt(n)
}
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
}
var extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/)
if (extName) {
extName = extName[1]
} else {
reject(new Error('base64 error'))
}
var fileName = getNewFileId() + '.' + extName
if (typeof plus === 'object') {
var basePath = '_doc'
var dirPath = 'uniapp_temp'
var filePath = basePath + '/' + dirPath + '/' + fileName
if (!biggerThan(plus.os.name === 'Android' ? '1.9.9.80627' : '1.9.9.80472', plus.runtime.innerVersion)) {
plus.io.resolveLocalFileSystemURL(basePath, function(entry) {
entry.getDirectory(dirPath, {
create: true,
exclusive: false,
}, function(entry) {
entry.getFile(fileName, {
create: true,
exclusive: false,
}, function(entry) {
entry.createWriter(function(writer) {
writer.onwrite = function() {
resolve(filePath)
}
writer.onerror = reject
writer.seek(0)
writer.writeAsBinary(dataUrlToBase64(base64))
}, reject)
}, reject)
}, reject)
}, reject)
return
}
var bitmap = new plus.nativeObj.Bitmap(fileName)
bitmap.loadBase64Data(base64, function() {
bitmap.save(filePath, {}, function() {
bitmap.clear()
resolve(filePath)
}, function(error) {
bitmap.clear()
reject(error)
})
}, function(error) {
bitmap.clear()
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
var filePath = wx.env.USER_DATA_PATH + '/' + fileName
wx.getFileSystemManager().writeFile({
filePath: filePath,
data: dataUrlToBase64(base64),
encoding: 'base64',
success: function() {
resolve(filePath)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
到了这里,关于uniapp实现将页面转换成pdf(小程序、app、h5)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!