html2canvas文档官网: http://html2canvas.hertzen.com/documentation/
html2canvas插件把相应的DOM节点里的所有元素按其属性来构建,生成截图,有些css属性它无法识别(理解不了),所以产生会有点偏差,不过问题不大
局限性: 使用的所有图像都需要在同一资源下,即最好不要跨域
浏览器兼容:
- Firefox 3.5+
- Google Chrome
- Opera 12+
- IE9 +
- Edge
- Safari 6+
安装及引入:
npm install html2canvas
import html2canvas from 'html2canvas'
html2canvas(document,option).then(canvas=>{......})
document 即是需要绘制的节点, option 为一些可选择配置
option可用参数:
参数名称 | 类型 | 默认值 | 描述 |
allowTaint | boolean | false | 是否允许跨域 |
background | string | #ffffff | 画布的背景色,如果没有在DOM中指定,将设置为透明 |
canvas | document | null | 现有canvas 元素用作绘图的基础 |
imageTimeout | number | 15000 | 加载图像的超时时间(单位: 毫秒),设置为0为禁用超时 |
timeout | number | 0 | 图片加载延时,默认延时为0(单位: 毫秒) |
logging | boolean | true | 在console.log()输出以进行调试 |
proxy | string | undefined | 设置跨域代理地址,如果留空则不会加载跨域图像 |
taintTest | boolean | true | 是否在渲染前测试图片 |
useCORS | boolean | false | 是否尝试使用CORS从服务器加载图像(也是跨域图像,我使用的时候未成功,原因未知) |
width | number | null | 画布宽度 |
height | number | null | 画布高度 |
如果希望Element
从渲染中排除某些s,则可以data-html2canvas-ignore
向这些元素添加属性,并且html2canvas会将它们从渲染中排除。(不知道啥意思)
例子:

1 <div class="share"> 2 <div class="imageWrapper" ref="imageWrapper"> 3 <img class="real_pic" :src="dataURL" /> 4 <!-- 需要转化为图片的DOM元素 --> 5 <slot> 6 <div class="canvas-bg"> 7 <img class="canvas-title" src="@/images/canvas-title.png" alt /> 8 <div class="canvas-info"> 9 <div class="info-content"> 10 <span>我叫</span> 11 <span>{{ userInfo.name }}</span> 12 </div> 13 <div class="info-content"> 14 <span>来自</span> 15 <span>{{ userInfo.userSchool }}</span> 16 </div> 17 <div class="info-content">在网上老年大学</div> 18 <div class="info-content"> 19 <span>学习</span> 20 <span class="study-day">{{ userInfo.study_day }}</span> 21 <span>天啦</span> 22 </div> 23 </div> 24 <div class="canvas-footer"> 25 <div class="canvas-user"> 26 <img :src="userInfo.user_image" alt /> 27 </div> 28 </div> 29 <div class="canvas-er"> 30 <img :src="userInfo.share_qrcode" alt /> 31 <div class="text">长按保存图片</div> 32 <div class="text">扫码一起学习</div> 33 </div> 34 </div> 35 </slot> 36 </div> 37 <div class="watermark">长按海报保存图片</div> 38 </div>

1 .share { 2 font-family: Source Han Sans CN; 3 position: relative; 4 .imageWrapper { 5 min-height: 100vh; 6 background: url("../images/canvas-bg.png") no-repeat; 7 background-size: 100% 100%; 8 position: relative; 9 .real_pic { 10 width: 100%; 11 height: 100%; 12 position: fixed; 13 top: 0; 14 bottom: 0; 15 left: 0; 16 right: 0; 17 z-index: 88; 18 opacity: 0; 19 } 20 } 21 .show-msg{ 22 position: fixed; 23 top: 0; 24 right: 0; 25 left: 0; 26 bottom: 0; 27 display: flex; 28 justify-content: center; 29 align-items: center; 30 font-size: 1.5rem /* 24/16 */; 31 color: white; 32 .msg{ 33 width: 15.3125rem /* 245/16 */; 34 height: 3.125rem /* 50/16 */; 35 line-height: 3.125rem /* 50/16 */; 36 text-align: center; 37 background: rgba(0,0,0,.6); 38 border-radius: .3125rem /* 5/16 */; 39 } 40 } 41 } 42 .canvas-bg { 43 min-height: 100%; 44 padding-top: 3.40625rem /* 54.5/16 */; 45 padding-left: 1.875rem; 46 .canvas-title { 47 width: 16.6875rem /* 267/16 */; 48 height: 10.3125rem /* 165/16 */; 49 margin-bottom: 2.15625rem; 50 } 51 .canvas-info { 52 font-size: 1.1875rem; 53 font-family: Source Han Sans CN; 54 font-weight: 400; 55 color: rgba(255, 255, 255, 1); 56 margin-bottom: 45.5px; 57 .info-content { 58 margin-bottom: 0.5125rem; /* 30/16 */ 59 & span:nth-child(2) { 60 font-size: 1.1875rem /* 19/16 */; 61 font-family: Source Han Sans CN; 62 font-weight: bold; 63 color: rgba(254, 207, 84, 1); 64 margin-left: 5px; 65 margin-right: 5px; 66 } 67 .study-day{ 68 font-size: 1.5rem !important; 69 } 70 } 71 } 72 .canvas-er { 73 max-width: 6.75rem /* 108/16 */; 74 padding-bottom: 5.90625rem /* 94.5/16 */; 75 z-index: 99; 76 img { 77 width: 100%; 78 height: 100%; 79 margin-bottom: 0.625rem /* 17/16 */; 80 background: white; 81 border-radius: 0.625rem /* 10/16 */; 82 overflow: hidden; 83 } 84 .text { 85 font-size: 0.9375rem /* 15/16 */; 86 font-family: Source Han Sans CN; 87 font-weight: 400; 88 color: rgba(255, 255, 255, 1); 89 text-align: center; 90 } 91 } 92 .canvas-footer { 93 width: 13.625rem /* 218/16 */; 94 height: 22.8438rem; 95 position: absolute; 96 bottom: 0; 97 right: 0; 98 background: url("../images/canvas-people.png") no-repeat; 99 background-size: 100% 100%; 100 border: none; 101 .canvas-user { 102 position: absolute; 103 top: -0.3125rem /* 5/16 */; 104 right: 1.425rem; 105 width: 5.8875rem /* 94.2/16 */; 106 height: 5.8875rem /* 94.2/16 */; 107 border: 2px solid rgba(255, 255, 255, 1); 108 border-radius: 100%; 109 overflow: hidden; 110 display: flex; 111 justify-content: center; 112 align-items: center; 113 img { 114 width: 100%; 115 height: 100%; 116 } 117 } 118 } 119 } 120 .watermark{ 121 font-size: 1.25rem /* 20/16 */; 122 font-family:Source Han Sans CN; 123 font-weight: bold; 124 color:rgba(255,255,255,0.3); 125 position: absolute; 126 bottom: 1.875rem /* 30/16 */; 127 left: 2rem /* 32/16 */; 128 }
只要是在 'imageWrapper' 节点外面的元素就不会被一起绘制生成海报,之后把整个画布铺满页面,层级最高,再设置透明度为0,就可以长按保存啦.
1 html2canvas(this.$refs.imageWrapper, { 2 backgroundColor: null, 3 allowTaint: true, //是否允许跨域图片 4 useCORS: true, 5 taintTest: true 6 }) 7 .then(canvas => { 8 let dataURL = canvas.toDataURL("image/png"); //转成base64 9 this.dataURL = dataURL; //在img的src中使用 10 })
在mounted的时候调用生成即可,图片加载有时候会比较慢,可以再加个延时器
问题总结:
1. 一开始是使用跨域的图片,时而生成的图片会没有相应的图片什么的,我就把它转换成base64的图片

1 conUrlBase64(len,url) { 2 //网络资源图片转成base64 3 //console.log("图片路径",url) 4 var canvas = document.createElement("canvas"); //创建canvas DOM元素 5 var ctx = canvas.getContext("2d"); 6 return new Promise((reslove, reject) => { 7 var img = new Image(); 8 img.crossOrigin = "Anonymous"; 9 img.onload = function() { 10 canvas.height = len; //指定画板的高度,自定义 11 canvas.width = len; //指定画板的宽度,自定义 12 ctx.drawImage(img, 0, 0, len, len); 13 var dataURL = canvas.toDataURL("image/"); 14 canvas = null; 15 reslove(dataURL); 16 }; 17 img.onerror = function(err){ 18 reject(err) 19 } 20 img.src = url; 21 }); 22 }
这里使用Promise, 方便后面如果有多张需要转换的图片,使用Promise.all() 一次转换,终身收益
2. 我写完后安卓手机生成的海报图片会有一条线,iOS却没有,还未解决,让设计换了切图也还是会有,不知道是不是兼容性问题还是我的样式写的问题