封裝常用的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閱讀 229,406評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,034評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,413評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,449評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,165評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,559評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,606評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,781評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,327評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,084評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,278評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,849評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,495評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,927評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,172評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,010評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,241評論 2 375

推薦閱讀更多精彩內容

  • 一:canvas簡介 1.1什么是canvas? ①:canvas是HTML5提供的一種新標簽 ②:HTML5 ...
    GreenHand1閱讀 4,704評論 2 32
  • 驗證瀏覽器是否支持 Your browser does not support HTML5 Canvas. f...
    shuaiutopia閱讀 2,648評論 0 0
  • 一、canvas簡介 1.1 什么是canvas?(了解) 是HTML5提供的一種新標簽 Canvas是一個矩形區...
    Looog閱讀 3,949評論 3 40
  • 一、canvas簡介 1.1 什么是canvas?(了解) 是HTML5提供的一種新標簽 Canvas是一個矩形區...
    J_L_L閱讀 1,540評論 0 4
  • 1 Canvas接口元素定義 1.1 getContext()方法 為了在canvas上繪制,你必須先得到一個畫布...
    Kevin_Junbaozi閱讀 1,340評論 1 2