移动端需求
业务背景:自动获取用户姓名,每个人输入自己想说的话,上传头像,然后自动生成统一背景的图片,并且长按下载下来。上传头像不进行存储到数据库,所以不涉及图片问题跨域。 (注:如果用户不输入文字,只有图片,直接用html2canvas就行)
技术选型:dom-to-image 与 html2canvas
一.dom-to-image
1.dom-to-image ios只支持生成svg图片,并且不支持background 引入的背景图片,
生成图片高清,但是在企业微信上面长按保存 模糊
2.dom-to-image android 可以生成svg图片,但是svg在android上不支持长按保存,
只能采取toPng,toJepg,但是生成图片模糊,长按保存也模糊
二.html2canvas
html2canvas 生成的图片高清且支持安卓 与 ios,生成图片时需要一个延时显示生成的图片。
注意点:若内容高于body时,在生成截图前,先把滚动条置顶
使用方法:
1.安装 npm install --save html2canvas
2.import html2canvas from 'html2canvas'
3.生成图片代码内容:如下
//先把滚动条置顶
window.pageYoffset=0;
document.documentElement.scrollTop=0;
document.body.scrollTop=0;
let node=document.getElementById('my-node');
let w=parseInt(node.offsetWidth);
let h=parseInt(node.offsetHeight);
html2canvas(node).then((canvas)=>{
canvas.style.width= w + 'px';
canvas.style.height=h + 'px';
let url =canvas.toDataURL();
const img=new Image();
img.src=url;
//设置生成图片展示的大小
img.style.width=w * 0.9 + 'px';
img.style.height=h * 0.7 + 'px';
//放在渲染的div里面
document.getElementById('generate-photo').appendChild(img)
},200)
//渲染的div需要延时,不然生成图片不完整
setTimout(()=>{
this.vshowPhoto=true;
},3500)
我以为用html2canvas就好了,结果部分手机测试发现生成图片字体会叠加在一起,用了好多方法都没有效果,最后用dom-to-image插件生成svg图片,然后再用html2canvas生成图片,字段才不重叠,图片也高清 代码片段如下:
//node需要渲染的div
var node = document.getElementById("my-node");
function filter(node) {
return node.tagName !== "i";
}
domtoimage.toSvg(node, {
filter: filter,
})
.then((dataUrl) => {
/* do something */
let img = new Image();
img.src = dataUrl;
//photo 一个空div,用来存放dom-to-image生成的svg图片
let photo = document.getElementById("help-div-img");
img.onload = () => {
//渲染第一个svg生成的dom
this.vshowMainOne = 1;
document.getElementById("help-div-img").appendChild(img);
var w = parseInt(node.offsetWidth);
var h = parseInt(node.offsetHeight);
//隐藏原页面的节点
this.vshowMain = false;
this.showLoading("生成图片中");
window.pageYoffset = 0;
document.documentElement.scrollTop = 0;
document.body.scrollTop = 0;
let photoStyle;
//因为苹果系统此版本生成照片时,背景图片失踪,做特殊处理,直接用html2canvas生成
if (this.$platform == "ios_12.5.4") {
photoStyle = node;
} else {
photoStyle = photo;
}
//html2canvas 重绘svg
html2canvas(photoStyle).then((canvas) => {
if (canvas) {
canvas.style.width = w + "px";
canvas.style.height = h + "px";
var url = canvas.toDataURL();
const img2 = new Image();
img2.src = url;
img2.style.transform = " scale(1.1)";
img2.style.width = w * 0.8 + "px";
img2.style.height = h * 0.7 + "px";
//渲染第二次生成的图片,隐藏第一次生成的图片
this.vshowMainOne = 2;
img2.onload = () => {
document.getElementById("help-ios-img").appendChild(img2);
photo.style.height = 0;
this.closeLoading();
};
}
});
};
});
pc端需求
需求:将系统统计的数据生成分析报告,然后可以导出成PDF下载到电脑上。
一. 安装依赖
npm install --save html2canvas // 页面转图片
npm install jspdf --save // 图片转pdf
二. 写一个pdf.js文件
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
export const downloadPDF = page => {
html2canvas(page).then(function(canvas) {
canvas2PDF(canvas);
});
};
const canvas2PDF = canvas => {
let contentWidth = canvas.width;
let contentHeight = canvas.height;
//a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
let imgWidth = 595.28;
let imgHeight = 592.28/contentWidth * contentHeight;
// 第一个参数: l:横向 p:纵向
// 第二个参数:测量单位("pt","mm", "cm", "m", "in" or "px")
let pdf = new jsPDF("p", "pt");
pdf.addImage(
canvas.toDataURL("image/jpeg", 1.0),
"JPEG",
0,
0,
imgWidth,
imgHeight
);
pdf.save("导出.pdf");
};
三.页面转图片
在index.vue 页面:
<template>
<div ref="pdf">
这是待转换的页面,点击
<button @click="handleExport">导出</button> 按钮,完成导出操作。
</div>
</template>
<script>
import {downloadPDF} from "@/util/pdf.js" //工具方法,导出操作
export default {
name: "pdf",
data() {
return {};
},
methods: {
handleExport(){
downloadPDF(this.$refs.pdf)
}
}
};
</script>
pc端转成pdf文档下载,参考文档:blog.csdn.net/ksjdbdh/art…
pc端扩展(带大图缩放展示)
需求:将系统统计的数据与图片生成分析报告,然后可以导出成PDF下载到电脑上,并且图片支持大图查看细节。
pdf导出图片效果图如下:
一. 安装依赖
npm install --save html2canvas // 页面转图片
npm install jspdf --save // 图片转pdf
二. 写一个pdf.js文件
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
export const downloadPDF = (page, img, width, height, userName) => {
//数据详情页面画成canvas
html2canvas(page).then(function (canvas) {
canvas2PDF(canvas, img, width, height, userName, account);
});
};
const canvas2PDF = (canvas, img, width, height, userName) => {
let contentWidth = canvas.width;
let contentHeight = canvas.height;
//a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
let imgWidth = 595.28;
let imgHeight = (592.28 / contentWidth) * contentHeight;
//控制第二个页面图片的大小,按照一定的比例去缩放图片
if (width > height) {
if (width > 2000) {
width = width * 0.1;
height = height * 0.1;
} else if (1000 < width < 2000) {
width = width * 0.2;
height = height * 0.2;
} else if (800 < width < 1000) {
width = width * 0.4;
height = height * 0.4;
} else if (400 < width < 800) {
width = width * 0.7;
height = height * 0.7;
}
} else {
if (height > 2000) {
width = width * 0.1;
height = height * 0.1;
} else if (1000 < height < 2000) {
width = width * 0.2;
height = height * 0.2;
} else if (800 < height < 1000) {
width = width * 0.4;
height = height * 0.4;
} else if (400 < height < 800) {
width = width * 0.7;
height = height * 0.7;
}
}
console.log(width, height, "widht,height----------", img);
// 第一个参数: l:横向 p:纵向
// 第二个参数:测量单位("pt","mm", "cm", "m", "in" or "px")
let pdf = new jsPDF("p", "pt");
//第一个数据详情页面
pdf.addImage(
canvas.toDataURL("image/jpeg", 1.0),
"JPEG",
0,
50,
imgWidth,
imgHeight
);
//只有一张图片时,展示图片的代码如下所示
·····只取其一·········
if (img) {
// 添加第二页,设置页面的大小
pdf.addPage([imgWidth, 700]);
//添加第二个页面的图片
pdf.addImage(img, "png", 20, 30, width, height);
}
······只取其一···················
//如果有两张图片时,展示图片的代码如下所示(上面传递的参数也要跟着变化eg:imgOne...)
if (imgOne) { //第一张图片
pdf.addPage([imgWidth, 700]);
pdf.addImage(imgOne, "png", 20, 30, widht1, height1);
if (imgTwo) { //有第二张图片时
if (height1 + height2 < 750) {
//两张图片小于pdf页面总高度,就添加到一个页面
pdf.addImage(imgTwo, "png", 20, height1 + 40, widht2, height2);
} else {
//大于则再添加一个新页面
pdf.addPage([imgWidth, 700]);
pdf.addImage(imgTwo, "png", 20, 30, widht2, height2);
}
}
}
....................
pdf.save(`xxx_${userName}.pdf`);
};
三.页面转图片
在index.vue 页面:
<template>
<div ref="pdf">
<img ref="imgPdf"
:src="'data:image/png;base64,' + file"
class="img-view"
alt=""
/>
这是待转换的页面,点击
<button @click="handleExport">导出</button> 按钮,完成导出操作。
</div>
</template>
<script>
import {downloadPDF} from "@/util/pdf.js" //工具方法,导出操作
export default {
name: "pdf",
data() {
return {
file:'',
name:'',
};
},
methods: {
handleExport(){
let image = document.querySelector(".img-view");
downloadPDF(
this.$refs.pdf, //pdf第一页
this.$refs.imgPdf, //pdf第二页
image.naturalWidth, //图片宽度
image.naturalHeight, //图片高度
name, //pdf文件名字
);
}
}
};
</script>