claySceneLayout function
The arrangement of the two spheres on a canvas of size whose display
column is textSafeArea (null: the top 36 %).
Implementation
({ClaySceneMode mode, ClaySphere a, ClaySphere b}) claySceneLayout(
Size size,
Rect? textSafeArea,
int angleTenths,
) {
final w = size.width;
final h = size.height;
final s = textSafeArea ?? Rect.fromLTWH(0, 0, w, 0.36 * h);
final beta = claySizeBalance(angleTenths);
final ka = 1.1 - 0.2 * beta;
final kb = 0.9 + 0.2 * beta;
final gutter = s.left;
double sphereB(Rect k) =>
math.min(0.30 * k.width, 0.33 * k.height).clamp(64.0, 150.0) * kb;
final rA = (0.24 * s.width).clamp(56.0, 120.0) * ka;
if (s.height >= 0.75 * h) {
final k = Rect.fromLTRB(s.right, 0, w, h);
final rB = sphereB(k);
return (
mode: ClaySceneMode.landscape,
a: (center: Offset(s.left + 0.25 * rA, s.top + 0.35 * rA), radius: rA),
b: (
center: Offset(k.right - 0.10 * rB, k.bottom - 0.10 * rB),
radius: rB,
),
);
}
if (gutter >= 120) {
// Each sphere (and its soft shadow) stays inside its gutter: never
// cut flat by the side panel or the keypad column.
final cap = gutter / 2 - claySphereGutterMargin;
return (
mode: ClaySceneMode.gutter,
a: (
center: Offset(gutter / 2, s.top + 0.30 * h),
radius: math.min(math.min(0.42 * gutter, 0.14 * h) * ka, cap),
),
b: (
center: Offset(s.right + gutter / 2, 0.76 * h),
radius: math.min(math.min(0.48 * gutter, 0.17 * h) * kb, cap),
),
);
}
final k = Rect.fromLTRB(s.left, s.bottom, s.right, h);
final rB = sphereB(k);
return (
mode: ClaySceneMode.portrait,
a: (center: Offset(s.right - 0.10 * rA, s.top - 0.10 * rA), radius: rA),
b: (center: Offset(k.left + 0.10 * rB, k.bottom - 0.10 * rB), radius: rB),
);
}