手把手教你實現一個流動的漸變色邊框

前言

記得在介紹 motion_toast一篇的時候,開篇有一張動圖,邊框是漸變色而且感覺是流動的。這個動效挺有趣的,當時也有人問怎麼實現,經過上一篇《讓你的聊天氣泡豐富多彩!》後,有了實現思路了。

實現思路

首先要實現但是漸變色邊框,這個其實可以參考上一篇的CustomPaint 的漸變填充實現。繪製一個矩形邊框,然後讓漸變色的區域填充到矩形區域內就可以了。

void paint(Canvas canvas, Size size) {
  final rectWidth = 300.0, rectHeight = 100.0;
  Rect rect = Offset(
          size.width / 2 - rectWidth / 2, size.height / 2 - rectHeight / 2) &
      Size(rectWidth, rectHeight);
  final paint = Paint()
    ..shader = LinearGradient(
      begin: Alignment.topLeft,
      end: Alignment.bottomRight,
      colors: colors,
      ),
    ).createShader(rect)
    ..style = PaintingStyle.stroke
    ..strokeWidth = 8.0;
  canvas.drawRect(rect, paint);
}

繪製出來的效果如下圖所示。


然後是讓漸變色流動起來,這裏就需要動畫了,通過動畫控制漸變填充的角度,週而復始就能夠形成不斷流動的效果。這裏還是要用到 LinearGradienttransform 屬性。Flutter 內置了一個GradientRotation旋轉變換的類,正好可以進行角度變換實現角度控制,GradientRotation 接收一個角度值實現對漸變的角度控制,下面是0度和90度的對比圖,可以看到0度到90度邊框的漸變色起始位置正好是旋轉了90度。

有了以上兩個基礎,我們通過一個 Animation 對象動畫過程中的值來控制旋轉角度就可以了。

void paint(Canvas canvas, Size size) {
  final rectWidth = 300.0, rectHeight = 100.0;
  Rect rect = Offset(
          size.width / 2 - rectWidth / 2, size.height / 2 - rectHeight / 2) &
      Size(rectWidth, rectHeight);
  final paint = Paint()
    ..shader = LinearGradient(
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter,
      colors: colors,
      transform: GradientRotation(
        animation * 2 * pi,
      ), //改變 transform 值實現漸變旋轉效果
    ).createShader(rect)
    ..style = PaintingStyle.stroke
    ..strokeWidth = 8.0;
  canvas.drawRect(rect, paint);
}

動畫配置代碼如下,2秒旋轉一週,使用 Curves.linear實現勻速旋轉。

class _GradientBoundDemoState extends State<GradientBoundDemo>
    with SingleTickerProviderStateMixin {
  late Animation<double> animation;
  late AnimationController controller;

  @override
  void initState() {
    super.initState();
    controller =
        AnimationController(duration: const Duration(seconds: 2), vsync: this);
    animation = Tween<double>(begin: 0, end: 1.0).animate(CurvedAnimation(
      parent: controller,
      curve: Curves.linear,
    ))
      ..addListener(() {
        setState(() {});
      });
    controller.repeat();
  }
  
  //...
}

實現的效果如下所示。


調整一下顏色和 LinearGradientbeginend 參數,還可以實現一些有趣的效果。下面這個效果就和開篇那個效果有點接近了。

如果是畫成圓圈邊框的話,做 Loading 效果其實也不錯。

源碼已經提交至:繪圖相關源碼,文件名爲:gradient_bound_demo.dart

總結

本篇介紹了自定義繪製漸變色邊框,並通過動畫實現流動的效果,繪圖加動畫組合能夠實現很多既有創意又有取的效果,大家也可以嘗試一下看看有哪些有趣的玩法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章