一、canvas
文档:
https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial
二、数据绘制(单位是像素):
1、绘制文本:
文字的长度超过设置的最大宽度,文字会缩在一起
① 填充文本(实心):
ctx.fillText("这里是文字", 开始绘制文本的点的 x 轴坐标, 开始绘制文本的点的 y 轴坐标[, 文字的最大宽度]);
② 边框文本(空心):
ctx.strokeText("这里是文字", 开始绘制文本的点的 x 轴坐标, 开始绘制文本的点的 y 轴坐标[, 文字的最大宽度]);
③ 文本超过最大宽度想要换行:
/**
* ctx:canvas元素
* x:开始绘制文本的点的 x 轴坐标
* y:开始绘制文本的点的 y 轴坐标
* lineHeight: 文本的行高
* maxWidth:文字的最大宽度
* 返回值:下一行文字的起始位置y坐标
**/
function drawWrappedText(ctx, text, x, y, lineHeight, maxWidth) {
// Split text into words using spaces, filtering out empty strings
const words = text.split(/\s+/g).filter(word => word.length > 0);
let line = '';
const lines = [];
for (const word of words) {
// Check if adding the word (with space) exceeds maxWidth
const testLine = line ? line + ' ' + word : word;
const metrics = ctx.measureText(testLine);
if (metrics.width > maxWidth) {
if (line === '') {
// Word is too long; split it
let splitIndex = 1;
while (splitIndex < word.length) {
const part = word.substring(0, splitIndex);
if (ctx.measureText(part).width > maxWidth) break;
splitIndex++;
}
splitIndex = Math.max(1, splitIndex - 1); // Adjust to fit
lines.push(word.substring(0, splitIndex));
line = word.substring(splitIndex); // Remaining part
} else {
// Push current line and start new line with the word
lines.push(line);
line = word;
}
} else {
line = testLine; // Add word to current line
}
}
if (line) lines.push(line); // Add the last line
// Draw each line and calculate nextStart
lines.forEach((line, index) => {
ctx.fillText(line, x, y + index * lineHeight, maxWidth);
});
return y + lines.length * lineHeight; // Next starting Y position
}
④ 文本样式:
ctx.font="文字大小 粗细 颜色 字体名称..."
2、绘制矩形:
① 填充矩形(实心):
ctx.fillStyle = '颜色' // 这个是填充的颜色
ctx.fillRect(矩形左上角的起始点x, 矩形左上角的起始点y, 矩形的宽, 矩形的高); // 这个是填充矩形
② 边框矩形(空心):
ctx.strokeRect(边框左上角的起始点x, 边框左上角的起始点y, 边框的宽, 边框的高);
ctx.strokeStyle = '颜色' // 这个是矩形线条边框的颜色
3、绘制路径:
① 新建一条路径:ctx.beginPath()
② 移动笔触设置起点:ctx.moveTo(路径的起点x,路径的起点y);
③ 绘制路径:
(1)直线:
ctx.lineTo(直线结束点x,直线结束点y);
- 只要线条轮廓:
ctx.stroke()
- 需要填充:
ctx.fill()
(2)闭合路径绘制(连接起点和终点):
ctx.closePath()
(3)指定线条的宽度:
ctx.lineWidth = 数字
4、绘制图片:
图片尽量使用临时路径,即使用uni.canvasToTempFilePath()
函数生成
① 微信小程序不允许使用new Image()
:
使用 canvas.createImage()
② 绘制图片是一个异步过程,要使用async\await
进行处理
三、简单的使用代码:
1、 模版代码:
<canvas
id="myCanvas"
type="2d"
:style="{ position: 'fixed', top: '-9999px', left: '-9999px', width: canvasWidth + 'px', height: canvasHeight + 'px' }"
></canvas>
2、js
代码:
// 初始化canvas
async createCanvas(width, height) {
return new Promise((resolve) => {
const query = uni.createSelectorQuery().in(this);
query.select('#myCanvas').fields({ node: true, size: true }).exec(res => {
const canvas = res[0].node;
// const dpr = uni.getSystemInfoSync().pixelRatio;
// canvas.width = width * dpr;
// canvas.height = height * dpr;
canvas.width = width
canvas.height = height
resolve(canvas);
});
});
},
// 点击某个按钮进行模版的绘制
async saveImg() {
const that = this
// 首先初始化canvas
const canvas = await that.createCanvas(图片的宽, 图片的高);
const ctx = canvas.getContext('2d');
// 拿到当前设备的像素比
const dpr = uni.getSystemInfoSync().pixelRatio;
// 绘制内容:
await that.drawImage(canvas, ctx, 图片的临时路径, 221,58, 108, 108);
},
async drawImage(canvas,ctx, imagePath, x, y, width, height) {
return new Promise((resolve) => {
const img = canvas.createImage();
img.src = imagePath;
img.onload = () => {
ctx.drawImage(img, x, y, width, height);
resolve();
};
});
}