封装常用的canvas工具类

2023-11-21  本文已影响0人  小仙有毒_1991

canvas绘图工具库

一、引言

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

二、使用场景

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

三、函数列表:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

9 wxGetImageInfo(url)

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

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

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

11 computeRender(o_w, o_h, r_w)

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

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

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

参考

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
};
上一篇下一篇

猜你喜欢

热点阅读