绿满眶商城微信小程序-uniapp
xiangpei
2025-05-09 c3e6cdbb29580e77444541c7953aca33581a4267
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/** 绘制表单扩展方法 */
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;
    },
};