如何简化 Canvas 图片绘制

前言

目前全部的 APP 或者 web 页面均可以直接分享到朋友圈,从朋友圈看到一条分享动态,很难区别这条动态是公众号文章,仍是一支 H5 的连接。javascript

相比之下,在朋友圈发一张图片,会更容易吸引朋友的注意,内容也能够更直接的曝光。同时微信能够识别图片中的二维码,又能起到回流做用。java

而单一的图片又会缺少趣味性。所以,根据用户的选择,使用 Canvas 生成自定义的海报图,成为了目前主流的 H5 类别。git

,使用 Canvas 生成自定义的海报图

如何使用 Canvas 绘制图片

了解如下 3 个步骤,就能够完成绘制了:github

1. 初始化 Canvas 并获取 Canvas 绘制的上下文:

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
复制代码

2. 绘制图片、文字:

ctx.drawImage(imageElement,0,0);
ctx.fillText("Hello world", 10, 50);
复制代码

3. 绘制结束,导出 base64:

const imageBase64 = canvas.toDataURL();
复制代码

实际绘制中存在的问题

以上的步骤为绘制的关键代码,但实际绘制过程当中仍是会存在一些问题的:web

1. 图片须要在 load 以后才能绘制:

const imageElement = new Image();
imageElement.onload = ()=>{
    ctx.drawImage(imageElement,0,0);
}
imageElement.src = imageAssetsURL;
复制代码

那若是要绘制两张图片呢?npm

const imageElement = new Image();
imageElement.onload = ()=>{
    ctx.drawImage(imageElement,0,0);
    
    // 第一张绘制结束,开始绘制第二张图片
    const imageElementSecond = new Image();
    imageElementSecond.onload = ()=>{
        ctx.drawImage(imageElementSecond,0,0);
    }
    imageElementSecond.src = imageAssetsURLSecond;
}
imageElement.src = imageAssetsURL;
复制代码

那若是要绘制 10 张图片呢?canvas

2. 图片加载未优化:

使用回调,第二张图片,只能等第一张图片绘制完成后才能开始加载。promise

图片资源是否是能够同时开始加载?bash

3. 文本绘制语法繁杂:

ctx.save();
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.font = "36px Arial";
ctx.fillStyle = "#ffffff";
ctx.fillText("Hello world", 10, 50);
ctx.restore();
复制代码

须要记忆的语法不少,若是要文本要加粗怎么设置?微信

简化并优化绘制过程

1. 简化回调

load 全部图片,图片加载完成后统一绘制。

2. 优化加载

使用 Promise 异步加载图片,让全部图片同时开始加载:

function loadImages(...assetsArr){
    const imageArr = [];
    const promiseArr = [];
    assetsArr.forEach((item,index)=>{
        promiseArr.push(new Promise((resolve)=>{
            const image = new Image();
            imageArr.push(image);
            image.onload = ()=>{
                resolve(imageArr)
            };
            image.src = assetsArr[index];
        }));
    });
    return Promise.all(promiseArr);
}
复制代码

3. 简化文本绘制

将文本绘制的内容、字体、行高等全部的基本样式封装成方法,经过修改对象参数来代替语法规则:

// 初始化默认值
const defaultFontStyle = {
    fontStyle:'normal',
    fontVariant:'normal',
    fontWeight:'normal',
    fontSize: 30,
    lineHeight: 'normal',
    fontFamily: 'Arial',
    left: 0,
    top: 300,
    maxWidth:undefined,
    content:'',
    textAlign:'start',
    textBaseline:'alphabetic',
    direction:'inherit',
    color: '#000000',
};

// 将文本绘制语法封装
drawText(obj){
    const prop = Object.assign({},defaultFontStyle,obj)
    ctx.save();
    ctx.fillStyle = prop.color;
    ctx.font = `${prop.fontStyle} ${prop.fontVariant} ${prop.fontWeight} ${prop}px/${prop.lineHeight} ${prop.fontFamily}`;
    ctx.textBaseline = prop.textBaseline;
    ctx.textAlign = prop.textAlign;
    ctx.direction = prop.direction;
    ctx.fillText(item,prop.left,prop.top,prop.maxWidth);
    ctx.restore();
}

// 使用
drawText({content:'Hello world'});
复制代码

高级进阶

在以上简单的封装基础上,咱们其实能够加入一些更高级的用法,好比:

  1. 绘制圆形图片(好比头像);
  2. 获取绘制的文本宽度;
  3. 文本自动换行(原生 Canvas 绘制无自动换行功能);
  4. 文本域旋转等。

总结

  1. Canvas 图片绘制基本流程并不复杂,若是绘制的图片与文本数量较小,能够经过 Canvas 原生方法来实现;
  2. 若是绘制图片较多,建议使用 Promise 异步加载图片;
  3. 文本语法较多,但全部涉及到的样式是有限的,能够经过封装方法来减小记忆;
  4. H5 海报绘制基本上只包含 图片 和 文本 绘制,能够将经常使用方法封装成组件,方便重复使用。

封装组件

本文提到的内容,包括高级进阶,能够 点此 查看源码。

若是须要直接使用,能够经过 npm 直接安装,使用说明以下:

npm 安装

npm i create-picture --save
复制代码

使用

import CreatePicture from 'create-picture';

// 初始化
const cp = new CreatePicture();

// 初始化(传参)
const cp:CreatePicture = new CreatePicture({width:750,height:1448});

// 绘制图片,参数1为图片路径,其余参数与 CanvasRenderingContext2D.drawImage() 参数相同
cp.drawImage(require('../assets/save_bg.jpg'),0,0);

// 绘制文本
cp.drawText({content:'文本'});

// 绘制文本,获取文字宽度
const textWidth = cp.drawText({
    content:'文本',
    fontSize: 30,
    top: 300,
    color: '#ffffff',
});

// 获取合成图
cp.getPicture().then((picture)=>{
    // picture 为合成的 base 64
});
复制代码

相关连接

相关文章
相关标签/搜索