封装常用的canvas工具类

canvas绘图工具库

一、引言

一个canvas绘图工具库,在开发小程序时编写的用于绘制图形的工具函数。

二、使用场景

基于最新 Canvas 2D API封装,这个库包含一系列开箱即用的函数,它们非常适用于微信小程序上各种复杂的Canvas绘图场景,如文字、图形、图片的绘制,以及内容的清除和导出等。

三、函数列表:

1 drawAutoWrapText(ctx, x, y, content, maxWidth, lineHeight, fontFamily, fontSize, fontColor, isCenter = false)

该函数用于在canvas上绘制带有自动换行功能的文本内容。
参数描述:

  • ctx: canvas的绘图环境上下文

  • x,y: 文字的起始坐标

  • content: 需要绘制的文本内容

  • maxWidth: 文本内容的最大宽度

  • lineHeight: 文本行的高度

  • fontFamily: 字体家族

  • fontSize: 字体大小

  • fontColor: 字体颜色

  • isCenter(可选): 文本是否居中对齐,默认值为false

2 drawRoundRectPathWithArc(ctx, x, y, width, height, radius)

该函数致力于在canvas上使用arc()方法绘制圆角矩形路径。
参数描述:

  • ctx: canvas的绘图环境上下文

  • x,y: 圆角矩形的左上角的坐标

  • width,height: 圆角矩形的宽和高

  • radius: 圆角的半径参数描述:

3 drawRoundRectPathWithArcTo(ctx, x, y, width, height, radius)

该函数的目标是在canvas上使用arcTo()方法绘制圆角矩形路径。
参数描述:

  • ctx: canvas的绘图环境上下文

  • x,y: 圆角矩形的左上角的坐标

  • width,height: 圆角矩形的宽和高

  • radius: 圆角的半径

4 fillRoundRectPath(ctx, x, y, width, height, radius, color)

这个函数用于填充圆角矩形路径的背景颜色。
参数描述:

  • ctx: canvas的绘图环境上下文

  • x,y: 圆角矩形的左上角的坐标

  • width,height: 圆角矩形的宽和高

  • radius: 圆角的半径

  • color: 需要填充的颜色

5 drawRoundRectImg(ctx, x, y, width, height, radius, img)

该函数专门用于在圆角矩形内填充图片。
参数描述:

  • ctx: canvas的绘图环境上下文

  • x,y: 圆角矩形的左上角的坐标

  • width,height: 圆角矩形的宽和高

  • radius: 圆角的半径

  • img: 需要填充的图片源地址

6 strokeRoundRectPath(ctx, x, y, width, height, radius)

此函数用以在圆角矩形路径上创建一个虚框。
参数描述:

  • ctx: canvas的绘图环境上下文

  • x,y: 圆角矩形的左上角的坐标

  • width,height: 圆角矩形的宽和高

  • radius: 圆角的半径

7 drawCircle(ctx, x, y, radius, startAngle, endAngle, anticlockwise = false)

该函数可以在canvas上绘制一个圆或圆弧。
参数描述:

  • ctx: canvas的绘图环境上下文

  • x,y: 圆的中心坐标

  • radius: 圆的半径

  • startAngle,endAngle: 规定圆弧起始和结束的弧度

  • anticlockwise(可选): 是否逆时针绘制,默认为false

8 clearRect(ctx, x, y, width, height)

该函数可以清除canvas上特定区域的内容。
参数描述:

  • ctx: canvas的绘图环境上下文

  • x,y: 需要清除区域的左上角的坐标

  • width,height: 需要清除的区域的宽和高

9 wxGetImageInfo(url)

此函数 Promise 形式返回,用于异步获取图片信息。
参数描述:

  • url: 需要获取信息的图片的链接

11-1 exportImg(canvas, w, h, calc = 2)

此函数 Promise 形式返回,用于将当前canvas的特定区域导出,并生成指定大小的图片。
参数描述:

  • canvas: 当前的canvas对象

  • w,h: 图片导出的宽和高

  • calc(可选): 图片质量,数值越高质量越好,默认为2,应小于3

11 computeRender(o_w, o_h, r_w)

此函数用于根据原始图片的宽高和渲染的宽度,从而计算出渲染的高度。
参数描述:

  • o_w,o_h: 原始图片的宽和高

  • r_w: 渲染图片的宽度

12 drawImage(canvas, ctx, bannerInfo, x, y, width, height)

此函数 Promise 形式返回,用于在canvas上绘制图片。
参数描述:

  • canvas: 当前的canvas对象

  • ctx: canvas的绘图环境上下文

  • bannerInfo: 包含图片信息的对象,例如图片 path

  • x,y: 图片的起始坐标

  • width,height: 需要绘制的图片的宽和高

参考

canvas | MDN

微信小程序画布教程

/*
 * @Author: 梁佩乐 liangpeile@vchangyi.com
 * @Date: 2023-11-10 16:00:56
 * @LastEditors: 梁佩乐 liangpeile@vchangyi.com
 * @LastEditTime: 2023-11-16 17:41:53
 * @FilePath: \activity-web-wx-app\src\pagesA\canvas-learn\canvas.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
/**
 * 该函数用于在canvas上绘制带有自动换行功能的文本内容。
 * @param {*} ctx: canvas的绘图环境上下文
 * @param {number} x,y : 文字的起始坐标
 * @param {string} content: 需要绘制的文本内容
 * @param {number} maxWidth: 文本内容的最大宽度
 * @param {number} lineHeight: 文本行的高度
 * @param {string} fontFamily: 字体家族
 * @param {number} fontSize: 字体大小
 * @param {string} fontColor: 字体颜色
 * @param {boolean} isCenter(可选): 文本是否居中对齐,默认值为false
 */
function drawAutoWrapText(
  ctx,
  x,
  y,
  content,
  maxWidth,
  lineHeight,
  fontFamily,
  fontSize,
  fontColor,
  isCenter = false
) {
  ctx.font = `${fontSize}px ${fontFamily}`;
  ctx.fillStyle = fontColor;
  if (isCenter) ctx.textAlign = 'center';
  let words = content.split(''); // 将字符串分割成一个个字符
  let line = '';
  for (let n = 0; n < words.length; n++) {
    let testLine = line + words[n];
    let metrics = ctx.measureText(testLine);
    let testWidth = metrics.width;
    if (testWidth > maxWidth && n > 0) {
      ctx.fillText(line, x, y);
      line = words[n];
      y += lineHeight;
    } else {
      line = testLine;
    }
  }
  if (isCenter) ctx.fillText(line, (x + maxWidth) / 2, y);
  if (!isCenter) ctx.fillText(line, x, y);
}

/**
 * 该函数致力于在canvas上使用arc()方法绘制圆角矩形路径。
 * 使用arc()方式绘制弧线 按照canvas的弧度从 0 - 2PI 开始顺时针绘制
 * @param {*} ctx: canvas的绘图环境上下文
 * @param {number} x,y: 圆角矩形的左上角的坐标
 * @param {number} width,height: 圆角矩形的宽和高
 * @param {number} radius: 圆角的半径
 */
function drawRoundRectPathWithArc(ctx, x, y, width, height, radius) {
  ctx.beginPath();
  // 从右下角顺时针绘制,弧度从0到1/2PI
  ctx.arc(x + width - radius, y + height - radius, radius, 0, Math.PI / 2);

  // 矩形下边线
  ctx.lineTo(x + radius, y + height);

  // 左下角圆弧,弧度从1/2PI到PI
  ctx.arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI);

  // 矩形左边线
  ctx.lineTo(x, y + radius);

  // 左上角圆弧,弧度从PI到3/2PI
  ctx.arc(x + radius, y + radius, radius, Math.PI, (Math.PI * 3) / 2);

  // 上边线
  ctx.lineTo(x + width - radius, y);

  //右上角圆弧
  ctx.arc(
    x + width - radius,
    y + radius,
    radius,
    (Math.PI * 3) / 2,
    Math.PI * 2
  );

  //右边线
  ctx.lineTo(x + width, y + height - radius);
  ctx.closePath();
}
/**
 * 该函数的目标是在canvas上使用arcTo()方法绘制圆角矩形路径。
 * 使用arc()方式 两个切线之间的弧
 * 根据控制点和半径绘制圆弧路径,使用当前的描点 (前一个 moveTo 或 lineTo 等函数的止点)。根据当前描点与给定的控制点 1 连接的直线,和控制点 1 与控制点 2 连接的直线,作为使用指定半径的圆的切线,画出两条切线之间的弧线路径
 * @param {*} ctx  canvas的绘图环境上下文
 * @param {number} x 圆角矩形的左上角的坐标
 * @param {number} y 圆角矩形的左上角的坐标
 * @param {number} width 圆角矩形的宽
 * @param {number} height 圆角矩形的高
 * @param {number} radius 圆角的半径
 */
function drawRoundRectPathWithArcTo(ctx, x, y, width, height, radius) {
  ctx.beginPath();

  // 上边线
  ctx.lineTo(x + width - radius, y);

  // 右上弧线 控制点1(x + width, y) 、控制点2( x + width , y + radius, radius)  radius
  ctx.arcTo(x + width, y, x + width, y + radius, radius);

  //右边线
  ctx.lineTo(x + width, y + height - radius);

  // 从右下角顺时针绘制,弧度从0到1/2PI
  ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius);

  // 矩形下边线
  ctx.lineTo(x + radius, y + height);

  // 左下角圆弧,弧度从1/2PI到PI
  ctx.arcTo(x, y + height, x, y + height - radius, radius);

  // 矩形左边线
  ctx.lineTo(x, y + radius);

  // 左上角圆弧,弧度从PI到3/2PI
  ctx.arcTo(x, y, x + radius, y, radius);

  ctx.closePath();
}
/**
 * 这个函数用于填充圆角矩形路径的背景颜色。
 * @param {*} ctx canvas的绘图环境上下文
 * @param {number} x 圆角矩形的左上角的坐标
 * @param {number} y
 * @param {number} width 圆角矩形的宽
 * @param {number} height 圆角矩形的高
 * @param {number} radius 圆角的半径
 * @param {string} color 需要填充的颜色
 */
function fillRoundRectPath(ctx, x, y, width, height, radius, color) {
  ctx.save();
  this.drawRoundRectPathWithArc(ctx, x, y, width, height, radius);
  ctx.fillStyle = color;
  ctx.fill();
  ctx.restore();
}
/**
 * 该函数专门用于在圆角矩形内填充图片
 * @param {*} ctx  canvas的绘图环境上下文
 * @param {*} x 圆角矩形的左上角的坐标
 * @param {*} y
 * @param {*} width 圆角矩形的宽
 * @param {*} height 圆角矩形的高
 * @param {*} radius 圆角的半径
 * @param {*} img 需要填充的图片源地址
 * @returns
 */
function drawRoundRectImg(ctx, x, y, width, height, radius, img) {
  if (!img) return;
  ctx.save();
  this.drawRoundRectPathWithArc(ctx, x, y, width, height, radius);
  // 剪切  原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
  ctx.clip();
  ctx.drawImage(img, x, y, width, height);
  ctx.restore();
}
/**
 * 此函数用以在圆角矩形路径上创建一个虚框。
 * @param {*} ctx  canvas的绘图环境上下文
 * @param {number} x 圆角矩形的左上角的坐标
 * @param {number} y
 * @param {number} width 圆角矩形的宽
 * @param {number} height 圆角矩形的高
 * @param {number} radius 圆角的半径
 */
function strokeRoundRectPath(
  ctx,
  x,
  y,
  width,
  height,
  radius,
  borderWidth = 0.5,
  borderColor = '#ddd'
) {
  this.drawRoundRectPathWithArc(ctx, x, y, width, height, radius);
  ctx.strokeStyle = borderColor;
  ctx.lineWidth = borderWidth;
  ctx.setLineDash([6, 5]);
  ctx.stroke();
}

/**
 * 该函数可以在canvas上绘制一个圆或圆弧
 * @param {*} ctx canvas的绘图环境上下文
 * @param {number} xy 圆的中心坐标
 * @param {number} radius  圆的半径
 * @param {number} startAngle,x 轴方向开始计算,单位以弧度表示
 * @param {number} endAngle 结束的弧度
 * @param {boolean} anticlockwise(可选): 是否逆时针绘制,默认为false
 * drawCircle(ctx,100, 75, 50, 0, 2 * Math.PI)
 */
function drawCircle(
  ctx,
  x,
  y,
  radius,
  startAngle,
  endAngle,
  anticlockwise = false
) {
  ctx.beginPath();

  ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);

  ctx.stroke();
  ctx.closePath();
}

/**
 * 该函数可以清除canvas上特定区域的内容。
 * @param {*} ctx  canvas的绘图环境上下文
 * @param {number} x 需要清除区域的左上角的坐标
 * @param {number} y
 * @param {number} width 需要清除的区域的宽
 * @param {number} height 需要清除的区域的高
 */
function clearRect(ctx, x, y, width, height) {
  ctx.clearRect(x, y, width, height);
}

/**
 * 此函数 Promise 形式返回,用于异步获取图片信息。
 * 获取图片信息方法。网络图片需先配置download域名才能生效
 * @param {String} url 图片的路径,支持网络路径、本地路径、代码包路径
 */
const wxGetImageInfo = (url) => {
  return new Promise((resolve, reject) => {
    if (!url) resolve();
    wx.getImageInfo({
      src: url,
      success: function (res) {
        resolve(res);
      },
      fail: function (res) {
        wx.showToast({
          title: '获取图片信息失败!',
          icon: 'none',
          duration: 3000,
          mask: true
        });
        reject(res);
      }
    });
  });
};

/**
 * 画布导出图片
 * @param {*} canvas  画布
 * @param {number} x 指定的画布区域的左上角横x坐标
 * @param {number} y 指定的画布区域的左上角横y坐标
 * @param {number} width 指定的画布宽
 * @param {number} height 指定的画布高
 * @param {number} calc 导出画布的
 * @returns
 */
const exportImg = (canvas, x, y, width, height, calc = 2) => {
  return new Promise((resolve, reject) => {
    wx.canvasToTempFilePath(
      {
        canvas,
        x: x,
        y: y,
        width: width,
        height: height,
        destWidth: width * calc,
        destHeight: height * calc,
        success: function ({ tempFilePath }) {
          wx.getImageInfo({
            src: tempFilePath,
            success: (res) => {
              resolve(res);
            }
          });
        },
        fail(err) {
          reject(err);
        }
      },
      this
    );
  });
};
/**
 * 此函数用于根据原始图片的宽高和渲染的宽度,从而计算出渲染的高度。
 * @param {number} o_w 原始图片的宽
 * @param {number} o_h 原始图片的高
 * @param {number} r_w 需要渲染的宽
 * @returns
 */
const computeRender = (o_w, o_h, r_w) => {
  return {
    width: r_w,
    height: (r_w * o_h) / o_w
  };
};
/**
 * 此函数 Promise 形式返回,用于在canvas上绘制图片。
 * 传入path(图片https路径),在画布绘制图片
 * @param {*} canvas 当前的canvas对象
 * @param {*} ctx canvas的绘图环境上下文
 * @param {string} path 包含图片的path
 * @param {number} x 图片的起始坐标x
 * @param {number} y 图片的起始坐标y
 * @param {number} width 需要绘制的图片的宽
 * @param {number} height 需要绘制的图片的高
 */
function drawImage(canvas, ctx, path, x, y, width, height) {
  return new Promise(async (resolve, reject) => {
    const bannerReader = canvas.createImage();
    bannerReader.onload = () => {
      try {
        ctx.drawImage(bannerReader, x, y, width, height);
        resolve();
      } catch (e) {
        reject();
        console.error('绘制背景图', e);
      }
    };
    bannerReader.src = path;
  });
}
export default {
  computeRender,
  drawAutoWrapText,
  fillRoundRectPath,
  drawRoundRectPathWithArc,
  drawRoundRectPathWithArcTo,
  drawRoundRectImg,
  strokeRoundRectPath,
  drawCircle,
  clearRect,
  wxGetImageInfo,
  exportImg,
  drawImage
};
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,362评论 6 544
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,577评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,486评论 0 383
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,852评论 1 317
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,600评论 6 412
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,944评论 1 328
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,944评论 3 447
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,108评论 0 290
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,652评论 1 336
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,385评论 3 358
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,616评论 1 374
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,111评论 5 364
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,798评论 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,205评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,537评论 1 295
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,334评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,570评论 2 379

推荐阅读更多精彩内容

  • 一:canvas简介 1.1什么是canvas? ①:canvas是HTML5提供的一种新标签 ②:HTML5 ...
    GreenHand1阅读 4,707评论 2 32
  • 验证浏览器是否支持 Your browser does not support HTML5 Canvas. f...
    shuaiutopia阅读 2,651评论 0 0
  • 一、canvas简介 1.1 什么是canvas?(了解) 是HTML5提供的一种新标签 Canvas是一个矩形区...
    Looog阅读 3,950评论 3 40
  • 一、canvas简介 1.1 什么是canvas?(了解) 是HTML5提供的一种新标签 Canvas是一个矩形区...
    J_L_L阅读 1,540评论 0 4
  • 1 Canvas接口元素定义 1.1 getContext()方法 为了在canvas上绘制,你必须先得到一个画布...
    Kevin_Junbaozi阅读 1,345评论 1 2