uniapp实现将页面转换成pdf(小程序、app、h5)

使用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

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如下

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'))
    })
}

猜你喜欢

转载自blog.csdn.net/xiyan_yu/article/details/132496935