@hirokisakabe/pom 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/calcYogaLayout/calcYogaLayout.d.ts.map +1 -1
- package/dist/calcYogaLayout/calcYogaLayout.js +49 -84
- package/dist/calcYogaLayout/fontLoader.d.ts +20 -0
- package/dist/calcYogaLayout/fontLoader.d.ts.map +1 -0
- package/dist/calcYogaLayout/fontLoader.js +59 -0
- package/dist/calcYogaLayout/fonts/notoSansJPBold.d.ts +7 -0
- package/dist/calcYogaLayout/fonts/notoSansJPBold.d.ts.map +1 -0
- package/dist/calcYogaLayout/fonts/notoSansJPBold.js +6 -0
- package/dist/calcYogaLayout/fonts/notoSansJPRegular.d.ts +7 -0
- package/dist/calcYogaLayout/fonts/notoSansJPRegular.d.ts.map +1 -0
- package/dist/calcYogaLayout/fonts/notoSansJPRegular.js +6 -0
- package/dist/calcYogaLayout/measureText.d.ts +1 -1
- package/dist/calcYogaLayout/measureText.d.ts.map +1 -1
- package/dist/calcYogaLayout/measureText.js +65 -114
- package/dist/renderPptx/nodes/box.d.ts +1 -0
- package/dist/renderPptx/nodes/box.d.ts.map +1 -0
- package/dist/renderPptx/nodes/box.js +2 -0
- package/dist/renderPptx/nodes/chart.d.ts +8 -0
- package/dist/renderPptx/nodes/chart.d.ts.map +1 -0
- package/dist/renderPptx/nodes/chart.js +23 -0
- package/dist/renderPptx/nodes/flow.d.ts +8 -0
- package/dist/renderPptx/nodes/flow.d.ts.map +1 -0
- package/dist/renderPptx/nodes/flow.js +208 -0
- package/dist/renderPptx/nodes/image.d.ts +8 -0
- package/dist/renderPptx/nodes/image.d.ts.map +1 -0
- package/dist/renderPptx/nodes/image.js +17 -0
- package/dist/renderPptx/nodes/index.d.ts +11 -0
- package/dist/renderPptx/nodes/index.d.ts.map +1 -0
- package/dist/renderPptx/nodes/index.js +10 -0
- package/dist/renderPptx/nodes/matrix.d.ts +8 -0
- package/dist/renderPptx/nodes/matrix.d.ts.map +1 -0
- package/dist/renderPptx/nodes/matrix.js +150 -0
- package/dist/renderPptx/nodes/processArrow.d.ts +8 -0
- package/dist/renderPptx/nodes/processArrow.d.ts.map +1 -0
- package/dist/renderPptx/nodes/processArrow.js +75 -0
- package/dist/renderPptx/nodes/shape.d.ts +8 -0
- package/dist/renderPptx/nodes/shape.d.ts.map +1 -0
- package/dist/renderPptx/nodes/shape.js +49 -0
- package/dist/renderPptx/nodes/table.d.ts +8 -0
- package/dist/renderPptx/nodes/table.d.ts.map +1 -0
- package/dist/renderPptx/nodes/table.js +29 -0
- package/dist/renderPptx/nodes/text.d.ts +8 -0
- package/dist/renderPptx/nodes/text.d.ts.map +1 -0
- package/dist/renderPptx/nodes/text.js +5 -0
- package/dist/renderPptx/nodes/timeline.d.ts +8 -0
- package/dist/renderPptx/nodes/timeline.d.ts.map +1 -0
- package/dist/renderPptx/nodes/timeline.js +157 -0
- package/dist/renderPptx/nodes/tree.d.ts +8 -0
- package/dist/renderPptx/nodes/tree.d.ts.map +1 -0
- package/dist/renderPptx/nodes/tree.js +223 -0
- package/dist/renderPptx/renderPptx.d.ts.map +1 -1
- package/dist/renderPptx/renderPptx.js +27 -945
- package/dist/renderPptx/types.d.ts +10 -0
- package/dist/renderPptx/types.d.ts.map +1 -0
- package/dist/renderPptx/types.js +1 -0
- package/dist/renderPptx/utils/backgroundBorder.d.ts +8 -0
- package/dist/renderPptx/utils/backgroundBorder.d.ts.map +1 -0
- package/dist/renderPptx/utils/backgroundBorder.js +44 -0
- package/dist/renderPptx/utils/index.d.ts +6 -0
- package/dist/renderPptx/utils/index.d.ts.map +1 -0
- package/dist/renderPptx/utils/index.js +3 -0
- package/dist/renderPptx/utils/shapeDrawing.d.ts +27 -0
- package/dist/renderPptx/utils/shapeDrawing.d.ts.map +1 -0
- package/dist/renderPptx/utils/shapeDrawing.js +36 -0
- package/dist/renderPptx/utils/textDrawing.d.ts +20 -0
- package/dist/renderPptx/utils/textDrawing.d.ts.map +1 -0
- package/dist/renderPptx/utils/textDrawing.js +20 -0
- package/package.json +3 -2
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { pxToIn, pxToPt } from "../units";
|
|
2
|
+
export function renderTreeNode(node, ctx) {
|
|
3
|
+
const layout = node.layout ?? "vertical";
|
|
4
|
+
const nodeShape = node.nodeShape ?? "rect";
|
|
5
|
+
const nodeWidth = node.nodeWidth ?? 120;
|
|
6
|
+
const nodeHeight = node.nodeHeight ?? 40;
|
|
7
|
+
const levelGap = node.levelGap ?? 60;
|
|
8
|
+
const siblingGap = node.siblingGap ?? 20;
|
|
9
|
+
const connectorStyle = node.connectorStyle ?? {};
|
|
10
|
+
const defaultColor = "1D4ED8";
|
|
11
|
+
// サブツリーの幅/高さを計算
|
|
12
|
+
function calculateSubtreeSize(item) {
|
|
13
|
+
if (!item.children || item.children.length === 0) {
|
|
14
|
+
return { width: nodeWidth, height: nodeHeight };
|
|
15
|
+
}
|
|
16
|
+
const childSizes = item.children.map(calculateSubtreeSize);
|
|
17
|
+
if (layout === "vertical") {
|
|
18
|
+
const childrenWidth = childSizes.reduce((sum, s) => sum + s.width, 0) +
|
|
19
|
+
siblingGap * (childSizes.length - 1);
|
|
20
|
+
const childrenHeight = Math.max(...childSizes.map((s) => s.height));
|
|
21
|
+
return {
|
|
22
|
+
width: Math.max(nodeWidth, childrenWidth),
|
|
23
|
+
height: nodeHeight + levelGap + childrenHeight,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
const childrenHeight = childSizes.reduce((sum, s) => sum + s.height, 0) +
|
|
28
|
+
siblingGap * (childSizes.length - 1);
|
|
29
|
+
const childrenWidth = Math.max(...childSizes.map((s) => s.width));
|
|
30
|
+
return {
|
|
31
|
+
width: nodeWidth + levelGap + childrenWidth,
|
|
32
|
+
height: Math.max(nodeHeight, childrenHeight),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// ツリーレイアウトを計算
|
|
37
|
+
function calculateTreeLayout(item, x, y) {
|
|
38
|
+
const subtreeSize = calculateSubtreeSize(item);
|
|
39
|
+
const layoutNode = {
|
|
40
|
+
item,
|
|
41
|
+
x: 0,
|
|
42
|
+
y: 0,
|
|
43
|
+
width: nodeWidth,
|
|
44
|
+
height: nodeHeight,
|
|
45
|
+
children: [],
|
|
46
|
+
};
|
|
47
|
+
if (layout === "vertical") {
|
|
48
|
+
// ノードを中央上部に配置
|
|
49
|
+
layoutNode.x = x + subtreeSize.width / 2 - nodeWidth / 2;
|
|
50
|
+
layoutNode.y = y;
|
|
51
|
+
// 子ノードを配置
|
|
52
|
+
if (item.children && item.children.length > 0) {
|
|
53
|
+
const childSizes = item.children.map(calculateSubtreeSize);
|
|
54
|
+
const totalChildWidth = childSizes.reduce((sum, s) => sum + s.width, 0) +
|
|
55
|
+
siblingGap * (childSizes.length - 1);
|
|
56
|
+
let childX = x + subtreeSize.width / 2 - totalChildWidth / 2;
|
|
57
|
+
const childY = y + nodeHeight + levelGap;
|
|
58
|
+
for (let i = 0; i < item.children.length; i++) {
|
|
59
|
+
const child = item.children[i];
|
|
60
|
+
const childLayout = calculateTreeLayout(child, childX, childY);
|
|
61
|
+
layoutNode.children.push(childLayout);
|
|
62
|
+
childX += childSizes[i].width + siblingGap;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
// horizontal: ノードを左中央に配置
|
|
68
|
+
layoutNode.x = x;
|
|
69
|
+
layoutNode.y = y + subtreeSize.height / 2 - nodeHeight / 2;
|
|
70
|
+
// 子ノードを配置
|
|
71
|
+
if (item.children && item.children.length > 0) {
|
|
72
|
+
const childSizes = item.children.map(calculateSubtreeSize);
|
|
73
|
+
const totalChildHeight = childSizes.reduce((sum, s) => sum + s.height, 0) +
|
|
74
|
+
siblingGap * (childSizes.length - 1);
|
|
75
|
+
const childX = x + nodeWidth + levelGap;
|
|
76
|
+
let childY = y + subtreeSize.height / 2 - totalChildHeight / 2;
|
|
77
|
+
for (let i = 0; i < item.children.length; i++) {
|
|
78
|
+
const child = item.children[i];
|
|
79
|
+
const childLayout = calculateTreeLayout(child, childX, childY);
|
|
80
|
+
layoutNode.children.push(childLayout);
|
|
81
|
+
childY += childSizes[i].height + siblingGap;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return layoutNode;
|
|
86
|
+
}
|
|
87
|
+
// 接続線を描画
|
|
88
|
+
function drawConnector(parent, child, style) {
|
|
89
|
+
const lineColor = style.color ?? "333333";
|
|
90
|
+
const lineWidth = style.width ?? 2;
|
|
91
|
+
if (layout === "vertical") {
|
|
92
|
+
// 親の下端中央から子の上端中央へ
|
|
93
|
+
const parentCenterX = parent.x + parent.width / 2;
|
|
94
|
+
const parentBottomY = parent.y + parent.height;
|
|
95
|
+
const childCenterX = child.x + child.width / 2;
|
|
96
|
+
const childTopY = child.y;
|
|
97
|
+
const midY = (parentBottomY + childTopY) / 2;
|
|
98
|
+
// 垂直線(親から中間点まで)
|
|
99
|
+
ctx.slide.addShape(ctx.pptx.ShapeType.line, {
|
|
100
|
+
x: pxToIn(parentCenterX),
|
|
101
|
+
y: pxToIn(parentBottomY),
|
|
102
|
+
w: 0,
|
|
103
|
+
h: pxToIn(midY - parentBottomY),
|
|
104
|
+
line: { color: lineColor, width: pxToPt(lineWidth) },
|
|
105
|
+
});
|
|
106
|
+
// 水平線(中間点で)
|
|
107
|
+
const minX = Math.min(parentCenterX, childCenterX);
|
|
108
|
+
const maxX = Math.max(parentCenterX, childCenterX);
|
|
109
|
+
if (maxX > minX) {
|
|
110
|
+
ctx.slide.addShape(ctx.pptx.ShapeType.line, {
|
|
111
|
+
x: pxToIn(minX),
|
|
112
|
+
y: pxToIn(midY),
|
|
113
|
+
w: pxToIn(maxX - minX),
|
|
114
|
+
h: 0,
|
|
115
|
+
line: { color: lineColor, width: pxToPt(lineWidth) },
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
// 垂直線(中間点から子まで)
|
|
119
|
+
ctx.slide.addShape(ctx.pptx.ShapeType.line, {
|
|
120
|
+
x: pxToIn(childCenterX),
|
|
121
|
+
y: pxToIn(midY),
|
|
122
|
+
w: 0,
|
|
123
|
+
h: pxToIn(childTopY - midY),
|
|
124
|
+
line: { color: lineColor, width: pxToPt(lineWidth) },
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// 親の右端中央から子の左端中央へ
|
|
129
|
+
const parentRightX = parent.x + parent.width;
|
|
130
|
+
const parentCenterY = parent.y + parent.height / 2;
|
|
131
|
+
const childLeftX = child.x;
|
|
132
|
+
const childCenterY = child.y + child.height / 2;
|
|
133
|
+
const midX = (parentRightX + childLeftX) / 2;
|
|
134
|
+
// 水平線(親から中間点まで)
|
|
135
|
+
ctx.slide.addShape(ctx.pptx.ShapeType.line, {
|
|
136
|
+
x: pxToIn(parentRightX),
|
|
137
|
+
y: pxToIn(parentCenterY),
|
|
138
|
+
w: pxToIn(midX - parentRightX),
|
|
139
|
+
h: 0,
|
|
140
|
+
line: { color: lineColor, width: pxToPt(lineWidth) },
|
|
141
|
+
});
|
|
142
|
+
// 垂直線(中間点で)
|
|
143
|
+
const minY = Math.min(parentCenterY, childCenterY);
|
|
144
|
+
const maxY = Math.max(parentCenterY, childCenterY);
|
|
145
|
+
if (maxY > minY) {
|
|
146
|
+
ctx.slide.addShape(ctx.pptx.ShapeType.line, {
|
|
147
|
+
x: pxToIn(midX),
|
|
148
|
+
y: pxToIn(minY),
|
|
149
|
+
w: 0,
|
|
150
|
+
h: pxToIn(maxY - minY),
|
|
151
|
+
line: { color: lineColor, width: pxToPt(lineWidth) },
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
// 水平線(中間点から子まで)
|
|
155
|
+
ctx.slide.addShape(ctx.pptx.ShapeType.line, {
|
|
156
|
+
x: pxToIn(midX),
|
|
157
|
+
y: pxToIn(childCenterY),
|
|
158
|
+
w: pxToIn(childLeftX - midX),
|
|
159
|
+
h: 0,
|
|
160
|
+
line: { color: lineColor, width: pxToPt(lineWidth) },
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// ノードを描画
|
|
165
|
+
function drawTreeNode(layoutNode, shape, defaultNodeColor) {
|
|
166
|
+
const color = layoutNode.item.color ?? defaultNodeColor;
|
|
167
|
+
const shapeType = (() => {
|
|
168
|
+
switch (shape) {
|
|
169
|
+
case "rect":
|
|
170
|
+
return ctx.pptx.ShapeType.rect;
|
|
171
|
+
case "roundRect":
|
|
172
|
+
return ctx.pptx.ShapeType.roundRect;
|
|
173
|
+
case "ellipse":
|
|
174
|
+
return ctx.pptx.ShapeType.ellipse;
|
|
175
|
+
}
|
|
176
|
+
})();
|
|
177
|
+
// ノードの背景
|
|
178
|
+
ctx.slide.addShape(shapeType, {
|
|
179
|
+
x: pxToIn(layoutNode.x),
|
|
180
|
+
y: pxToIn(layoutNode.y),
|
|
181
|
+
w: pxToIn(layoutNode.width),
|
|
182
|
+
h: pxToIn(layoutNode.height),
|
|
183
|
+
fill: { color },
|
|
184
|
+
line: { color: "333333", width: pxToPt(1) },
|
|
185
|
+
});
|
|
186
|
+
// ノードのラベル
|
|
187
|
+
ctx.slide.addText(layoutNode.item.label, {
|
|
188
|
+
x: pxToIn(layoutNode.x),
|
|
189
|
+
y: pxToIn(layoutNode.y),
|
|
190
|
+
w: pxToIn(layoutNode.width),
|
|
191
|
+
h: pxToIn(layoutNode.height),
|
|
192
|
+
fontSize: pxToPt(12),
|
|
193
|
+
fontFace: "Noto Sans JP",
|
|
194
|
+
color: "FFFFFF",
|
|
195
|
+
align: "center",
|
|
196
|
+
valign: "middle",
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
// すべての接続線を再帰的に描画
|
|
200
|
+
function drawAllConnectors(layoutNode) {
|
|
201
|
+
for (const child of layoutNode.children) {
|
|
202
|
+
drawConnector(layoutNode, child, connectorStyle);
|
|
203
|
+
drawAllConnectors(child);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// すべてのノードを再帰的に描画
|
|
207
|
+
function drawAllNodes(layoutNode) {
|
|
208
|
+
drawTreeNode(layoutNode, nodeShape, defaultColor);
|
|
209
|
+
for (const child of layoutNode.children) {
|
|
210
|
+
drawAllNodes(child);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// ツリーのサイズを計算
|
|
214
|
+
const treeSize = calculateSubtreeSize(node.data);
|
|
215
|
+
// 描画領域内の中央に配置
|
|
216
|
+
const offsetX = node.x + (node.w - treeSize.width) / 2;
|
|
217
|
+
const offsetY = node.y + (node.h - treeSize.height) / 2;
|
|
218
|
+
// レイアウト計算
|
|
219
|
+
const rootLayout = calculateTreeLayout(node.data, offsetX, offsetY);
|
|
220
|
+
// 描画(接続線を先に、ノードを後に描画)
|
|
221
|
+
drawAllConnectors(rootLayout);
|
|
222
|
+
drawAllNodes(rootLayout);
|
|
223
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderPptx.d.ts","sourceRoot":"","sources":["../../src/renderPptx/renderPptx.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,aAAa,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"renderPptx.d.ts","sourceRoot":"","sources":["../../src/renderPptx/renderPptx.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,aAAa,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAiB/C,KAAK,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEpD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,OAAO,iBA8EnE"}
|