『Flutter-繪制篇』實現(xiàn)炫酷的雷電特效

前言

前不久,利用周末時間學(xué)習(xí)并完成一個簡單的 Flutter 項目 - 簡悅天氣牺六,簡約不簡單,豐富不復(fù)雜汗捡,這是一款簡約風(fēng)格的 flutter 天氣項目淑际,提供實時、多日扇住、24 小時春缕、臺風(fēng)路徑、語音播報以及生活指數(shù)等服務(wù)艘蹋,支持定位锄贼、刪除、搜索等操作女阀。

下圖為主頁效果宅荤,點擊下載 進(jìn)行體驗:

圖1

項目中運用了大量的自定義繪制 widget,首頁豐富的 自定義 chart 效果和炫酷的天氣背景動效浸策。天氣背景動效在不同的天氣氣象下展示不同的效果冯键。目前一共實現(xiàn)了 15 種類別,其中有庸汗,晴惫确、晴晚、多云夫晌、多云晚雕薪、陰天、小中大雨晓淀、小中大雪所袁、霧、霾凶掰、浮塵以及雷暴燥爷。背景動效一共分為三層:

  • 背景顏色層蜈亩。從上到下的漸變效果
  • 云層。只有一種圖片前翎,對其位移稚配、數(shù)量、染色做不同變化達(dá)到不同效果
  • 信息層港华。包括雨雪道川、雷暴和晴晚流星效果

之前分別用兩篇文章介紹雨雪和晴晚流星效果的實現(xiàn)細(xì)節(jié):

今天我們介紹背景動畫的最后一篇,如何實現(xiàn)炫酷的雷電特效立宜,先看一下最終效果:

thunder

準(zhǔn)備

根據(jù)實現(xiàn)效果進(jìn)行分析冒萄,雨滴效果在之前文章有介紹過不多贅述,仔細(xì)觀察橙数,其實就是對閃電圖片在繪制時控制其 alpha 以營造出這種霹靂的效果尊流。

首先準(zhǔn)備幾張閃電的素材,UI 網(wǎng)站找了很長時間沒有找到滿意的效果灯帮,關(guān)鍵費時費錢崖技。后來發(fā)現(xiàn) oppo 最新版的天氣的雷暴效果停酷炫的钟哥,于是對其反編譯迎献,找到他的資源目錄。其實 oppo 雷暴的動畫效果是通過 視頻+openGL 的方式實現(xiàn)腻贰,里面有閃電的靜態(tài)資源忿晕、視頻資源和 openGL 代碼文件。我們只需提取他的靜態(tài)資源文件即可银受。隨即在 initState() 方法中異步獲取加載圖片資源:

  Future<void> fetchImages() async {
    weatherPrint("開始獲取雷暴圖片");
    var image1 = await ImageUtils.getImage('assets/images/lightning/lightning0.webp');
    var image2 = await ImageUtils.getImage('assets/images/lightning/lightning1.webp');
    var image3 = await ImageUtils.getImage('assets/images/lightning/lightning2.webp');
    var image4 = await ImageUtils.getImage('assets/images/lightning/lightning3.webp');
    var image5 = await ImageUtils.getImage('assets/images/lightning/lightning4.webp');
    _images.add(image1);
    _images.add(image2);
    _images.add(image3);
    _images.add(image4);
    _images.add(image5);
    weatherPrint("獲取雷暴圖片成功: ${_images?.length}");
  }

有了圖片后,開始構(gòu)建對象和參數(shù)列表鸦采。由上面分析可知宾巍,除了基本的坐標(biāo) x,y 信息,只需要額外增加 alpha 屬性來達(dá)到效果渔伯。

class ThunderParams {
  ui.Image image;
  double x;
  double y;
  double alpha;
  int get imgWidth => image.width;
  int get imgHeight => image.height;

  ThunderParams(this.image);

  void reset() {
    x = Random().nextDouble() * 0.5.wp -  1 / 3 * imgWidth;
    y = Random().nextDouble() * -0.05.hp;
    alpha = 0;
  }
}

reset() 方法用于在當(dāng)前雷暴結(jié)束時,重新初始化參數(shù)信息。

繪制

參數(shù)配置好后贯钩,繪制很簡單杖玲。有了圖片有了位置信息和 alpha 信息,調(diào)用 canvas 的相關(guān) api 進(jìn)行繪制即可玄叠。

  void drawThunder(ThunderParams params, Canvas canvas, Size size) {
    if (params == null || params.image == null) {
      return;
    }
    canvas.save();
    var identity = ColorFilter.matrix(<double>[
      1, 0, 0, 0, 0,
      0, 1, 0, 0, 0,
      0, 0, 1, 0, 0,
      0, 0, 0, params.alpha, 0,
    ]);
    _paint.colorFilter = identity;
    canvas.drawImage(params.image, Offset(params.x, params.y), _paint);
    canvas.restore();
  }

繪制到屏幕中大概長這樣:

<img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e893b7064eb9463b88f07d3d79fdd4e2~tplv-k3u1fbpfcp-zoom-1.image" alt="thunder2" style="zoom: 33%;" />

動畫

離炫酷就差最后一步 動畫古徒。

首先我們把單個閃電看做一個動畫對象,從消失到展示再顯示读恃,落實到動畫上隧膘,alpha 由0到1代态,然后再到0。但是你可能發(fā)現(xiàn)疹吃,出現(xiàn)的速度要比消失的速度要快蹦疑。我們可以借助 TweenSequence 類來實現(xiàn)這個效果。

TweenSequence 是一個動畫序列萨驶,支持配置權(quán)重歉摧,以及對應(yīng)的動畫 Tween。這樣腔呜,我們可以給 alpha 在 [0,1] 區(qū)間做動畫時權(quán)重設(shè)置低一點叁温,[1,0] 時權(quán)重高一點。

    var _animation = TweenSequence([
      TweenSequenceItem(
          tween: Tween(begin: 0.0, end: 1.0)
              .chain(CurveTween(curve: Curves.easeIn)),
          weight: 1),
      TweenSequenceItem(
          tween: Tween(begin: 1.0, end: 0.0)
              .chain(CurveTween(curve: Curves.easeIn)),
          weight: 3),
    ]);

實現(xiàn)后育谬,效果如下:

image

然后券盅,我們用三個隨機的閃電作為一組,做循環(huán)動畫膛檀,控制其序列幀锰镀,完成連續(xù)&不同&隨機的刪掉效果。

    _controller = AnimationController(duration: Duration(seconds: 1), vsync: this);
    _controller.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _controller.reset();
        Future.delayed(Duration(milliseconds: 10)).then((value) {
          initThunderParams();
          _controller.forward();
        });
      }
    });

    var _animation = TweenSequence([
      TweenSequenceItem(
          tween: Tween(begin: 0.0, end: 1.0)
              .chain(CurveTween(curve: Curves.easeIn)),
          weight: 1),
      TweenSequenceItem(
          tween: Tween(begin: 1.0, end: 0.0)
              .chain(CurveTween(curve: Curves.easeIn)),
          weight: 3),
    ]).animate(CurvedAnimation(
      parent: _controller,
      curve: Interval(
        0.0, 1.0,
        curve: Curves.ease,
      ),
    ));

在之前說的一個閃電動畫后面咖刃,新增 .animate() 的配置泳炉,通過控制

Interval(
        0.0, 0.3,
        curve: Curves.ease,
      )

配置該動畫執(zhí)行序列幀的開始和結(jié)束,以及插值器嚎杨。

通過在 addStatusListener 中監(jiān)聽動畫的執(zhí)行狀態(tài)花鹅,在觸發(fā) AnimationStatus.completed 時隨機等待一定時間后,重新開始枫浙。

到此刨肃,一個炫酷的雷電特效就完成了,是不是很簡單箩帚,如果覺得還不錯真友,后面考慮把天氣動畫背景做成插件供有需要的小伙伴使用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市紧帕,隨后出現(xiàn)的幾起案子盔然,更是在濱河造成了極大的恐慌,老刑警劉巖是嗜,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愈案,死亡現(xiàn)場離奇詭異,居然都是意外死亡鹅搪,警方通過查閱死者的電腦和手機站绪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丽柿,“玉大人崇众,你說我怎么就攤上這事掂僵。” “怎么了顷歌?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵锰蓬,是天一觀的道長。 經(jīng)常有香客問我眯漩,道長芹扭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任赦抖,我火速辦了婚禮舱卡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘队萤。我一直安慰自己轮锥,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布要尔。 她就那樣靜靜地躺著舍杜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪赵辕。 梳的紋絲不亂的頭發(fā)上既绩,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機與錄音还惠,去河邊找鬼饲握。 笑死,一個胖子當(dāng)著我的面吹牛蚕键,可吹牛的內(nèi)容都是我干的救欧。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼锣光,長吁一口氣:“原來是場噩夢啊……” “哼颜矿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嫉晶,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎田篇,沒想到半個月后替废,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡泊柬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年椎镣,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兽赁。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡状答,死狀恐怖冷守,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情惊科,我是刑警寧澤拍摇,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站馆截,受9級特大地震影響充活,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蜡娶,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一混卵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧窖张,春花似錦幕随、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至澄阳,卻和暖如春拥知,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背碎赢。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工低剔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肮塞。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓襟齿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親枕赵。 傳聞我的和親對象是個殘疾皇子猜欺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345