canva怎么组合_教你使用Canvas合成图片

本文介绍了如何利用HTML5的Canvas实现动态图片合成功能,包括Canvas的基本原理、编码实践和一个可复用的JS插件示例。通过示例代码展示了如何将多张图片绘制到Canvas并导出为一张图片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前写过一篇有关Canvas图片处理的文章,主要说的是用HTML5中的Canvas实现类似PS中的滤镜功能,而今天我们继续说说这强大的Canvas,看看如何用它来实现PS中的图片合成功能。

一、使用场景

图片合成的使用场景是非常广的,虽说强大的PS能将任意图片组合在一起,但它也只能实现固定的几张图片的合成,而Canvas则能动态地将各种不同的图片合为一张图片。

那么,何为动态合成呢?

比如,我们要将用户的头像合到另一张图片上,这时候因为用户是不确定的,不同用户的头像不同,所以我们肯定不能用PS来做这件事,这时候就是Canvas大显身手的时候了。

二、基本原理

HTML5给我们提供了一个很好的图像处理神器Canvas,想要合成图片,我们首先得将图片按照一定顺序、大小和位置一张张绘制到Canvas画布中去,最后再将整个Canvas导出为图片。

84c1d79dbefc

Canvas图片合成

三、编码实践

1、创建Canvas画布

let canvas = document.createElement('canvas'),

ctx = canvas.getContext('2d');

canvas.width = 800;

canvas.height = 800;

2、绘制图片至Canvas

let img1 = new Image(),

img2 = new Image();

img1.src = './images/1.jpg';

img2.src = './images/2.jpg';

// 加载img1

let pm1 = new Promise((res,rej)=>{

img1.onload = ()=>{

res();

}

});

// 加载img2

let pm2 = new Promise((res,rej)=>{

img2.onload = ()=>{

res();

}

});

// 两张图片都加载完成后绘制于Canva中

let drawAllImg = Promise.all([pm1, pm2]).then((res)=>{

ctx.drawImage(img2, 0, 0, 400, 533);

ctx.drawImage(img1, 0, 0, 100, 100);

});

这里我分别绘制了1.jpg和2.jpg两张图片于Canvas画布中,由于图片需要先从本地加载才能进行绘制,所以这里我使用了onload()方法和Promise对象(详见ES6异步编程之Promise(一)和ES6异步编程之Promise(二)

),其中Promise对象中的all()方法是为了等两张图片全部加载完后在执行后续操作。

由于我们现在创建的Canvas还未添加到DOM中,所以若是想要看现在的Canvas情况得先加上下面这句:

document.body.appendChild(canvas);

当然,实际若是只想要合成图片的话就没必要加上这句了,在离屏Canvas(即手动创建的Canvas但并未添加至DOM中)上绘制即可。

3、将Canvas导出为图片

drawAllImg.then(()=>{

let outputImg = new Image();

outputImg.src = ctx.canvas.toDataURL();

document.body.appendChild(outputImg);

});

4、整合代码,最终形成可复用的JS插件

// 图片合成插件

class ImgMerge {

constructor(imgs = [], options){

// 图片数组默认配置项

let defaultImgsItem = {

url: '',

x: 0,

y: 0

};

// 导出图片的格式与压缩程度默认配置项

let defaultOpts = {

type: 'image/jpeg',

compress: 1

};

try {

imgs.forEach((item,i,arr) => {

arr[i] = Object.assign({},defaultImgsItem,item)

});

}catch (e) {

throw '请传入一个正确的对象数组作为参数';

}

this.imgs = imgs; // 图片数组配置项

this.opts = Object.assign({},defaultOpts,options); // 其他配置项

this.imgObjs = []; // 图片对象数组

this.createCanvas(); // 创建画布

return this.outputImg(); // 导出图片

}

// 创建画布

createCanvas(){

let canvas = document.createElement('canvas'),

ctx = canvas.getContext('2d');

let w = this.imgs[0].width, h = this.imgs[0].height;

if(!w){

throw '第一张图片宽度未设置';

}

if(!h){

throw '第一张图片高度未设置';

}

canvas.width = w;

canvas.height = h;

this.ctx = ctx;

}

// 绘制图片

drawImg(i){

let img = new Image();

img.src = this.imgs[i].url;

this.imgObjs.push(img);

return new Promise((resolve)=>{

img.onload = resolve;

});

}

// 导出图片

outputImg(){

let imgArr = [];

// 将单张图片的Promise对象存入数组

this.imgs.forEach((item,i) => {

imgArr.push(this.drawImg(i));

});

// 所有图片加载成功后将图片绘制于Canvas中,后将Canvas导出为图片

return Promise.all(imgArr).then(()=>{

this.imgs.forEach((item,i) => {

let drawPara = [this.imgObjs[i], this.imgs[i].x, this.imgs[i].y];

// 此处判断参数中图片是否设置了宽高,若宽高均设置,则绘制已设置的宽高,否则按照图片默认宽高绘制

if(this.imgs[i].width && this.imgs[i].height){

drawPara.push(this.imgs[i].width, this.imgs[i].height);

}

this.ctx.drawImage(...drawPara);

});

// 以base64格式导出图片

return Promise.resolve(this.ctx.canvas.toDataURL(this.opts.type),this.opts.compress);

});

}

}

window.ImgMerge = ImgMerge; // 可用于全局引用

export default ImgMerge; // 可用于模块化引用

然后就可以轻松地使用该插件了。

import ImgMerge from './imgMerge.js';

window.onload = function () {

let imgMerge = new ImgMerge([

{

url: require('../images/bg.jpg'),

width: 640,

height: 1169

},

{

url: require('../images/1.jpg'),

width: 200,

height: 200

}

]);

imgMerge.then(img => {

let mergeImg = new Image();

mergeImg.src = img;

mergeImg.onload = () => {

document.body.appendChild(mergeImg);

};

});

};

相关推荐

结束语

本文通过实际案例主要讲述了如何通过Canvas将多张图片合成为单张图片,同时也展示了由ES6编写的面向对象的JS插件代码,大家如果有兴趣可尝试将文字合成功能也添加进去,如果理解了本文方法之后,其实文字合成到图片上也是非常简单的,仅仅添加个方法和修改下配置项就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值