2025-03-14 16:27:50 +08:00

141 lines
5.8 KiB
JavaScript

/** 绘制表单扩展方法 */
export default {
name: 'createLayer',
init: (dp) => {
dp.from = {
height: 0,
padding: 8,
margin: 0
};
dp.setFromOptions = (opts) => {
if (typeof opts.height !== 'undefined') {
dp.from.height = opts.height;
}
if (typeof opts.margin !== 'undefined') {
dp.from.margin = opts.margin;
}
if (typeof opts.padding !== 'undefined') {
dp.from.padding = opts.padding;
}
};
},
handle: (dp, afferOpts, rowList) => {
// 当前配置(头部偏移量, 列内边距, 表单外边距)
const height = dp.from.height;
const margin = dp.from.margin;
const padding = dp.from.padding;
// 当前层宽度
const containerWidth = dp.canvas.width - (margin * 2);
// 基本层配置
const opts = Object.assign({ background: "#fff", columnY: height || margin, self: true, line: true, lineHeight: 0, border: true }, afferOpts);
// 基本列配置
const baseRowOpts = {
text: "",
font: "24px sans-serif",
color: "#333",
center: false,
width: 0,
};
// 累计最高的列为标准定义为层高度
let maxRowHeight = 0;
// 累计固定栅格列偏移量
let columnOffsetX = margin;
// 创建行绘制任务
const drawLayerInfos = rowList.map((afferRowOpts = {}, index) => {
const rowOpts = Object.assign(Object.assign({}, baseRowOpts), afferRowOpts);
let columnX = 0; // 每列的X轴
let columnW = 0; // 每列的宽度
let fontOffsetX = 0; // 字体偏移X轴
let fontMaxWidth = 100; // 字体最大宽度
opts.lineHeight = opts.lineHeight || Number(rowOpts.font.replace(/[^0-9.]/g, ""));
if (opts.self) {
// 自适应栅格格子计算
columnX = containerWidth - (containerWidth / (index + 1)) + margin;
columnW = containerWidth / rowList.length;
if (columnX > 0 && columnX < containerWidth - columnW) {
columnX = (columnW * index) + margin;
}
fontOffsetX = rowOpts.center ? columnX + (columnW / 2) : columnX + padding;
fontMaxWidth = columnW - (padding * 3);
}
if (!opts.self) {
// 固定栅格格子计算
columnW = rowOpts.width;
columnX = columnOffsetX;
fontMaxWidth = columnW - (padding * 3);
fontOffsetX = rowOpts.center ? columnOffsetX + (rowOpts.width / 2) : columnOffsetX + padding;
columnOffsetX += rowOpts.width;
}
dp.ctx.font = rowOpts.font;
const drawFontInfos = dp.ctx.fillWarpText({
text: rowOpts.text,
maxWidth: fontMaxWidth,
lineHeight: opts.lineHeight,
x: fontOffsetX,
y: opts.columnY,
layer: 10,
notFillText: true
});
// 当前行的高度
const rowHeight = (opts.lineHeight * drawFontInfos.length) + (padding * 3);
// 若该列高度大于累计高度, 将累计高度替换
if (rowHeight > maxRowHeight) {
maxRowHeight = rowHeight;
}
return {
font: rowOpts.font,
center: rowOpts.center,
color: rowOpts.color,
border: opts.border,
background: opts.background,
lineHeight: opts.lineHeight,
line: opts.line,
drawFontInfos,
columnY: opts.columnY,
columnX,
columnW,
columnH: maxRowHeight,
margin,
padding
};
});
// 将行绘制任务添加至绘制容器中
dp.draw((ctx) => drawLayerInfos.forEach((rowOpts, index) => {
ctx.font = rowOpts.font;
ctx.fillStyle = rowOpts.background;
ctx.strokeStyle = "#333";
ctx.textBaseline = "middle";
ctx.textAlign = 'left';
if (rowOpts.center) {
ctx.textAlign = "center";
}
ctx.fillRect(rowOpts.columnX, rowOpts.columnY, rowOpts.columnW, rowOpts.columnH);
if (rowOpts.border) {
dp.ctx.strokeRect(margin, rowOpts.columnY, dp.canvas.width - margin, maxRowHeight);
}
if (rowOpts.line && rowOpts.columnX !== margin) {
ctx.moveTo(rowOpts.columnX, rowOpts.columnY);
ctx.lineTo(rowOpts.columnX, rowOpts.columnY + rowOpts.columnH);
ctx.stroke();
ctx.beginPath();
}
ctx.fillStyle = rowOpts.color;
rowOpts.drawFontInfos.forEach(fontInfo => {
// 计算每行字体绘制y轴长度
// y(当前列置顶轴) + (rowOpts.columnH(当前列最高长度) / 2) - (((总列数-1) * 行高) / 2)
const textTotal = rowOpts.drawFontInfos.length - 1;
const textMiddleY = (textTotal * rowOpts.lineHeight) / 2;
let fontOffsetY = fontInfo.y + (rowOpts.columnH / 2);
fontOffsetY -= textMiddleY;
ctx.fillText(fontInfo.text, fontInfo.x, fontOffsetY);
});
}));
if (opts.columnY === 0 || opts.columnY === margin) {
maxRowHeight += margin;
}
// 叠加高度
dp.from.height += maxRowHeight;
return maxRowHeight;
},
};