You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现基于数值的Flutter CustomPainter多颜色补间动画?

多颜色数值驱动的CustomPainter动画实现方案

核心问题分析

原来的实现仅依赖animationController.forward()/reverse()切换蓝橙颜色,这种逻辑无法适配多区间的颜色过渡需求。需要先把数值映射到动画控制器的进度区间,再通过TweenSequence定义多阶段颜色补间,才能实现平滑的多色切换。

步骤1:修改父组件的动画驱动逻辑

放弃单纯的forward/reverse判断,根据当前数值计算动画控制器的目标进度值,用animateTo()实现平滑过渡:

// 假设数值上限为1000,可根据实际需求调整
double maxValue = 1000;
double targetProgress = 0.0;

if (magnetometerState.v < 400) {
  targetProgress = 0.0; // 对应蓝色
} else if (magnetometerState.v <= 600) {
  // 400-600映射到动画进度0-0.5(蓝→橙阶段)
  targetProgress = (magnetometerState.v - 400) / (600 - 400) * 0.5;
} else {
  // 600以上映射到动画进度0.5-1(橙→红阶段)
  targetProgress = 0.5 + (magnetometerState.v - 600) / (maxValue - 600) * 0.5;
}

// 平滑过渡到目标进度,可调整duration控制动画速度
animationController.animateTo(targetProgress, duration: const Duration(milliseconds: 300));

步骤2:重构CircleChart的颜色动画逻辑

用TweenSequence定义三个颜色区间的补间规则,替换原来的单一ColorTween:

class CircleChart extends CustomPainter {
  final double value;
  final Animation<Color> color;

  CircleChart({required this.value, required Animation<double> animation})
      : color = TweenSequence<Color>([
            // 进度0→0.5:蓝色→橙色
            TweenSequenceItem(
              tween: ColorTween(begin: const Color(0xFF00D1FF), end: Colors.orange),
              weight: 1.0,
            ),
            // 进度0.5→1:橙色→红色
            TweenSequenceItem(
              tween: ColorTween(begin: Colors.orange, end: Colors.red),
              weight: 1.0,
            ),
          ]).animate(animation),
        super(repaint: animation);

  @override
  void paint(Canvas canvas, Size size) {
    final p1 = const Offset(50, 50);
    final p2 = const Offset(250, 150);
    final paint = Paint()
      ..color = color.value
      ..strokeWidth = 4;
    canvas.drawLine(p1, p2, paint);
  }

  @override
  bool shouldRepaint(CircleChart oldDelegate) {
    // 优化重绘逻辑,仅当数值或颜色动画变化时重绘
    return oldDelegate.value != value || oldDelegate.color != color;
  }
}

关键说明

  • TweenSequence的weight参数控制每个颜色阶段占总动画进度的比例:这里两个阶段weight都是1,所以各占0-0.5、0.5-1的进度区间,刚好对应数值的400-600、600以上区间。
  • 动画控制器的animateTo()会自动处理数值上升/下降时的反向过渡(红→橙→蓝),无需额外判断。
  • 原来用TweenSequence没效果的原因是动画进度没有和数值区间正确绑定,单纯的forward/reverse无法触发多阶段的颜色变化。

内容的提问来源于stack exchange,提问作者JBTG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 23:33:17