Skip to content

Instantly share code, notes, and snippets.

@zxch3n
Created June 15, 2022 11:54
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save zxch3n/1f28317731876a8d9026d4d7d4eef892 to your computer and use it in GitHub Desktop.
function layoutSubtree(node, children) {
if (children.length == 0) {
return;
}
const prev = [children[0]];
let iyl = new IYL(getBottom(children[0]), 0, null);
for (let i = 1; i < children.length; i++) {
const cur = children[i];
const [distance, collideIndex] = getMoveDistance(prev, cur, iyl);
cur.relativeX = distance;
distributeDistanceToInteriorSubtrees(children, distance, collideIndex, i);
mergeContour(prev, cur);
prev.push(cur);
iyl = iyl.update(getBottom(cur), i);
}
positionRoot(node);
}
function finalizeAbsolutePosition(node) {
addChildSpacing(node);
finalizeXPosition(node);
}
class IYL {
constructor(
public bottom: number,
public index: number,
public next: IYL | null
) {}
update(minY: number, index: number) {
let cur = this;
while (cur != null && minY >= cur.bottom) cur = cur.next;
return new IYL(minY, index, cur);
}
}
function getMoveDistance(prev, cur, iyl) {
const curLeftContour = cur;
const prevRightContour = prev[prev.length - 1];
let maxDistance = 0;
let collideIndex = 0;
while (curLeftContour && prevRightContour) {
if (xR.y + xR.height > iyl.bottom) {
iyl = iyl.next;
}
const xL = getRelativeX(curLeftContour)
const xR = getRelativeX(prevRightContour) + prevRightContour.width + margin;
if (xR - xL > maxDistance) {
maxDistance = xR - xL;
collideIndex = iyl.index;
}
const yL = curLeftContour.y + curLeftContour.height;
const yR = prevRightContour.y + prevRightContour.height;
if (yL <= yR) {
curLeftContour = nextLeftContour(curLeftContour);
}
if (yL >= yR) {
prevRightContour = nextRightContour(prevRightContour);
}
}
return [maxDistance, collideIndex];
}
function mergeContour(prev, cur) {
if (bottom(prev) > bottom(cur)) {
const extremeRight = getRightThreadLastNode(cur)
extremeRight.threadRight = getRightThreadNodeAtY(prev[prev.length - 1], extremeRight.y);
extremeRight.modifierThreadRight = ...;
} else if (bottom(prev) < bottom(cur)) {
const extremeLeft = getLeftThreadLastNode(prev[0])
extremeLeft.threadLeft = getLeftThreadNodeAtY(cur, extremeLeft.y);
extremeLeft.modifierThreadLeft = ...;
}
}
function addChildSpacing(node) {
let speed = 0.;
let delta = 0.;
for (const child of node.children) {
speed += child.shiftAcceleration;
delta += speed + child.shiftChange;
child.relativeX += delta;
}
}
function distributeDistanceToInteriorSubtrees(children, distance, from, to) {
if (to == from + 1){
return;
}
children[from + 1].shiftAcceleration += distance/(to-from);
children[to].shiftAcceleration -= distance/(to-from);
children[to].shiftChange -= distance - distance/(to-from);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment