九、Flutter水波動畫

目錄
一、效果展示
二、CustomPaint
三、CustomPainter
四、水波效果
五、文字效果
六、動起來

一、效果展示

Flutter水波動畫.png

二、CustomPaint

WaterWave繼承CustomPainter用畫筆畫出來的水波動畫效果需要CustomPaint呈現出來。
CustomPaint有兩個參數painter和size,painter是一個繼承了CustomPainter的對象,主要實現了繪畫控件的功能。size指定了控件的大小,如果CustomPaint的child不為空,size的值就是child控件的大小,指定size的值則無效;如果child為空,所指定的size的值,就是畫布的大小。

CustomPaint(
                painter: WaterWave(this.variable, 0.79, this.offsetX),
                size: Size(160, 160),
              )

三、CustomPainter

WaterWave繼承了CustomPainter,實現了其中兩個重要方法:paint和shouldRepaint。paint當自定義控件需要重畫時被調用。shouldRepaint則決定當條件變化時是否需要重畫。

class WaterWave extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
  }

  @override
  bool shouldRepaint(ClockPainter oldDelegate) {
    return true;
  }
}

四、水波效果

繪出水波效果有幾個重要的參數:波紋振幅:double waveAmplitude;
波紋周期:double waveCycle;波紋上升速度:double waveGrowth;
波浪x位移:double offsetX;當前波浪上市高度Y(高度從大到小 坐標系向下增長):double currentWavePointY; 模擬波紋:double variable;這幾個參數在sin函數和cos函數地計算下模擬出水波的形狀,然后畫出來。

void firstWave() {
    Path path = new Path();
    double y = this.currentWavePointY;
    path.moveTo(0, y);
    for (double x = 0.0; x <= this.waterWaveWidth; x++) {
      y = this.waveAmplitude * sin(this.waveCycle * x + this.offsetX) +
          this.currentWavePointY;
      path.lineTo(x, y);
    }
    path.lineTo(this.waterWaveWidth, this.size.height);
    path.lineTo(0, this.size.height);
    path.close();
    var paint = new Paint()
      ..color = Color.fromRGBO(223, 83, 64, 1)
      ..style = PaintingStyle.fill
      ..maskFilter = MaskFilter.blur(BlurStyle.inner, 5.0);
    this.canvas.drawPath(path, paint);
  }


void secondWave() {
    Path path = new Path();
    double y = this.currentWavePointY;
    path.moveTo(0, y);
    for (double x = 0.0; x <= this.waterWaveWidth; x++) {
      y = this.waveAmplitude * cos(this.waveCycle * x + this.offsetX) +
          this.currentWavePointY;
      path.lineTo(x, y);
    }
    path.lineTo(this.waterWaveWidth, this.size.height);
    path.lineTo(0, this.size.height);
    path.close();
    var paint = new Paint()
      ..color = Color.fromRGBO(236, 90, 66, 1)
      ..style = PaintingStyle.fill
      ..maskFilter = MaskFilter.blur(BlurStyle.inner, 5.0);
    this.canvas.drawPath(path, paint);
}

五、文字效果

繪畫文字的時候需要添加引用,import 'dart:ui' as UI;

 UI.ParagraphBuilder pb = UI.ParagraphBuilder(UI.ParagraphStyle(
      textAlign: TextAlign.center,
      fontWeight: FontWeight.w500,
      fontStyle: FontStyle.normal,
      fontSize: 70.0,
    ));
    pb.pushStyle(UI.TextStyle(color: Colors.white));
    pb.addText('86');
    UI.Paragraph paragraph = pb.build();
    paragraph.layout(UI.ParagraphConstraints(width: 140));
    Offset offset = Offset(10, 30.0);
    this.canvas.drawParagraph(paragraph, offset);


    UI.ParagraphBuilder pb2 = UI.ParagraphBuilder(UI.ParagraphStyle(
      textAlign: TextAlign.center,
      fontWeight: FontWeight.w500,
      fontStyle: FontStyle.normal,
      fontSize: 18.0,
    ));
    pb2.pushStyle(UI.TextStyle(color: Colors.white));
    pb2.addText('評分');
    UI.Paragraph paragraph2 = pb2.build();
    paragraph2.layout(UI.ParagraphConstraints(width: 100));
    Offset offset2 = Offset(30, 105.0);
    this.canvas.drawParagraph(paragraph2, offset2);

六、動起來

重新initState方法,添加一個定時器沒25毫秒改變一下水波的波紋。
variable模擬波紋上下浮動的效果,offsetX模擬波浪的位移,從而能夠增強波紋震動的效果。

@override
  void initState() {
    super.initState();

    this.variable = widget.variable;
    this.increase = widget.increase;
    this.waveSpeed = 0.4 / pi;
    this.offsetX = 0.0;

    this.timer = Timer.periodic(new Duration(milliseconds: 25), (timer) {
      setState(() {
        this.offsetX += this.waveSpeed;

        if (this.increase) {
          this.variable += 0.01;
        } else {
          this.variable -= 0.01;
        }

        if (this.variable <= 1) {
          this.increase = true;
        }

        if (this.variable >= 1.6) {
          this.increase = false;
        }
      });
    });
  }
關注公眾號,查看更多內容.jpg
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內容

  • 我們已經了解了Flutter中的剪裁,那么制作一個評分控件已經很簡單了。先準備兩個版本的五角星,一個用于高亮展示分...
    秋分落葉閱讀 3,561評論 2 2
  • 1,從本篇文章/音頻/視頻中我學到的最重要的概念 劃分段落時,記敘文感覺比較難一點。快速閱讀第三單元...
    201吳曉歡閱讀 228評論 2 0
  • 最近股市比較火爆,我自己做了也比較久,我在此將我的一些對市場的思考總結出來,和大家分享。從一個對話開始。一次和同事...
    長頸猴閱讀 297評論 0 0
  • 今天是什么日子 起床:8:10 就寢:12:00 天氣:晴 心情:雜亂 紀念日:83天 叫我起床的不是鬧鐘是夢想 ...
    WILDATTENTION閱讀 169評論 0 1
  • 小時候熱愛文學,喜歡看書,從小就有當作家的夢想,那時候只知道能當作家是多么高尚多么光榮的事情。可是因為不知道怎么樣...
    喜若盈盈閱讀 208評論 3 2