技术使用背景
最开始我是使用了html2canvas插件,从后台获取数据后填充在div中,直接截取屏幕上的该div,但是该插件一个是兼容性不太好,第二个截取图片需要5秒以上,且不包括等待加载其他图片加载的时间(之前页面上有从后台获取到的图片加载失败的情况,那时该插件生成图片花费23秒左右时间,天啦噜~别说用户了,我自己都不想等了!)后面解决了等待图片加载失败的情况后,耗时需4-5秒,倒是能忍受,但是兼容ie 不友好啊,解决了ie promise的问题后,啥错也不报了,但就是截图失败。
所以我还是乖乖的自己用canvas去画了,这个高版ie都支持了吧!但是后面又生出图片跨域问题,ie 10报SecurityError错误。
所以!!需要canvas画的容器里的图片能本地的就本地,从后台来的图片让后台转成base64流传给我,吼吼,问题就这样解决啦!
上代码!
<canvas id="myCanvas"></canvas>
//画矩形
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();
};
//画卡片
function drawImg(bgSrc, index, logoSrc, accountName, ProfitRate, Deposit, Orders, Lots, GenerationTime, callback) {
//背景图,账户编号,账户logo,账户名,利率,本金,单量,手数,生成时间
var width = 750; //宽度
var height = 1334; // 高度
var c = document.getElementById("myCanvas");
c.width = width;
c.height = height;
var ctx = c.getContext("2d");
//需要等图片加载完后再进行后续操作
//bgSrc是本地图,logoSrc是base64流
new imgload(bgSrc, function (bgImg) {
new imgload(logoSrc, function (Img) {
ctx.drawImage(bgImg, 0, 0, width, height); //绘制图像进行拉伸
//右上角矩形框
ctx.beginPath();
ctx.save();
ctx.translate(610, 35);
drawRoundRectPath(ctx, 95, 46, 3);
if (ProfitRate < -4) {
ctx.fillStyle = "#919191";
} else {
ctx.fillStyle = "#f35050";
}
ctx.fill();
ctx.restore();
//右上角文字
ctx.beginPath();
ctx.font = "26px 黑体";
ctx.fillStyle = "#ffffff";
ctx.fillText(index, 618, 70);
ctx.drawImage(Img, 656, 37, 43, 43); //绘制图像进行拉伸
var txtWidth;
//用户名
ctx.beginPath();
ctx.font = "54px 黑体";
//获取动态有样式的数据的宽,让其居中显示
txtWidth = ctx.measureText(accountName.toString()).width;
ctx.fillStyle = "#fff";
ctx.fillText(accountName, 375 - txtWidth / 2, 560);
//月收益
ctx.beginPath();
ctx.font = "34px 黑体";
ctx.fillStyle = "#fff";
ctx.fillText("月 收 益", 303, 624);
//data
ctx.beginPath();
ctx.font = "72px 黑体 bolder";
txtWidth = ctx.measureText((ProfitRate + "%").toString()).width;
ctx.fillStyle = "#f35050";
ctx.fillText((ProfitRate + "%"), 375 - txtWidth / 2, 710);
//ctx.fillText("+9.09%", 245, 710);
//本金
ctx.beginPath();
ctx.font = "32px 黑体 ";
ctx.fillStyle = "#fff";
ctx.fillText("本 金", 122, 825);
//本金data
ctx.beginPath();
ctx.font = "42px 黑体 normal";
txtWidth = ctx.measureText(("$" + Deposit).toString()).width;
ctx.fillStyle = "#f35050";
ctx.fillText(("$" + Deposit), 156 - txtWidth / 2, 880);
//单量
ctx.beginPath();
ctx.font = "32px 黑体 ";
ctx.fillStyle = "#fff";
ctx.fillText("单 量", 341, 825);
//单量data
ctx.beginPath();
ctx.font = "42px 黑体 normal";
txtWidth = ctx.measureText(Orders.toString()).width;
ctx.fillStyle = "#f35050";
ctx.fillText(Orders, 375 - txtWidth / 2, 880);
//手数
ctx.beginPath();
ctx.font = "32px 黑体 ";
ctx.fillStyle = "#fff";
ctx.fillText("手 数", 550, 825);
//手数data
ctx.beginPath();
ctx.font = "42px 黑体 normal";
txtWidth = ctx.measureText(Lots.toString()).width;
ctx.fillStyle = "#f35050";
ctx.fillText(Lots, 582 - txtWidth / 2, 880);
//线条
ctx.beginPath();
ctx.moveTo(264, 793);
ctx.lineTo(264, 891);
ctx.lineWidth = 1; //线的宽度
ctx.strokeStyle = '#e65d5d'; //线的颜色
ctx.lineCap = 'round'; //线的两头圆滑
ctx.stroke();
ctx.beginPath();
ctx.moveTo(491, 793);
ctx.lineTo(491, 891);
ctx.lineWidth = 1; //线的宽度
ctx.strokeStyle = '#e65d5d'; //线的颜色
ctx.lineCap = 'round'; //线的两头圆滑
ctx.stroke();
//时间
ctx.beginPath();
ctx.font = "32px 黑体 ";
txtWidth = ctx.measureText(GenerationTime.toString()).width;
ctx.fillStyle = "#6c6465";
ctx.fillText(GenerationTime, 375 - txtWidth / 2, 995);
//扫码
ctx.beginPath();
ctx.font = "30px 黑体 ";
ctx.fillStyle = "#883d3d";
//ctx.rotate(90 * Math.PI / 180);
var s = "长按扫码";
for (var i = 0; i < s.length; i++) {
ctx.fillText(s[i], 229, 1075 + 35 * i);
}
//下载
ctx.beginPath();
ctx.font = "30px 黑体 ";
ctx.fillStyle = "#883d3d";
s = "下载汇聊";
for (var i = 0; i < s.length; i++) {
ctx.fillText(s[i], 490, 1075 + 35 * i);
}
//30天
ctx.beginPath();
ctx.font = "28px 黑体 ";
ctx.fillStyle = "#6c6465";
ctx.fillText("数据显示为近30天收益", 225, 1261);
//绘制完成,转为图片
setTimeout(function () { //在ios上无法在画完之后取到整个画布内容,加了个settimeout
var src = c.toDataURL("image/png");
callback && callback(src);//获取到src后进行后续操作
}, 0);
});
});
};
function imgload(src, callback) {
var img = new Image();
img.setAttribute("crossOrigin", 'Anonymous');
img.src = src;
img.onload = function () {
callback && callback(img);
}
}
//调用方式
drawImg(bgSrc, index, logoSrc, accountName, data.ProfitRate, data.Deposit, data.Orders, data.Lots, data.GenerationTime, function (imgBase64) {
//拿取imgBase64 进行后续操作,生成的是base64数据哦
//我这里是截取后面的流后ajax传给后台服务器,拿回图片链接的
var i = imgBase64.indexOf(",");
var imgResult = imgBase64.substring(i + 1, imgBase64.length);//这就是去掉头部的纯流
//...
}