|
@@ -0,0 +1,256 @@
|
|
|
|
+/**
|
|
|
|
+ * 在矩形内绘制矩形
|
|
|
|
+ * @param {CanvasRenderingContext2D} ctx - 画布的上下文
|
|
|
|
+ * @param {Object} rect - 矩形范围,包含 { x, y, width, height },以像素为单位
|
|
|
|
+ * @param {number} startXPercent - 内部矩形起始点横坐标,范围从 0 到 100
|
|
|
|
+ * @param {number} startYPercent - 内部矩形起始点纵坐标,范围从 0 到 100
|
|
|
|
+ * @param {number} widthPercent - 内部矩形宽度,范围从 0 到 100
|
|
|
|
+ * @param {number} heightPercent - 内部矩形高度,范围从 0 到 100
|
|
|
|
+ * @param {string} color - 填充颜色,可选参数,默认为黑色
|
|
|
|
+ */
|
|
|
|
+const drawRectInRect = (ctx, rect, startXPercent, startYPercent, widthPercent, heightPercent, color = 'black') => {
|
|
|
|
+ // 计算内部矩形的起始坐标
|
|
|
|
+ const startX = rect.x + (startXPercent / 100) * rect.width;
|
|
|
|
+ const startY = rect.y + (startYPercent / 100) * rect.height;
|
|
|
|
+ // 计算内部矩形的宽度和高度
|
|
|
|
+ const width = (widthPercent / 100) * rect.width;
|
|
|
|
+ const height = (heightPercent / 100) * rect.height;
|
|
|
|
+ ctx.fillStyle = color; // 设置填充颜色
|
|
|
|
+ ctx.fillRect(startX, startY, width, height); // 绘制矩形
|
|
|
|
+ return { x:startX, y:startY, width, height };
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 在矩形内绘制文本
|
|
|
|
+ * @param {CanvasRenderingContext2D} ctx - 画布的上下文
|
|
|
|
+ * @param {Object} rect - 矩形范围,包含 { x, y, width, height },以像素为单位
|
|
|
|
+ * @param {string} text - 要绘制的文本
|
|
|
|
+ * @param {number} startXPercent - 文字起始横坐标,范围从 0 到 100
|
|
|
|
+ * @param {number} startYPercent - 文字起始纵坐标,范围从 0 到 100
|
|
|
|
+ * @param {number} fontSizePercent - 文字大小,范围从 0 到 100,基于矩形高度
|
|
|
|
+ */
|
|
|
|
+const drawTextInRect = (ctx, rect, text, startXPercent, startYPercent, fontSizePercent) => {
|
|
|
|
+ // 计算文字起始坐标
|
|
|
|
+ const startX = rect.x + (startXPercent / 100) * rect.width;
|
|
|
|
+ const startY = rect.y + (startYPercent / 100) * rect.height;
|
|
|
|
+
|
|
|
|
+ // 计算文字大小
|
|
|
|
+ const fontSize = (fontSizePercent / 100) * rect.height;
|
|
|
|
+ ctx.font = `${fontSize}px sans-serif`; // 设置字体样式
|
|
|
|
+ ctx.fillText(text, startX, startY);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 在矩形内绘制线
|
|
|
|
+ * @param {CanvasRenderingContext2D} ctx - 画布的上下文
|
|
|
|
+ * @param {Object} rect - 矩形范围,包含 { x, y, width, height },以像素为单位
|
|
|
|
+ * @param {number} startXPercent - 起始点横坐标,范围从 0 到 100
|
|
|
|
+ * @param {number} startYPercent - 起始点纵坐标,范围从 0 到 100
|
|
|
|
+ * @param {number} endXPercent - 结束点横坐标,范围从 0 到 100
|
|
|
|
+ * @param {number} endYPercent - 结束点纵坐标,范围从 0 到 100
|
|
|
|
+ * @param {string} color - 线条颜色,可选参数,默认为黑色
|
|
|
|
+ * @param {number} lineWidth - 线条宽度,可选参数,默认为1像素
|
|
|
|
+ */
|
|
|
|
+const drawLineInRect = (ctx, rect, startXPercent, startYPercent, endXPercent, endYPercent, color = 'black', lineWidth = 1) => {
|
|
|
|
+ // 计算起始点坐标
|
|
|
|
+ const startX = rect.x + (startXPercent / 100) * rect.width;
|
|
|
|
+ const startY = rect.y + (startYPercent / 100) * rect.height;
|
|
|
|
+
|
|
|
|
+ // 计算结束点坐标
|
|
|
|
+ const endX = rect.x + (endXPercent / 100) * rect.width;
|
|
|
|
+ const endY = rect.y + (endYPercent / 100) * rect.height;
|
|
|
|
+
|
|
|
|
+ // 设置线条样式
|
|
|
|
+ ctx.strokeStyle = color; // 设置线条颜色
|
|
|
|
+ ctx.lineWidth = lineWidth; // 设置线条宽度
|
|
|
|
+
|
|
|
|
+ // 绘制线
|
|
|
|
+ ctx.beginPath();
|
|
|
|
+ ctx.moveTo(startX, startY);
|
|
|
|
+ ctx.lineTo(endX, endY);
|
|
|
|
+ ctx.stroke();
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 在矩形内绘制点
|
|
|
|
+ * @param {CanvasRenderingContext2D} ctx - 画布的上下文
|
|
|
|
+ * @param {Object} rect - 矩形范围,包含 { x, y, width, height },以像素为单位
|
|
|
|
+ * @param {number} xPercent - 点的横坐标,范围从 0 到 100
|
|
|
|
+ * @param {number} yPercent - 点的纵坐标,范围从 0 到 100
|
|
|
|
+ * @param {string} color - 点的颜色,可选参数,默认为黑色
|
|
|
|
+ * @param {number} radius - 点的半径,可选参数,默认为1像素
|
|
|
|
+ */
|
|
|
|
+const drawPointInRect = (ctx, rect, xPercent, yPercent, color = 'black', radius = 1) => {
|
|
|
|
+ // 计算点的坐标
|
|
|
|
+ const x = rect.x + (xPercent / 100) * rect.width;
|
|
|
|
+ const y = rect.y + (yPercent / 100) * rect.height;
|
|
|
|
+
|
|
|
|
+ // 设置点的样式
|
|
|
|
+ ctx.fillStyle = color; // 设置点的颜色
|
|
|
|
+
|
|
|
|
+ // 开始绘制路径
|
|
|
|
+ ctx.beginPath();
|
|
|
|
+ ctx.arc(x, y, radius, 0, Math.PI * 2); // 绘制一个圆
|
|
|
|
+ ctx.fill(); // 填充圆
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 在矩形内绘制图片
|
|
|
|
+ * @param {CanvasRenderingContext2D} ctx - 画布的上下文
|
|
|
|
+ * @param {Object} rect - 矩形范围,包含 { x, y, width, height },以像素为单位
|
|
|
|
+ * @param {HTMLImageElement} img - 要绘制的图片对象
|
|
|
|
+ * @param {number} imgXPercent - 图片起始横坐标,范围从 0 到 100
|
|
|
|
+ * @param {number} imgYPercent - 图片起始纵坐标,范围从 0 到 100
|
|
|
|
+ * @param {number} imgWidthPercent - 图片宽度百分比,范围从 0 到 100
|
|
|
|
+ * @param {number} imgHeightPercent - 图片高度百分比,范围从 0 到 100
|
|
|
|
+ */
|
|
|
|
+const drawImageInRect = (ctx, rect, img, imgXPercent, imgYPercent, imgWidthPercent, imgHeightPercent) => {
|
|
|
|
+ // 计算图片的起始坐标
|
|
|
|
+ const imgX = rect.x + (imgXPercent / 100) * rect.width;
|
|
|
|
+ const imgY = rect.y + (imgYPercent / 100) * rect.height;
|
|
|
|
+ // 计算图片的宽度和高度
|
|
|
|
+ const imgWidth = (imgWidthPercent / 100) * rect.width;
|
|
|
|
+ const imgHeight = (imgHeightPercent / 100) * rect.height;
|
|
|
|
+ // 开始绘制图片
|
|
|
|
+ ctx.drawImage(img, imgX, imgY, imgWidth, imgHeight);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 在矩形内绘制图片,带圆角和白色边框
|
|
|
|
+ * @param {CanvasRenderingContext2D} ctx - 画布的上下文
|
|
|
|
+ * @param {Object} rect - 矩形范围,包含 { x, y, width, height },以像素为单位
|
|
|
|
+ * @param {HTMLImageElement} img - 要绘制的图片对象
|
|
|
|
+ * @param {number} imgXPercent - 图片起始横坐标,范围从 0 到 100
|
|
|
|
+ * @param {number} imgYPercent - 图片起始纵坐标,范围从 0 到 100
|
|
|
|
+ * @param {number} imgWidthPercent - 图片宽度百分比,范围从 0 到 100
|
|
|
|
+ * @param {number} imgHeightPercent - 图片高度百分比,范围从 0 到 100
|
|
|
|
+ * @param {number} borderRadius - 圆角半径,以像素为单位
|
|
|
|
+ * @param {number} borderWidth - 边框宽度,以像素为单位
|
|
|
|
+ */
|
|
|
|
+const drawBorderImageInRect = (ctx, rect, img, imgXPercent, imgYPercent, imgWidthPercent, imgHeightPercent, borderRadius, borderWidth) => {
|
|
|
|
+ // 计算图片的起始坐标
|
|
|
|
+ const imgX = rect.x + (imgXPercent / 100) * rect.width + borderWidth;
|
|
|
|
+ const imgY = rect.y + (imgYPercent / 100) * rect.height + borderWidth;
|
|
|
|
+ // 计算图片的宽度和高度
|
|
|
|
+ const imgWidth = (imgWidthPercent / 100) * rect.width - 2 * borderWidth;
|
|
|
|
+ const imgHeight = (imgHeightPercent / 100) * rect.height - 2 * borderWidth;
|
|
|
|
+
|
|
|
|
+ // 保存画布状态
|
|
|
|
+ ctx.save();
|
|
|
|
+
|
|
|
|
+ // 开始绘制圆角矩形的边框
|
|
|
|
+ ctx.beginPath();
|
|
|
|
+ ctx.moveTo(imgX + borderRadius, imgY);
|
|
|
|
+ ctx.lineTo(imgX + imgWidth - borderRadius, imgY);
|
|
|
|
+ ctx.arcTo(imgX + imgWidth, imgY, imgX + imgWidth, imgY + borderRadius, borderRadius);
|
|
|
|
+ ctx.lineTo(imgX + imgWidth, imgY + imgHeight - borderRadius);
|
|
|
|
+ ctx.arcTo(imgX + imgWidth, imgY + imgHeight, imgX + imgWidth - borderRadius, imgY + imgHeight, borderRadius);
|
|
|
|
+ ctx.lineTo(imgX + borderRadius, imgY + imgHeight);
|
|
|
|
+ ctx.arcTo(imgX, imgY + imgHeight, imgX, imgY + imgHeight - borderRadius, borderRadius);
|
|
|
|
+ ctx.lineTo(imgX, imgY + borderRadius);
|
|
|
|
+ ctx.arcTo(imgX, imgY, imgX + borderRadius, imgY, borderRadius);
|
|
|
|
+ ctx.closePath();
|
|
|
|
+
|
|
|
|
+ // 设置边框颜色和宽度
|
|
|
|
+ ctx.strokeStyle = 'white';
|
|
|
|
+ ctx.lineWidth = borderWidth;
|
|
|
|
+ ctx.stroke();
|
|
|
|
+
|
|
|
|
+ // 开始绘制圆角矩形的填充(可选,如果需要背景)
|
|
|
|
+ // ctx.fillStyle = 'transparent'; // 或者设置其他背景颜色
|
|
|
|
+ // ctx.fill();
|
|
|
|
+
|
|
|
|
+ // 开始裁剪
|
|
|
|
+ ctx.clip();
|
|
|
|
+
|
|
|
|
+ // 绘制图片
|
|
|
|
+ ctx.drawImage(img, imgX, imgY, imgWidth, imgHeight);
|
|
|
|
+
|
|
|
|
+ // 恢复画布状态
|
|
|
|
+ ctx.restore();
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 在矩形内绘制横向文本列表
|
|
|
|
+ * @param {CanvasRenderingContext2D} ctx - 画布的上下文
|
|
|
|
+ * @param {Object} rect - 矩形范围,包含 { x, y, width, height },以像素为单位
|
|
|
|
+ * @param {Array<string>} texts - 要绘制的文本数组
|
|
|
|
+ * @param {number} fontSizePercent - 文字大小,范围从 0 到 100,基于矩形高度
|
|
|
|
+ * @param {number} startXPercent - 文字起始横坐标,范围从 0 到 100,基于矩形宽度
|
|
|
|
+ * @param {number} startYPercent - 文字起始纵坐标,范围从 0 到 100,基于矩形高度
|
|
|
|
+ * @param {number} columnSpacingPercent - 列间距,范围从 0 到 100,基于矩形宽度
|
|
|
|
+ * @param {string} columnSeparator - 列间隔字符,默认为空字符串
|
|
|
|
+ * @param {number} columnSeparatorWidthPercent - 列间隔字符的宽度百分比,范围从 0 到 100,基于矩形宽度
|
|
|
|
+ * @param {number} separatorFontSizePercent - 分隔符字号大小,范围从 0 到 100,基于矩形高度
|
|
|
|
+ * @param {string} separatorColor - 分隔符颜色,默认为黑色
|
|
|
|
+ * @param {number} separatorMarginLeftPercent - 分隔符左边的边距,范围从 0 到 100,基于矩形宽度
|
|
|
|
+ * @param {number} separatorMarginRightPercent - 分隔符右边的边距,范围从 0 到 100,基于矩形宽度
|
|
|
|
+ */
|
|
|
|
+const drawHorizontalTextList = (ctx, rect,color='white', texts, fontSizePercent, startXPercent = 0, startYPercent = 50, columnSpacingPercent = 0, columnSeparator = '', columnSeparatorWidthPercent = 0, separatorFontSizePercent = fontSizePercent, separatorColor = 'black', separatorMarginLeftPercent = 0, separatorMarginRightPercent = 0) => {
|
|
|
|
+ // 计算文字大小
|
|
|
|
+ const fontSize = (fontSizePercent / 100) * rect.height;
|
|
|
|
+ ctx.font = `${fontSize}px sans-serif`; // 设置字体样式
|
|
|
|
+
|
|
|
|
+ // 计算文字的总宽度
|
|
|
|
+ let totalTextWidth = 0;
|
|
|
|
+ texts.forEach(text => {
|
|
|
|
+ totalTextWidth += ctx.measureText(text).width;
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 计算分隔符的字体大小
|
|
|
|
+ const separatorFontSize = (separatorFontSizePercent / 100) * rect.height;
|
|
|
|
+
|
|
|
|
+ // 计算分隔符的总宽度
|
|
|
|
+ ctx.font = `${separatorFontSize}px sans-serif`; // 设置分隔符字体样式
|
|
|
|
+ const separatorWidth = (columnSeparatorWidthPercent / 100) * rect.width;
|
|
|
|
+ const totalSeparatorWidth = (texts.length - 1) * separatorWidth;
|
|
|
|
+
|
|
|
|
+ // 计算分隔符的左右边距
|
|
|
|
+ const separatorMarginLeft = (separatorMarginLeftPercent / 100) * rect.width;
|
|
|
|
+ const separatorMarginRight = (separatorMarginRightPercent / 100) * rect.width;
|
|
|
|
+
|
|
|
|
+ // 计算可用的总间距
|
|
|
|
+ const totalSpacing = (columnSpacingPercent / 100) * rect.width;
|
|
|
|
+
|
|
|
|
+ // 计算所有文字和间隔字符以及间距的总宽度
|
|
|
|
+ const totalWidth = totalTextWidth + totalSeparatorWidth + totalSpacing + (texts.length - 1) * (separatorMarginLeft + separatorMarginRight);
|
|
|
|
+
|
|
|
|
+ // 计算实际的起始坐标,使得文本和间隔字符居中于矩形
|
|
|
|
+ const startX = rect.x + (startXPercent / 100) * rect.width + (rect.width - totalWidth) / 2;
|
|
|
|
+ const startY = rect.y + (startYPercent / 100) * rect.height - (fontSize / 2); // 绘制文字,纵坐标居中
|
|
|
|
+
|
|
|
|
+ // 绘制文本和间隔字符
|
|
|
|
+ let currentX = startX;
|
|
|
|
+ texts.forEach((text, index) => {
|
|
|
|
+ ctx.font = `${fontSize}px sans-serif`; // 设置文字字体样式
|
|
|
|
+ ctx.fillStyle = color; // 设置文字颜色
|
|
|
|
+ ctx.fillText(text, currentX, startY + (fontSize / 2)); // 绘制文字,纵坐标居中
|
|
|
|
+ currentX += ctx.measureText(text).width;
|
|
|
|
+
|
|
|
|
+ // 如果不是最后一列,则绘制间隔字符
|
|
|
|
+ if (index < texts.length - 1) {
|
|
|
|
+ // 添加左边距
|
|
|
|
+ currentX += separatorMarginLeft;
|
|
|
|
+
|
|
|
|
+ // 设置分隔符颜色和字体样式
|
|
|
|
+ ctx.fillStyle = separatorColor;
|
|
|
|
+ ctx.font = `${separatorFontSize}px sans-serif`;
|
|
|
|
+
|
|
|
|
+ // 绘制分隔符
|
|
|
|
+ ctx.fillText(columnSeparator, currentX, startY + (separatorFontSize / 2));
|
|
|
|
+
|
|
|
|
+ // 添加右边距
|
|
|
|
+ currentX += separatorWidth + separatorMarginRight + columnSpacingPercent / 100 * rect.width;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+export { drawTextInRect, drawLineInRect, drawPointInRect ,drawImageInRect,drawBorderImageInRect, drawRectInRect, drawHorizontalTextList};
|
|
|
|
+
|