项目需求要求,需要多张图片动态合成一张,且每个图片都有圆角。具体效果如下所示:
解决思路:先动态生成每个圆角的图片,然后把每个圆角的图片合成一张图。需要使用的方法主要是:canvas里的clip drawIamge promise 以及图片的动态js加载
- drawImage(img,x,y,width,height),主要是用来绘制图像,也是最关键实现的代码之一。
- clip() 主要是用来裁切圆角,先用画出一个正方形的圆角图片,然后裁切。
- new Image() 去动态加载图片资源
第一步,先把单张的原始图处理成圆角的图片,主要代码如下:
//画出矩形圆角
function drawRoundRect(ctx,x,y,w,h,r){
ctx.beginPath();
ctx.arc(x+r,y+r,r,Math.PI,Math.PI*3/2);
ctx.lineTo(w-r+x,y)
ctx.arc(w-r+x,r+y,r,Math.PI*3/2,Math.PI*2)
ctx.lineTo(w+x,h+y-r)
ctx.arc(w-r+x,h-r+y,r,0,Math.PI/2)
ctx.lineTo(r+x,h+y)
ctx.arc(r+x,h-r+y,r,Math.PI/2,Math.PI);
ctx.closePath();
}
//动态生成裁切图
window.onload=function(){
var img = new Image();
img.crossOrigin = "anonymous";
img.src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRIIgaOFwohofaftXTSUPZmpKblrpSrlnHDLbq1y3HQlA&s";
var canvas=document.getElementById('canvas');
canvas.width=500;
canvas.height=500;
var ctx =canvas.getContext("2d");
ctx.fillStyle="#fff";
ctx.fillRect(0,0,500,500);
drawRoundRect(ctx,200,200,200,200,25);
ctx.strokeStyle="#000";
ctx.stroke();
ctx.clip()
ctx.drawImage(img, 200,200,200,200);
document.querySelector('img').src=canvas.toDataURL('image/png', 0.92)
}
复制代码
生成效果如下:
第二步,把裁切的图片进行合并,主要代码如下:
// 设置默认对象
var defaultOptions = {
format: 'image/png',
quality: 0.92,
};
// 返回一个 Promise对象进行处理
var mergeImages = function (sources, options) {
if ( sources === void 0 ) sources = [];
if ( options === void 0 ) options = {};
return new Promise(function (resolve) {
options = Object.assign({}, defaultOptions, options);
var canvas = options.Canvas ? new options.Canvas() : window.document.createElement('canvas');
var Image = options.Image || window.Image;
// 图片加载的时候,去获取图片
var images = sources.map(function (source) { return new Promise(function (resolve, reject) {
if (source.constructor.name !== 'Object') {
source = { src: source };
}
// 图片加载完后Resolve
var img = new Image();
img.crossOrigin = "anonymous";//支持跨域请求资源
img.onerror = function () { return reject(new Error('Couldn\'t load image')); };
img.onload = function () { return resolve(Object.assign({}, source, { img: img })); };
img.src = source.src;
}); });
// 获取画布对象
var ctx = canvas.getContext('2d');
// 当所有图片通过js请求结束后,去在画布画出图片
resolve(Promise.all(images)
.then(function (images) {
var getSize = function (dim) { return options[dim] || Math.max.apply(Math, images.map(function (image) { return image.img[dim]; })); };
canvas.width = getSize('width');
canvas.height = getSize('height');
// 在画布上画图
images.forEach(function (image) {
ctx.globalAlpha = image.opacity ? image.opacity : 1;
return ctx.drawImage(image.img, image.x || 0, image.y || 0,image.w||0,image.h||0);
});
if (options.Canvas && options.format === 'image/jpeg') {
return new Promise(function (resolve, reject) {
canvas.toDataURL(options.format, {
quality: options.quality,
progressive: false
}, function (err, jpeg) {
if (err) {
reject(err);
return;
}
resolve(jpeg);
});
});
}
// 所有异步结束后,生成合并图片
return canvas.toDataURL(options.format, options.quality);
}));
});
};
//调用对象生成合并图,举例如下
mergeImages([{src:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRIIgaOFwohofaftXTSUPZmpKblrpSrlnHDLbq1y3HQlA&s',x:0,y:0,w:100,h:100},
{src:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRIIgaOFwohofaftXTSUPZmpKblrpSrlnHDLbq1y3HQlA&s',x:200,y:200,w:100,h:100}],{width:600,height:600})
.then(b64 => document.querySelector('img').src = b64);
复制代码
<img src="" alt="">
复制代码