This commit is contained in:
@@ -268,7 +268,9 @@ export function initLanding() {
|
|||||||
const tipY = lineStartY + mix(longLength * extension, finalLength * scale, converge);
|
const tipY = lineStartY + mix(longLength * extension, finalLength * scale, converge);
|
||||||
const handoff = progress(time, flow.handoff, 280);
|
const handoff = progress(time, flow.handoff, 280);
|
||||||
trunk.setAttribute('d', `M${centreX} ${lineStartY} V${tipY}`);
|
trunk.setAttribute('d', `M${centreX} ${lineStartY} V${tipY}`);
|
||||||
trunk.style.strokeWidth = String(mix(10, scale, converge));
|
// Keep the 1px resting stroke proportional to the slash's shared scale.
|
||||||
|
// Convergence changes the trunk's length, never its relative thickness.
|
||||||
|
trunk.style.strokeWidth = String(scale);
|
||||||
const ink = [[32, 142], [34, 152], [31, 134]].map(([from, to]) => Math.round(mix(from, to, converge)));
|
const ink = [[32, 142], [34, 152], [31, 134]].map(([from, to]) => Math.round(mix(from, to, converge)));
|
||||||
trunk.style.stroke = `rgb(${ink.join(',')})`;
|
trunk.style.stroke = `rgb(${ink.join(',')})`;
|
||||||
trunk.style.opacity = String(progress(time, flow.grow, 100) * (1 - handoff));
|
trunk.style.opacity = String(progress(time, flow.grow, 100) * (1 - handoff));
|
||||||
|
|||||||
@@ -89,6 +89,34 @@ test('hover streams are masked at the actual slash edges throughout the loop', a
|
|||||||
await expect(page.locator('.tap-stream-b')).toHaveCSS('opacity', '0');
|
await expect(page.locator('.tap-stream-b')).toHaveCSS('opacity', '0');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('trunk thickness keeps the same proportion to the slash throughout scaling', async ({ page }, testInfo) => {
|
||||||
|
await page.clock.install({ time: new Date('2026-01-01T00:00:00Z') });
|
||||||
|
await page.clock.pauseAt(new Date('2026-01-01T00:00:01Z'));
|
||||||
|
await armed(page);
|
||||||
|
await page.keyboard.press('Enter');
|
||||||
|
let previousTime = 0;
|
||||||
|
let previousWidth = Infinity;
|
||||||
|
for (const time of [1360, 1520, 1760, 2000, 2240, 2480, 2700]) {
|
||||||
|
await page.clock.runFor(time - previousTime);
|
||||||
|
const ink = await page.evaluate(() => {
|
||||||
|
const path = document.querySelector<SVGPathElement>('.trunk-line')!;
|
||||||
|
const matrix = path.getScreenCTM()!;
|
||||||
|
const stroke = parseFloat(getComputedStyle(path).strokeWidth) * Math.hypot(matrix.a, matrix.b);
|
||||||
|
const slashHeight = document.querySelector('.root-shape')!.getBoundingClientRect().height;
|
||||||
|
return { stroke, slashHeight, opacity: Number(getComputedStyle(path).opacity) };
|
||||||
|
});
|
||||||
|
expect(ink.opacity).toBeGreaterThan(0);
|
||||||
|
// At rest: 1px trunk, 21px of actual slash ink (56/64 of its 24px box).
|
||||||
|
expect(ink.stroke / ink.slashHeight).toBeCloseTo(1 / 21, 5);
|
||||||
|
expect(ink.stroke).toBeLessThan(previousWidth);
|
||||||
|
if ([1520, 2000, 2480].includes(time)) await page.screenshot({ path: testInfo.outputPath(`proportions-${time}.png`) });
|
||||||
|
previousTime = time;
|
||||||
|
previousWidth = ink.stroke;
|
||||||
|
}
|
||||||
|
await page.clock.runFor(1400);
|
||||||
|
await complete(page);
|
||||||
|
});
|
||||||
|
|
||||||
test('continuous motion overlaps growth, travel and reveal without intermediate stops', async ({ page }, testInfo) => {
|
test('continuous motion overlaps growth, travel and reveal without intermediate stops', async ({ page }, testInfo) => {
|
||||||
await page.clock.install({ time: new Date('2026-01-01T00:00:00Z') });
|
await page.clock.install({ time: new Date('2026-01-01T00:00:00Z') });
|
||||||
await page.clock.pauseAt(new Date('2026-01-01T00:00:01Z'));
|
await page.clock.pauseAt(new Date('2026-01-01T00:00:01Z'));
|
||||||
|
|||||||
Reference in New Issue
Block a user