封面图适配 等比例缩放
//canvasWidth, canvasHeight 是图片要展示的区域宽高 而非整个canvas的实际宽高
const aspectFit = (imageWidth, imageHeight, canvasWidth, canvasHeight) => {
const imageRate = imageWidth / imageHeight;
const canvasRate = canvasWidth / canvasHeight;
let [dx, dy, dw, dh] = [];
if (imageRate >= canvasRate) {
dw = canvasWidth;
dh = canvasWidth / imageRate;
} else {
dh = canvasHeight;
dw = canvasHeight * imageRate;
}
dx = (canvasWidth - dw) / 2;
dy = (canvasHeight - dh) / 2;
return [dx, dy, dw, dh];
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div style="display: none;">
<img id="disCanvas" style="width: 270px;height: 480px;" />
<!-- <div class="share-poster-qrcode"></div> -->
</div>
<button>生成海报</button>
<script type='text/javascript' src='http://cdn.staticfile.org/jquery/2.1.1/jquery.min.js'></script>
<script type="text/javascript" src="http://cdn.staticfile.org/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>
<script>
// js生成二维码
// $(".share-poster-qrcode").qrcode({
// width: 200,
// height: 200,
// text: 'https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E8%82%96%E6%88%98&step_word=&hs=0&pn=4&spn=0&di=130790&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=2&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=-1&cs=1242611061%2C961778257&os=2885154884%2C2812315772&simid=4182049253%2C418573008&adpicid=0&lpn=0&ln=1740&fr=&fmq=1611824526965_R&fm=result&ic=0&s=undefined&hd=0&latest=0©right=0&se=&sme=&tab=0&width=&height=&face=undefined&ist=&jit=&cg=&bdtype=0&oriquery=&objurl=https%3A%2F%2Fgimg2.baidu.com%2Fimage_search%2Fsrc%3Dhttp%3A%2F%2Finews.gtimg.com%2Fnewsapp_match%2F0%2F11013045682%2F0.jpg%26refer%3Dhttp%3A%2F%2Finews.gtimg.com%26app%3D2002%26size%3Df9999%2C10000%26q%3Da80%26n%3D0%26g%3D0n%26fmt%3Djpeg%3Fsec%3D1614416531%26t%3Dfe8f2ca315ea3ac64c26013bccf72365&fromurl=ippr_z2C%24qAzdH3FAzdH3Fh7wtkw5_z%26e3Bqq_z%26e3Bv54AzdH3FfAzdH3Fdadaa8amAaLGlZaa&gsm=5&rpstart=0&rpnum=0&islist=&querylist=&force=undefined', //内容
// typeNumber: 0, //计算模式
// correctLevel: 1, //二维码纠错级别
// background: "#ffffff", //背景颜色
// foreground: "#000000", //二维码颜色
// // src: '__PUBLIC__/Home/Images/chat-photo.jpg', //logo图片
// toImg: true //是否转化为图片,默认为false
// });
let goodsImage = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fcdn.duitang.com%2Fuploads%2Fitem%2F201211%2F25%2F20121125163420_33unS.jpeg&refer=http%3A%2F%2Fcdn.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1614416310&t=45f42114f1ede684e69f65a13b2ffc34', goods_title ='我是标题', goods_dis_price = '330.00';
let sharePosterObj = {
bgurl: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Finews.gtimg.com%2Fnewsapp_match%2F0%2F11013045682%2F0.jpg&refer=http%3A%2F%2Finews.gtimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1614416531&t=fe8f2ca315ea3ac64c26013bccf72365",
styleData: {
//商品图片
goods_pic: {
x: 0,
y: 0,
width: 540,
height: 540,
rectX: 0,
rectY: 0,
rectW: 540,
rectH: 540
},
//商品名称
goods_title: {
x: 22,
y: 572,
color: "#333333",
fontSize: 20
},
//展示价格单位
goods_dis_unit: {
x: 22,
y: 478,
color: "#FF0000",
fontSize: 22
},
//展示价格内容
goods_dis_price: {
x: 42,
y: 478,
color: "#FF0000",
fontSize: 44
},
//二维码
qrcode: {
x: 190,
y: 738,
width: 158,
height: 158
},
},
draw: function () {
// 创建画布
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
canvas.width = 540;
canvas.height = 960;
let cardBg = new Image();
cardBg.crossOrigin = 'Anonymous';
cardBg.setAttribute("crossOrigin", 'Anonymous');
cardBg.onload = () => {
let lineHeightIndex = 0;
let drawTxt = '';
let drawLine = 1;
let drawIndex = 0, ident = 1;
let lineMaxWidth = 488;
ctx.drawImage(cardBg, 0, 0, canvas.width, canvas.height);
//商品名称
ctx.save();
ctx.fillStyle = this.styleData.goods_title.color;
ctx.font = `${this.styleData.goods_title.fontSize}px Microsoft YaHei`;
this.styleData.goods_title.y = 572;
if (ctx.measureText(goods_title).width <= lineMaxWidth) {
ctx.fillText(goods_title, this.styleData.goods_title.x, this.styleData.goods_title.y);
} else {
for (var i = 0; i < goods_title.length; i++) {
drawTxt += goods_title[i];
if (ctx.measureText(drawTxt).width >= lineMaxWidth) {
if (lineHeightIndex >= 0 && lineHeightIndex < ident) {
ctx.fillText(goods_title.substring(drawIndex, i + 1), this.styleData.goods_title.x, this.styleData.goods_title.y);
drawIndex = i + 1;
drawLine += 1;
this.styleData.goods_title.y += 30;
drawTxt = '';
lineHeightIndex += 1;
} else if (lineHeightIndex == ident) {
let txt_content_t = goods_title.substring(drawIndex);
txt_content_t = txt_content_t.slice(0, 22) + '...';
ctx.fillText(txt_content_t, this.styleData.goods_title.x, this.styleData.goods_title.y);
break;
}
// }
} else {
// 内容绘制完毕,但是剩下的内容宽度不到lineMaxWidth
if (i === goods_title.length - 1 && lineHeightIndex < ident * 1 + 1) {
if (lineHeightIndex == 0) {
ctx.fillText(goods_title.substring(drawIndex), this.styleData.goods_title.x, this.styleData.goods_title.y);
} else {
let txt_content_t = goods_title.substring(drawIndex);
// txt_content_t = txt_content_t.slice(0,10) + '...';
ctx.fillText(txt_content_t, this.styleData.goods_title.x, this.styleData.goods_title.y);
break;
}
}
}
}
}
ctx.restore();
let prizeY = 572;
if (lineHeightIndex == 1) {
prizeY += 30;
}
//价格单位
ctx.save();
ctx.fillStyle = this.styleData.goods_dis_unit.color;
ctx.font = `bold ${this.styleData.goods_dis_unit.fontSize}px PingFang SC`;
let goods_dis_unit = '¥';
ctx.fillText(goods_dis_unit, this.styleData.goods_dis_unit.x, prizeY + 60);
ctx.restore();
//价格内容
ctx.save();
ctx.fillStyle = this.styleData.goods_dis_price.color;
ctx.font = `bold ${this.styleData.goods_dis_price.fontSize}px PingFang SC`;
ctx.fillText(goods_dis_price, this.styleData.goods_dis_price.x, prizeY + 60);
ctx.restore();
let goodsObj = new Image();//商品图片
goodsObj.crossOrigin = 'Anonymous';
goodsObj.setAttribute("crossOrigin", 'Anonymous');
goodsObj.onload = () => {
let qrObj = new Image();//二维码
qrObj.crossOrigin = 'Anonymous';
qrObj.setAttribute("crossOrigin", 'Anonymous');
// ctx.save();
ctx.fillRect(this.styleData.goods_pic.rectX, this.styleData.goods_pic.rectY, this.styleData.goods_pic.rectW, this.styleData.goods_pic.rectH);
ctx.drawImage(goodsObj, this.styleData.goods_pic.x, this.styleData.goods_pic.y, this.styleData.goods_pic.width, this.styleData.goods_pic.height);
$('#disCanvas').attr('src', canvas.toDataURL('image/jpeg')).attr('complete', 'complete');
// ctx.restore();
// qrObj.onload = () => {
// // ctx.save();
// ctx.fillRect(this.styleData.qrcode.rectX, this.styleData.qrcode.rectY, this.styleData.qrcode.rectW, this.styleData.qrcode.rectH);
// ctx.drawImage(qrObj, this.styleData.qrcode.x, this.styleData.qrcode.y, this.styleData.qrcode.width, this.styleData.qrcode.height);
// // ctx.restore();
// $('#disCanvas').attr('src', canvas.toDataURL('image/jpeg')).attr('complete', 'complete');
// }
// qrObj.src = $('.share-poster-qrcode img').attr('src');
}
goodsObj.src = goodsImage;
}
cardBg.src = this.bgurl;
}
};
$('button').on('click',function(){
$('div').show();
sharePosterObj.draw();
})
</script>
</body>
</html>
遇到的问题:生成的二维码跟图片内容合不到一个canvas里面,具体原因还没找到,看页面元素,二维码是一个canvas元素,并不是一个普通的图片