手把手教你實(shí)現(xiàn)一個(gè)流動(dòng)的漸變色邊框

前言

記得在介紹 motion_toast一篇的時(shí)候,開(kāi)篇有一張動(dòng)圖,邊框是漸變色而且感覺(jué)是流動(dòng)的。這個(gè)動(dòng)效挺有趣的,當(dāng)時(shí)也有人問(wèn)怎么實(shí)現(xiàn),經(jīng)過(guò)上一篇《讓你的聊天氣泡豐富多彩!》后,有了實(shí)現(xiàn)思路了。

motion_toast 邊框

實(shí)現(xiàn)思路

首先要實(shí)現(xiàn)但是漸變色邊框,這個(gè)其實(shí)可以參考上一篇的CustomPaint 的漸變填充實(shí)現(xiàn)。繪制一個(gè)矩形邊框,然后讓漸變色的區(qū)域填充到矩形區(qū)域內(nèi)就可以了。

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);
}

繪制出來(lái)的效果如下圖所示。


漸變邊框繪制效果

然后是讓漸變色流動(dòng)起來(lái),這里就需要?jiǎng)赢?huà)了,通過(guò)動(dòng)畫(huà)控制漸變填充的角度,周而復(fù)始就能夠形成不斷流動(dòng)的效果。這里還是要用到 LinearGradienttransform 屬性。Flutter 內(nèi)置了一個(gè)GradientRotation旋轉(zhuǎn)變換的類(lèi),正好可以進(jìn)行角度變換實(shí)現(xiàn)角度控制,GradientRotation 接收一個(gè)角度值實(shí)現(xiàn)對(duì)漸變的角度控制,下面是0度和90度的對(duì)比圖,可以看到0度到90度邊框的漸變色起始位置正好是旋轉(zhuǎn)了90度。

角度旋轉(zhuǎn)

有了以上兩個(gè)基礎(chǔ),我們通過(guò)一個(gè) Animation 對(duì)象動(dòng)畫(huà)過(guò)程中的值來(lái)控制旋轉(zhuǎn)角度就可以了。

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 值實(shí)現(xiàn)漸變旋轉(zhuǎn)效果
    ).createShader(rect)
    ..style = PaintingStyle.stroke
    ..strokeWidth = 8.0;
  canvas.drawRect(rect, paint);
}

動(dòng)畫(huà)配置代碼如下,2秒旋轉(zhuǎn)一周,使用 Curves.linear實(shí)現(xiàn)勻速旋轉(zhuǎn)。

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();
  }
  
  //...
}

實(shí)現(xiàn)的效果如下所示。

漸變邊框?qū)崿F(xiàn)效果1

調(diào)整一下顏色和 LinearGradientbeginend 參數(shù),還可以實(shí)現(xiàn)一些有趣的效果。下面這個(gè)效果就和開(kāi)篇那個(gè)效果有點(diǎn)接近了。

漸變邊框?qū)崿F(xiàn)效果2

如果是畫(huà)成圓圈邊框的話,做 Loading 效果其實(shí)也不錯(cuò)。

漸變 loading

源碼已經(jīng)提交至:繪圖相關(guān)源碼,文件名為:gradient_bound_demo.dart。

總結(jié)

本篇介紹了自定義繪制漸變色邊框,并通過(guò)動(dòng)畫(huà)實(shí)現(xiàn)流動(dòng)的效果,繪圖加動(dòng)畫(huà)組合能夠?qū)崿F(xiàn)很多既有創(chuàng)意又有取的效果,大家也可以嘗試一下看看有哪些有趣的玩法。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容