perf(ui): stop the nav-rail brand pulse to fix web scroll jank
The DeltaMark ran an endless 9s breathing animation (60fps repaint) inside the persistent nav rail, so it repainted on every scroll frame and stuttered scrolling on Flutter web. Make the rail mark static (animated: false) and isolate the animated variant (landing page) behind a RepaintBoundary. Signed-off-by: flemming-it <sf@flemming.it>
This commit is contained in:
parent
51beb332c4
commit
136d3b48c6
2 changed files with 29 additions and 12 deletions
|
|
@ -50,7 +50,11 @@ class _ShellPageState extends State<ShellPage> {
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const DeltaMark(size: 36),
|
// Static in the persistent nav rail: a 60fps pulse
|
||||||
|
// here repaints every scroll frame and stutters web
|
||||||
|
// scrolling. The breathing mark stays on the
|
||||||
|
// landing page (which isn't scrolled).
|
||||||
|
const DeltaMark(size: 36, animated: false),
|
||||||
const SizedBox(height: ReclaimSpace.sm),
|
const SizedBox(height: ReclaimSpace.sm),
|
||||||
const BrandWordmark(size: 18),
|
const BrandWordmark(size: 18),
|
||||||
Text(
|
Text(
|
||||||
|
|
|
||||||
|
|
@ -46,17 +46,30 @@ class _DeltaMarkState extends State<DeltaMark>
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AnimatedBuilder(
|
// Static mark: no controller listening, paint once.
|
||||||
|
if (!widget.animated) {
|
||||||
|
return CustomPaint(
|
||||||
|
size: Size.square(widget.size),
|
||||||
|
painter: _DeltaPainter(pulse: 1.0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Animated: isolate the per-frame repaint in its own layer so
|
||||||
|
// the breathing pulse never invalidates surrounding content
|
||||||
|
// (web scroll stays smooth).
|
||||||
|
return RepaintBoundary(
|
||||||
|
child: AnimatedBuilder(
|
||||||
animation: _controller,
|
animation: _controller,
|
||||||
builder: (context, _) {
|
builder: (context, _) {
|
||||||
final t = _controller.value;
|
final t = _controller.value;
|
||||||
// Breathe: scale 1 → 1.28 → 1 over the cycle.
|
// Breathe: scale 1 → 1.28 → 1 over the cycle.
|
||||||
final pulse = 1.0 + 0.28 * (1 - (math.cos(t * 2 * math.pi).abs()));
|
final pulse =
|
||||||
|
1.0 + 0.28 * (1 - (math.cos(t * 2 * math.pi).abs()));
|
||||||
return CustomPaint(
|
return CustomPaint(
|
||||||
size: Size.square(widget.size),
|
size: Size.square(widget.size),
|
||||||
painter: _DeltaPainter(pulse: widget.animated ? pulse : 1.0),
|
painter: _DeltaPainter(pulse: pulse),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue