html dom 转化成图片踩坑记(canvas toDataURL)
需求
在开发过程中遇到这么一个需求,h5页面需要将一个html dom转化成图片,便于用户保存。
面向百度搜索第三方得 html2canvas 和 dom-to-image
两者在写这篇笔记之前在github上的星星数分别是
dom-to-image 4k ️
html2canvas 13.7k ️
两者都有尝试过,都有意想不到的bug,包括
- 部分手机有某些背景图片无法展示,为空白
 - iphone8 plus ios 11中根本不调用这个转换方法,从而得不到想要的图片。
 
等等
自己动手
思路
利用canvas的toDataURL来拿到canvas转化的base64码,来替换img的url, 也可以把图片上传到公司的服务器上,得到图片的地址来进行下载,或作为参数来传递
那么canvas的绘制主要就是文本和图片的绘制,文本绘制相对简单,图片绘制有一些注意点。
canvas 初始化
由于最后生成的图片可能会模糊,可以尽量画大一点画布,可以按照设计图来
<canvas id="canvas" width="750" height="1164">
  你的浏览器居然不支持Canvas?!赶快换一个吧!!
</canvas>
let c = document.getElementById("canvas");
let ctx = c.getContext("2d");
文本绘制
官方文档如图
详细文档请参考 canvas手册
代码示例
ctx.fillStyle = "#fff";
ctx.font = "32px PingFangSC-Regular";
ctx.textAlign = "left";
ctx.fillText("这是一些文字", 280, 755);
图片绘制
官方文档如图
详细文档请参考 canvas手册
注意事项
- 图片需要进行跨域处理,否则后期无法生成图片,也就是在img标签中增加crossOrigin属性,值为anonymous
 
const instBanner = document.getElementById("instBanner");
instBanner.crossOrigin = "anonymous";
- 需要等到图片加载完成再画到画布上,否则有可能没画上去
 
const posterBg = new Image();
posterBg.src = mainBg;
posterBg.onload = () => {
  ctx.drawImage(posterBg, 0, 0, 750, 1164);
}
完整代码示例
const posterBg = new Image();
posterBg.src = 'https:....'; //这里是图片url
posterBg.crossOrigin = "anonymous";
posterBg.onload = () => {
  ctx.drawImage(posterBg, 0, 0, 750, 1164);
}
生成图片
替换img src
let dataURL = c.toDataURL("image/png");
let canvasImg = document.getElementById("canvasImg");
canvas.src = dataURL;
上传服务器,得到img url(可作为参数,保存图片)
let dataURL = c.toDataURL("image/png");
function getImgUrl(dataURL){
  //一些上传服务器的代码
  return imgUrl
}
let imgUrl = getImgUrl();
let canvasImg = document.getElementById("canvasImg");
canvas.src = imgUrl;
最后奉上一些,常用的canvas处理方法
圆形图片的绘制
ctx.save();
ctx.beginPath(); //开始绘制
//先画个圆   前两个参数确定了圆心 (x,y) 坐标  第三个参数是圆的半径  四参数是绘图方向  默认是false,即顺时针
ctx.arc(60, 60, 30, 0 * Math.PI, 2 * Math.PI);
ctx.clip();//画好了圆 剪切  原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内 这也是我们要save上下文的原因
ctx.drawImage('https:....', 30, 30, 60, 60);
contex.restore(); //恢复之前保存的绘图上下文 恢复之前保存的绘图上下午即状态 还可以继续绘制
圆角矩形绘制
/**该方法用来绘制圆角矩形
*@param cxt:canvas的上下文环境
*@param x:左上角x轴坐标
*@param y:左上角y轴坐标
*@param width:矩形的宽度
*@param height:矩形的高度
*@param radius:圆的半径
*@param lineWidth:线条粗细
*@param strokeColor:线条颜色
**/
function strokeRoundRect(cxt,x,y,width,height,radius,/*optional*/lineWidth,/*optional*/strokeColor){
    //圆的直径必然要小于矩形的宽高
    if(2*radius>width || 2*radius>height){return false;}  
    cxt.save();
    cxt.translate(x,y);
    //绘制圆角矩形的各个边
    drawRoundRectPath(cxt,width,height,radius);
    cxt.lineWidth = lineWidth||2;//若是给定了值就用给定的值否则给予默认值2
    cxt.strokeStyle=strokeColor||"#000";
    cxt.stroke();
    cxt.restore();
}  
/**该方法用来绘制一个有填充色的圆角矩形
*@param cxt:canvas的上下文环境
*@param x:左上角x轴坐标
*@param y:左上角y轴坐标
*@param width:矩形的宽度
*@param height:矩形的高度
*@param radius:圆的半径
*@param fillColor:填充颜色
**/
function fillRoundRect(cxt,x,y,width,height,radius,/*optional*/fillColor){
    //圆的直径必然要小于矩形的宽高
    if(2*radius>width || 2*radius>height){return false;}  
    cxt.save();
    cxt.translate(x,y);
    //绘制圆角矩形的各个边
    drawRoundRectPath(cxt,width,height,radius);
    cxt.fillStyle=fillColor||"#000";//若是给定了值就用给定的值否则给予默认值
    cxt.fill();
    cxt.restore();
}  
function drawRoundRectPath(cxt,width,height,radius){
    cxt.beginPath(0);
    //从右下角顺时针绘制,弧度从0到1/2PI
    cxt.arc(width-radius,height-radius,radius,0,Math.PI/2);  
    //矩形下边线
    cxt.lineTo(radius,height);  
    //左下角圆弧,弧度从1/2PI到PI
    cxt.arc(radius,height-radius,radius,Math.PI/2,Math.PI);  
    //矩形左边线
    cxt.lineTo(0,radius);  
    //左上角圆弧,弧度从PI到3/2PI
    cxt.arc(radius,radius,radius,Math.PI,Math.PI*3/2);  
    //上边线
    cxt.lineTo(width-radius,0);  
    //右上角圆弧
    cxt.arc(width-radius,radius,radius,Math.PI*3/2,Math.PI*2);  
    //右边线
    cxt.lineTo(width,height-radius);
    cxt.closePath();
}  
» 点击阅读原文
html dom 转化成图片踩坑记(canvas toDataURL)的更多相关文章
- vue的html2canvas将dom转化为图片时踩得坑
		
一.html2canvas中图片涉及跨域图片 应用场景:做个投票活动,将参赛者的信息转化成图片截图分享.用户上传图片上传到腾讯云cos桶中,html2canvas只能转换本地资源的图片,涉及跨域的图片 ...
 - Vue + TypeScript + Element 搭建简洁时尚的博客网站及踩坑记
		
前言 本文讲解如何在 Vue 项目中使用 TypeScript 来搭建并开发项目,并在此过程中踩过的坑 . TypeScript 具有类型系统,且是 JavaScript 的超集,TypeScript ...
 - Hook踩坑记:React Hook react-unity-webgl
		
自公司前后分离上手React以来,一个坑一个坑的踩,Class的全生命周期云里雾里,还么屡明白,就抱上了Hook的大腿不松手,确实爽到飞起.修改到Hook的过程基本比较顺畅,直接少了三分之一的代码,组 ...
 - Spark踩坑记——Spark Streaming+Kafka
		
[TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...
 - 【踩坑记】从HybridApp到ReactNative
		
前言 随着移动互联网的兴起,Webapp开始大行其道.大概在15年下半年的时候我接触到了HybridApp.因为当时还没毕业嘛,所以并不清楚自己未来的方向,所以就投入了HybridApp的怀抱. Hy ...
 - Spark踩坑记——从RDD看集群调度
		
[TOC] 前言 在Spark的使用中,性能的调优配置过程中,查阅了很多资料,之前自己总结过两篇小博文Spark踩坑记--初试和Spark踩坑记--数据库(Hbase+Mysql),第一篇概况的归纳了 ...
 - vue踩坑记
		
vue踩坑记 易错点 语法好难啊qwq 不要把'data'写成'date' 在v-html/v-bind中使用vue变量时不需要加变量名 在非vue事件中使用vue中变量时需要加变量名 正确 < ...
 - Spark踩坑记:Spark Streaming+kafka应用及调优
		
前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark streaming从k ...
 - vue 使用html2canvas将DOM转化为图片
		
一.前言 我发现将DOM转化为图片是一个非常常见的需求,而自己手动转是非常麻烦的,于是找到了html2canvas这个插件,既是用得比较多的也是维护得比较好的一个插件. 注意:版本比较多,这里介绍最新 ...
 
随机推荐
- python面试_总结02_代码题
			
- 代码题 1.创建一个函数,接收一个字符串参数,判断其做为Python标识符是否合法. 具体要求: 如果合法则输出 True,否则输出 False. 如果该字符串与Python内置的关键字,或Bif ...
 - (第二章第二部分)TensorFlow框架之读取图片数据
			
系列博客链接: (第二章第一部分)TensorFlow框架之文件读取流程:https://www.cnblogs.com/kongweisi/p/11050302.html 本文概述: 目标 说明图片 ...
 - JVM上篇:类加载子系统
			
JVM类加载 目录 JVM类加载 1.内存结构概述 2.类加载子系统概述 3.类的加载过程 2.1加载 2.2Linking 2.2.1验证(Verify) 2.2.2准备(Prepare) 2.2. ...
 - 矩池云 | 神经网络图像分割:气胸X光片识别案例
			
在上一次肺炎X光片的预测中,我们通过神经网络来识别患者胸部的X光片,用于检测患者是否患有肺炎.这是一个典型的神经网络图像分类在医学领域中的运用. 另外,神经网络的图像分割在医学领域中也有着很重要的用作 ...
 - tp5  多文件上传
			
路由: Route::post('imgs','task/task/uploads'); 控制器代码: // 多文件上传 public function uploads() { //接受参数 $dat ...
 - find: `./folder': No such file or directory 错误处理
			
这是我正在处理的目录的内容: misha@hp-laptop:~/work/c/5$ ls -l total 8 -rw-rw-r-- 1 misha misha 219 May 20 15:37 d ...
 - React学习小结(一)
			
一.React的发展 facebook在构建instagram网站的时候遇见两个问题: 1.数据绑定的时候,大量操作真实dom,性能成本太高 2.网站的数据流向太混乱,不好控制 于是facebook起 ...
 - VS Code配置Python环境
			
Visual Studio Code配置Python环境 目录 Visual Studio Code配置Python环境 1.安装Python环境 2.安装VS Code 2.1 下载 2.2 配置中 ...
 - 使用vscode Container开发调试envoy
			
由于我最近在研究 envoy 这个项目,这是个cpp的项目,对于我这种cpp新人来说还是比较有压力的,感觉处处都是坑,开个引导文章记录一下. 如果要研究 envoy 项目源码,那肯定是需要代码跳转的, ...
 - Linux-timedatectl使用
			
Linux下使用timedatectl命令时间时区操作详解 timedatectl命令对于RHEL / CentOS 7和基于Fedora 21+的分布式系统来说,是一个新工具,它作为systemd系 ...