mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
156 lines
5.0 KiB
Markdown
156 lines
5.0 KiB
Markdown
/*
|
|
|
|

|
|
|
|
Download this file and save to your Obsidian Vault including the first line, or open it in "Raw" and copy the entire contents to Obsidian.
|
|
|
|

|
|
|
|
This script expands the height of the selected rectangles until they are all the same height and keep the text centered.
|
|
|
|
See documentation for more details:
|
|
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
|
|
|
|
```javascript
|
|
*/
|
|
|
|
const elements = ea.getViewSelectedElements();
|
|
const topGroups = ea.getMaximumGroups(elements);
|
|
const allIndividualArrows = ea.getMaximumGroups(ea.getViewElements())
|
|
.reduce((result, group) => (group.length === 1 && (group[0].type === 'arrow' || group[0].type === 'line')) ?
|
|
[...result, group[0]] : result, []);
|
|
|
|
const groupHeights = topGroups
|
|
.map((g) => {
|
|
if(g.length === 1 && (g[0].type === 'arrow' || g[0].type === 'line')) {
|
|
// ignore individual lines
|
|
return { minTop: 0, maxBottom: 0 };
|
|
}
|
|
return g.reduce(
|
|
(pre, cur, i) => {
|
|
if (i === 0) {
|
|
return {
|
|
minTop: cur.y,
|
|
maxBottom: cur.y + cur.height,
|
|
index: i,
|
|
};
|
|
} else {
|
|
return {
|
|
minTop: cur.y < pre.minTop ? cur.y : pre.minTop,
|
|
maxBottom:
|
|
cur.y + cur.height > pre.maxBottom
|
|
? cur.y + cur.height
|
|
: pre.maxBottom,
|
|
index: i,
|
|
};
|
|
}
|
|
},
|
|
{ minTop: 0, maxBottom: 0 }
|
|
);
|
|
})
|
|
.map((r) => {
|
|
r.height = r.maxBottom - r.minTop;
|
|
return r;
|
|
});
|
|
|
|
const maxGroupHeight = Math.max(...groupHeights.map((g) => g.height));
|
|
|
|
for (var i = 0; i < topGroups.length; i++) {
|
|
const rects = topGroups[i]
|
|
.filter((el) => el.type === "rectangle")
|
|
.sort((lha, rha) => lha.y - rha.y);
|
|
const texts = topGroups[i]
|
|
.filter((el) => el.type === "text")
|
|
.sort((lha, rha) => lha.y - rha.y);
|
|
const groupWith = groupHeights[i].height;
|
|
if (groupWith < maxGroupHeight) {
|
|
const distance = maxGroupHeight - groupWith;
|
|
const perRectDistance = distance / rects.length;
|
|
const textsWithRectIndex = [];
|
|
for (var j = 0; j < rects.length; j++) {
|
|
const rect = rects[j];
|
|
const rectLeft = rect.x;
|
|
const rectTop = rect.y;
|
|
const rectRight = rect.x + rect.width;
|
|
const rectBottom = rect.y + rect.height;
|
|
|
|
const textsWithRect = texts.filter(text => text.x >= rectLeft && text.x <= rectRight
|
|
&& text.y >= rectTop && text.y <= rectBottom);
|
|
|
|
textsWithRectIndex[j] = textsWithRect;
|
|
}
|
|
for (var j = 0; j < rects.length; j++) {
|
|
const rect = rects[j];
|
|
rect.y = rect.y + perRectDistance * j - perRectDistance / 2;
|
|
rect.height += perRectDistance;
|
|
|
|
const textsWithRect = textsWithRectIndex[j];
|
|
|
|
if(textsWithRect) {
|
|
for(const text of textsWithRect) {
|
|
text.y = text.y + perRectDistance * j;
|
|
}
|
|
}
|
|
|
|
// recalculate the position of the points
|
|
const startBindingLines = allIndividualArrows.filter(el => (el.startBinding||{}).elementId === rect.id);
|
|
for(startBindingLine of startBindingLines) {
|
|
recalculateStartPointOfLine(startBindingLine, rect);
|
|
}
|
|
|
|
const endBindingLines = allIndividualArrows.filter(el => (el.endBinding||{}).elementId === rect.id);
|
|
for(endBindingLine of endBindingLines) {
|
|
recalculateEndPointOfLine(endBindingLine, rect);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ea.copyViewElementsToEAforEditing(elements);
|
|
await ea.addElementsToView(false, false);
|
|
|
|
function recalculateStartPointOfLine(line, el) {
|
|
const aX = el.x + el.width/2;
|
|
const bX = line.x + line.points[1][0];
|
|
const aY = el.y + el.height/2;
|
|
const bY = line.y + line.points[1][1];
|
|
|
|
line.startBinding.gap = 8;
|
|
line.startBinding.focus = 0;
|
|
const intersectA = ea.intersectElementWithLine(
|
|
el,
|
|
[bX, bY],
|
|
[aX, aY],
|
|
line.startBinding.gap
|
|
);
|
|
|
|
if(intersectA.length > 0) {
|
|
line.points[0] = [0, 0];
|
|
for(var i = 1; i<line.points.length; i++) {
|
|
line.points[i][0] -= intersectA[0][0] - line.x;
|
|
line.points[i][1] -= intersectA[0][1] - line.y;
|
|
}
|
|
line.x = intersectA[0][0];
|
|
line.y = intersectA[0][1];
|
|
}
|
|
}
|
|
|
|
function recalculateEndPointOfLine(line, el) {
|
|
const aX = el.x + el.width/2;
|
|
const bX = line.x + line.points[line.points.length-2][0];
|
|
const aY = el.y + el.height/2;
|
|
const bY = line.y + line.points[line.points.length-2][1];
|
|
|
|
line.endBinding.gap = 8;
|
|
line.endBinding.focus = 0;
|
|
const intersectA = ea.intersectElementWithLine(
|
|
el,
|
|
[bX, bY],
|
|
[aX, aY],
|
|
line.endBinding.gap
|
|
);
|
|
|
|
if(intersectA.length > 0) {
|
|
line.points[line.points.length - 1] = [intersectA[0][0] - line.x, intersectA[0][1] - line.y];
|
|
}
|
|
} |