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
: 包含圖片信息的對象,例如圖片 pathx
,y
: 圖片的起始坐標width
,height
: 需要繪制的圖片的寬和高
參考
/*
* @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
};