在日常uniapp和小程序开发,每当工作须要绘制一个海报,都让我很头疼,我须要将我以前的代码(downloadFile异步封装,ctx绘制办法....)复制过去,而后在一个个引入,又或者找不到了,又去百度(而后这漫长的一天将这么节约了,所以为了缩小引入这些芜杂的工具我做了一个专门用于绘制海报的一个工具库,这样就能够缩小我的工作量啦(hhh又能够摸鱼划水了。上面是插件库的介绍,大家能够看看,目前性能都曾经全副欠缺了

绘制海报工具简述

  • 创立绘制海报canvas矩形办法,内置了图片绘制,圆角矩形绘制,换行字体绘制等办法。
  • 靠近原生开发体验,上手快,只需思考业务逻辑,而不必思考其余问题。
  • 领有良好的语法架构,不会在绘制uni/wx矩形时陷入回调天堂。
  • 反对原生小程序,与uniapp多端利用。当是环境为原生小程序时,主动切换为性能更好的type2d绘制形式。
  • 将简单的逻辑组合为简略的办法,扩展性强,可应用 use|useCtx 引入扩大。
  • 反对typescript,反对vue3模板,具体应用参考 useDrawPoster。

api文档:u-draw-poster

插件市场:dcloud/u-draw-poster

npm 装置插件

npm i --save-dev u-draw-poster

开启对该插件的uni条件编译(重要)

// vue.config.jsmodule.exports = {  transpileDependencies: ['u-draw-poster'],};

1. 创立海报绘制工具

<!-- #ifdef MP-WEIXIN --><canvas id="canvas" type="2d" style="width:100rpx; height:100rpx" /><!-- #endif --><!-- #ifndef MP-WEIXIN --><canvas canvas-id="canvas" id="canvas" style="width:100rpx; height:100rpx" /><!-- #endif -->
// 留神:如果应用HBuilder引入, 须要引入 '@/js_sdk/u-draw-poster'import DrawPoster from 'u-draw-poster'async onReady() { // 传入选择器, 初始化绘制工具(留神, 不须要传入#符号) 当微信小程序时, 将主动启用type2d绘制 const dp = await DrawPoster.build("canvas")   }

2. 设置画布尺寸

// 设置长高为100px的矩形宽高dp.canvas.width = 100dp.canvas.height = 100

3. 绘制任意内容

// 绘制背景与文字dp.draw((ctx) => {    ctx.fillStyle = "#F4F4F4";    ctx.fillRect(0, 0, dp.canvas.width, dp.canvas.height);    ctx.textBaseline = "top";    ctx.textAlign = "start";    ctx.fillStyle = "white";    ctx.font = `bold ${22}px sans-serif`;    ctx.fillText('周先生', dp.canvas.width/2, 38.5);})// 绘制图片内容dp.draw(async (ctx) => {    //.......})

值得注意的是, draw办法会主动的执行ctx.save/ctx.restore, 不须要人为操纵绘画栈.

dp.draw((ctx) => {/* ... */})// 相当于ctx.save()/* ... */ctx.restore()

4. 进行绘制

dp.draw并不会马上绘制,只是将该工作增加到了工作栈,须要应用dp.awaitCreate函数进行绘制,该函数在绘制结束后将弹出所有工作。
dp.awaitCreate在非2d绘画中,执行绘画工作结束后,将主动执行ctx.draw办法,并在draw绘画才算异步完结。

dp.draw((ctx) => {/* ... */})dp.draw(async (ctx) => {/* ... */})// 因为每个工作都有可能会有异步的绘制工作, 所以得须要应用await期待绘制const result = await dp.awaitCreate();// 绘制胜利将返回每个工作的绘制情况组成的数组console.log("draw绘制情况:", result); // draw绘制情况: [true]

5. 生成图片本地地址

如须要保留为图片时,能够应用dp.createImgUrl 进行创立图片本地地址,在由wxuniapi进行保留。

dp.draw(async (ctx) => {/* ... */})const result = await dp.awaitCreate();const posterImgUrl = await dp.createImagePath();console.log("draw绘制情况:", result); // [true]console.log("绘制生成本地地址:", posterImgUrl); // ...tmp...

你也能够不应用dp.awaitCreate办法,当调用dp.createImagePath时会自动检测工作列表,如果有则执行绘制工作后在创立地址。

dp.draw(async (ctx) => {/* ... */})// 跳过drawPoster.awaitCreate间接生成地址const posterImgUrl = await dp.createImagePath();console.log("绘制生成本地地址:", posterImgUrl);

绘制扩大 API

drawPoster在创立时,会主动的向ctx(画笔)增加/笼罩扩大办法,以便构建海报矩形。

dp.draw(async (ctx) => {  // ctx.drawImage | ctx.drawRoundImage | ctx.fillWarpText | ....})

绘制图片(ctx.drawImage)

ctx.drawImage(url, x, y, w, h)

drawPoster绘制图片与原生绘制不雷同,ctx.drawImage外部曾经内置了downloadFile,只须要传入本地/网络地址即可。反对2d非2d绘制,绘制形式统一。须要await期待绘制。

留神:当绘制环境为H5时,uniapp应用本地图片绘画时不要用尺寸较大的图片,不然会在创立图片时生成失败。

dp.draw(async (ctx)=>{    const url = "/static/logo.png"    // const url = "https://...."    await ctx.drawImage(url, 88, 174.94, 198.98, 36);})
参数形容
url网络图片地址,或本地/static中图片门路。
x,y图片的左上角的坐标。
width,height图片的大小。

换行字体(ctx.fillWarpText)

ctx.fillWarpText(options)

传入配置对象,绘制换行字体,以下为可配置项。

interface FillWarpTextOpts {  // 绘制字符串, 必传项  text: string;  // 绘制最长高度, 默认100px  maxWidth?: number;  // 绘制行高, 默认取以后字体的默认宽度  lineHeight?: number;  // 绘制行数量, 默认限度为2层  layer?: number;  // 绘制x轴, 默认0  x?: number;  // 绘制y轴, 默认0  y?: number;  // 设置换行字符, 默认为空, 如设置, maxWidth|layer 将会生效  splitText?: string;  // 是否不马上进行绘制  notFillText?: boolean;}// 当 `notFillText` 为 `true` 时,则不进行绘制,该函数将返回一个绘制信息队列// 用于代表每行字体所对应的绘制信息, 以下是返回的构造信息,你能够用于计算该// 换行字体的宽度,也你能够应用array.forEach与ctx.fillText进行绘制。[  { text: string, y: number, x: number}  // ....]

圆角矩形(ctx.fillRoundRect)

ctx.fillWarpText(x, y, w, h, r)

dp.draw(async (ctx)=>{   // 设置矩形色彩   ctx.fillStyle = "#fff";   // 进行绘制   ctx.fillRoundRect(15, 179, 345, 365.5, 10);})
参数形容
x,y矩形的左上角的坐标。
width,height矩形的大小。
r矩形的弧度半径。

圆角矩形边框(ctx.strokeRoundRect)

ctx.strokeRoundRect(x, y, w, h, r)

参数形容
x,y矩形的左上角的坐标。
width,height矩形的大小。
r矩形的弧度半径。

圆角图片(ctx.drawRoundImage)

ctx.drawRoundImage(url, x, y, w, h, r)

dp.draw(async (ctx) => {  const url = "static/logo.png"  // const url = "https://...."  await ctx.drawRoundImage(url, 0, 0, 100, 100, 50);});
参数形容
url网络图片地址,或本地/static中图片门路。
x,y图片的左上角的坐标。
width,height图片的大小。
r图片的弧度半径。

绘制二维码(ctx.drawQrCode)

生成二维码扩大,源码应用了 uQRCode 并改变了一下,该文件比拟大,所以作为扩大插件应用,应用时得先引入插件。

// 留神:如果应用HBuilder引入, 须要引入 '@/js_sdk/u-draw-poster'import DrawPoster from 'u-draw-poster'import drawQrCode from 'u-draw-poster/dist/extends/draw-qr-code'// 引入绘制二维码插件DrawPoster.useCtx(drawQrCode)async onReady() { const dp = await DrawPoster.build("canvas") dp.canvas.width = 200; dp.canvas.height = 200 dp.draw(ctx=>{   ctx.drawQrCode({    x: (dp.canvas.width / 2) - 50,    y: (dp.canvas.height / 2) - 50,    text: "http://www.baidu.com",    size: 100,  }); })}
参数类型必填阐明
xnumber程度方向偏移长度
ynumber垂直方向偏移长度
textString二维码内容
sizeNumber二维码尺寸大小
marginNumber边距,二维码理论尺寸会依据所设边距值进行缩放调整(默认:0
backgroundColorString背景色,若设置为通明背景, fileType 需设置为 'png' , 而后设置背景色为 'rgba(255,255,255,0)' 即可(默认:'#ffffff'
foregroundColorString前景色(默认:'#000000'
errorCorrectLevelNumber纠错等级,蕴含 errorCorrectLevel.LerrorCorrectLevel.MerrorCorrectLevel.QerrorCorrectLevel.H 四个级别,L: 最大 7% 的谬误可能被纠正;M: 最大 15% 的谬误可能被纠正;Q: 最大 25% 的谬误可能被纠正;H: 最大 30% 的谬误可能被纠正。

全局实例 API

绘画构建(DrawPoster.build)

DrawPoster.build(string|object)

初始化构建绘制工具,传入查问字符串与配置对象,当配置字符串时,则间接查问该字符串的canvas,当配置对象时,object.selector则为必选项,以下是options的配置项,须要留神的是,返回值为Promise,返回绘制构建对象dp

/** DrawPoster.build 构建配置 */interface DrawPosterBuildOpts {    // 查问字符串(必须), 留神不要写错对应canvas id, 不须要传入#符号    selector: string;    // 选取组件范畴    componentThis?: any;    // 类型为2d绘制, 默认开启, 在微信小程序的时候动静加载    type2d?: boolean;    // 是否在绘制的过程中, 显示加载框, 默认敞开    loading?: boolean,    // 当存在绘制图片时, 期待绘画结束的工夫(毫秒),仅在App中失效    drawImageTime?: 100,    // 加载提醒文字    loadingText?: '绘制海报中...',    // 创立图片加载提醒文字    createText?: '生成图片中...'}

多绘画构建(DrawPoster.buildAll)

DrawPoster.buildAll(Array<string|object>)

构建多个绘画工具,传入build函数中参数string | options形成的数组,返回多个绘制工具组成的对象。key为canvasId,value为构建对象。

挂载全局扩大(DrawPoster.use)

DrawPoster.use(object)

传入挂载配置对象,增加全局扩大办法,个别可用于海报绘制模板的封装,在不同页面有一样的海报模板时能够无效的缩小代码量,应用形式如下。

一、在任意地位增加扩大(倡议放在main.js中执行)

import DrawPoster from 'u-draw-poster'// 全局增加绘制集体海报的扩大实现DrawPoster.use({  name: "createMyCardImagePath",  // dp为以后实例, 其余参数为自定义传入参数  handle: async (dp, opts) => {    // ..自定义构建内容..    return await dp.createImagePath()  }})

二、页面中应用自定义扩大

import DrawPoster from 'u-draw-poster'async onReady() { const dp = await DrawPoster.build("canvas") dp.canvas.width = 100; dp.canvas.height = 100 const posterImg = await dp.createMyCardImagePath({/*...*/})}

挂载绘制扩大(DrawPoster.useCtx)

DrawPoster.useCtx(object)

传入挂载配置对象,增加全局绘制扩大办法,用于自定义绘制办法的定义,应用形式如下。

一、在任意地位增加扩大(倡议放在main.js中执行)

// 全局增加绘制二维码的绘画扩大实现DrawPoster.useCtx({  name: "drawQrCode",  // canvas(绘制节点), ctx(绘制画笔), 其余参数为自定义传入参数  handle: async (canvas, ctx, url, x, y, w, h) => {    // ..自定义绘制内容..  },});

二、绘制中应用自定义扩大

dp.draw(ctx=> {  const url = 'http://www.baidu.com'  await ctx.drawQrCode(url, 0, 0, 50, 50) })

绘制节点(dp.canvas)

dp.canvas | dp.canvas.width | dp.canvas.height | ...

dp.canvas为全局的绘制根节点,在微信小程序中领有独享API。在其余端将作为全局宽高容器应用。当dp.createImagePath未传入参数时,默认应用 dp.canvas.width | dp.canvas.height 创立图片,以下是dp.canvas对象中存在的api与属性。

interface Canvas {  width: number;  height: number;  // 残余参数为微信小程序独享API,只有微信小程序才领有的API  // 具体参考微信小程序文档:https://developers.weixin.qq.com/miniprogram/dev/api/canvas/Canvas.html}

创立绘制(dp.draw)

dp.draw(async callback(ctx))

绘制器, 接管执行器函数, 增加到绘制容器中,可改装为异步函数解决图片绘制,也能够为同步函数。

全局画笔(dp.ctx)

dp.ctx

全局绘制画笔,非凡状况能够应用,举荐只应用dp.draw函数进行绘制。

期待绘制(dp.awaitCreate)

dp.awaitCreate()

异步绘制绘制器堆栈,胜利后清空绘制器容器,返回胜利堆栈情况的数组(boolean[])。

进行绘画(dp.stop)

dp.stop()

进行以后绘画栈,调用后将进行dp.awaitCreate |dp.createImagePath 的执行。

创立图片(dp.createImagePath)

dp.createImagePath(options)

创立以后canvas绘制后的本地图片地址,如绘制器堆栈未清空时,会主动调用dp.awaitCreate()清空堆栈。createImagePath 会依据 canvas.widthcanvas.height 进行创立图片。如果你想自定义参数,awaitCreate 办法能够承受一个配置对象,返回图片地址,以下为可配置项。

interface CreateImagePathOptions {  x?: number;  y?: number;  width?: number;  height?: number;  destWidth?: number;  destHeight?: number;}

应用倡议

canvas在海报生成中请当做一个生成工具来对待,它的作用仅是绘制出海报。应把生成失去的资源保留并应用,显示用image图片组件,起因是不便操作,例如调整大小,或是H5端长按保留或辨认,所以canvas应将它放在看不见的中央。不能用display:none;overflow:hidden;暗藏,否则生成空白。这里举荐canvas的暗藏款式代码,该阐明为 uQRCode 提供的阐明,同样u-draw-poster也实用

.canvas-hide {    /* 1 */    position: fixed;    right: 100vw;    bottom: 100vh;    /* 2 */    z-index: -9999;    /* 3 */    opacity: 0;}

常见问题

微信小程序手机浏览空白

微信小程序绘制如果有图片绘制,手机浏览须要在后盾增加downloadFile域名,并须要重启开发者工具。

微信小程序无奈真机调试

https://developers.weixin.qq....

H5 端图片裁剪异样

H5 端绘制两个以上的ctx.drawRoundImage圆角图片时,创立的本地base64显示异样,倡议当环境是h5时,将圆角图片限度为一个,或者uni动静编译展现img标签。

绘制结束后没有成果

留神DrawPoster.build无奈检测你所抉择canvasId的是否正确,所以肯定要确保与canvas-idhtml中的canvas雷同,在小程序端,因为会主动切换为type2d,必须得加上动静编译。

<!-- #ifdef MP-WEIXIN --><canvas id="canvas" type="2d" style="width: 300px; height: 300px" /><!-- #endif --><!-- #ifndef MP-WEIXIN --><canvas canvas-id="canvas" id="canvas" style="width: 300px; height: 300px" /><!-- #endif -->

绘制多个图片加载慢

如果感觉多个图片绘制await加载慢,能够应用Promise.all将一部分不须要解决图层笼罩的图片进行同步绘制。

dp.draw(async (ctx) => {  // // 用户头像  await ctx.drawRoundImage(headImgUrl, 39, 790, 90, 90, 100);  await Promise.all([    ctx.drawImage('/static/logo1.png', 20, 20, 35, 35),    ctx.drawImage('/static/tp.png', 19, 86, 612, 459),    ctx.drawImage('/static/bw.png', 188, 559, 274, 50),    // // 用户二维码    ctx.drawImage(codeImgUrl, 518, 780, 92, 92),  ]);});

须要留神的是:ctx.drawRoundImage不能够放在Promise.all当中,因为ctx.drawRoundImage外部会调用ctx.clip办法,在Promise.all中会与其余图片绘制产生抵触。从而导致圆角生效。

我的博客:Mr.Mao'blog

联系方式:951416545@qq.com