index.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /** 绘制表单扩展方法 */
  2. export default {
  3. name: 'createLayer',
  4. init: (dp) => {
  5. dp.from = {
  6. height: 0,
  7. padding: 8,
  8. margin: 0
  9. };
  10. dp.setFromOptions = (opts) => {
  11. if (typeof opts.height !== 'undefined') {
  12. dp.from.height = opts.height;
  13. }
  14. if (typeof opts.margin !== 'undefined') {
  15. dp.from.margin = opts.margin;
  16. }
  17. if (typeof opts.padding !== 'undefined') {
  18. dp.from.padding = opts.padding;
  19. }
  20. };
  21. },
  22. handle: (dp, afferOpts, rowList) => {
  23. // 当前配置(头部偏移量, 列内边距, 表单外边距)
  24. const height = dp.from.height;
  25. const margin = dp.from.margin;
  26. const padding = dp.from.padding;
  27. // 当前层宽度
  28. const containerWidth = dp.canvas.width - (margin * 2);
  29. // 基本层配置
  30. const opts = Object.assign({ background: "#fff", columnY: height || margin, self: true, line: true, lineHeight: 0, border: true }, afferOpts);
  31. // 基本列配置
  32. const baseRowOpts = {
  33. text: "",
  34. font: "24px sans-serif",
  35. color: "#333",
  36. center: false,
  37. width: 0,
  38. };
  39. // 累计最高的列为标准定义为层高度
  40. let maxRowHeight = 0;
  41. // 累计固定栅格列偏移量
  42. let columnOffsetX = margin;
  43. // 创建行绘制任务
  44. const drawLayerInfos = rowList.map((afferRowOpts = {}, index) => {
  45. const rowOpts = Object.assign(Object.assign({}, baseRowOpts), afferRowOpts);
  46. let columnX = 0; // 每列的X轴
  47. let columnW = 0; // 每列的宽度
  48. let fontOffsetX = 0; // 字体偏移X轴
  49. let fontMaxWidth = 100; // 字体最大宽度
  50. opts.lineHeight = opts.lineHeight || Number(rowOpts.font.replace(/[^0-9.]/g, ""));
  51. if (opts.self) {
  52. // 自适应栅格格子计算
  53. columnX = containerWidth - (containerWidth / (index + 1)) + margin;
  54. columnW = containerWidth / rowList.length;
  55. if (columnX > 0 && columnX < containerWidth - columnW) {
  56. columnX = (columnW * index) + margin;
  57. }
  58. fontOffsetX = rowOpts.center ? columnX + (columnW / 2) : columnX + padding;
  59. fontMaxWidth = columnW - (padding * 3);
  60. }
  61. if (!opts.self) {
  62. // 固定栅格格子计算
  63. columnW = rowOpts.width;
  64. columnX = columnOffsetX;
  65. fontMaxWidth = columnW - (padding * 3);
  66. fontOffsetX = rowOpts.center ? columnOffsetX + (rowOpts.width / 2) : columnOffsetX + padding;
  67. columnOffsetX += rowOpts.width;
  68. }
  69. dp.ctx.font = rowOpts.font;
  70. const drawFontInfos = dp.ctx.fillWarpText({
  71. text: rowOpts.text,
  72. maxWidth: fontMaxWidth,
  73. lineHeight: opts.lineHeight,
  74. x: fontOffsetX,
  75. y: opts.columnY,
  76. layer: 10,
  77. notFillText: true
  78. });
  79. // 当前行的高度
  80. const rowHeight = (opts.lineHeight * drawFontInfos.length) + (padding * 3);
  81. // 若该列高度大于累计高度, 将累计高度替换
  82. if (rowHeight > maxRowHeight) {
  83. maxRowHeight = rowHeight;
  84. }
  85. return {
  86. font: rowOpts.font,
  87. center: rowOpts.center,
  88. color: rowOpts.color,
  89. border: opts.border,
  90. background: opts.background,
  91. lineHeight: opts.lineHeight,
  92. line: opts.line,
  93. drawFontInfos,
  94. columnY: opts.columnY,
  95. columnX,
  96. columnW,
  97. columnH: maxRowHeight,
  98. margin,
  99. padding
  100. };
  101. });
  102. // 将行绘制任务添加至绘制容器中
  103. dp.draw((ctx) => drawLayerInfos.forEach((rowOpts, index) => {
  104. ctx.font = rowOpts.font;
  105. ctx.fillStyle = rowOpts.background;
  106. ctx.strokeStyle = "#333";
  107. ctx.textBaseline = "middle";
  108. ctx.textAlign = 'left';
  109. if (rowOpts.center) {
  110. ctx.textAlign = "center";
  111. }
  112. ctx.fillRect(rowOpts.columnX, rowOpts.columnY, rowOpts.columnW, rowOpts.columnH);
  113. if (rowOpts.border) {
  114. dp.ctx.strokeRect(margin, rowOpts.columnY, dp.canvas.width - margin, maxRowHeight);
  115. }
  116. if (rowOpts.line && rowOpts.columnX !== margin) {
  117. ctx.moveTo(rowOpts.columnX, rowOpts.columnY);
  118. ctx.lineTo(rowOpts.columnX, rowOpts.columnY + rowOpts.columnH);
  119. ctx.stroke();
  120. ctx.beginPath();
  121. }
  122. ctx.fillStyle = rowOpts.color;
  123. rowOpts.drawFontInfos.forEach(fontInfo => {
  124. // 计算每行字体绘制y轴长度
  125. // y(当前列置顶轴) + (rowOpts.columnH(当前列最高长度) / 2) - (((总列数-1) * 行高) / 2)
  126. const textTotal = rowOpts.drawFontInfos.length - 1;
  127. const textMiddleY = (textTotal * rowOpts.lineHeight) / 2;
  128. let fontOffsetY = fontInfo.y + (rowOpts.columnH / 2);
  129. fontOffsetY -= textMiddleY;
  130. ctx.fillText(fontInfo.text, fontInfo.x, fontOffsetY);
  131. });
  132. }));
  133. if (opts.columnY === 0 || opts.columnY === margin) {
  134. maxRowHeight += margin;
  135. }
  136. // 叠加高度
  137. dp.from.height += maxRowHeight;
  138. return maxRowHeight;
  139. },
  140. };