『Flutter-繪制篇』實現(xiàn)夢幻的晴晚流星效果

前言

前不久矮瘟,利用周末時間學(xué)習(xí)并完成一個簡單的 Flutter 項目 - 簡悅天氣庐扫,簡約不簡單吟孙,豐富不復(fù)雜澜倦,這是一款簡約風(fēng)格的 flutter 天氣項目聚蝶,提供實時杰妓、多日、24 小時碘勉、臺風(fēng)路徑巷挥、語音播報以及生活指數(shù)等服務(wù),支持定位验靡、刪除倍宾、搜索等操作。

下圖為主頁效果胜嗓,點擊下載 進行體驗:

圖1

項目中運用了大量的自定義繪制 widget高职,首頁豐富的 自定義 chart 效果和炫酷的天氣背景動效。天氣背景動效在不同的天氣氣象下展示不同的效果辞州。目前一共實現(xiàn)了 14 種類別怔锌,其中有,晴变过、晴晚埃元、多云、陰天媚狰、小中大雨岛杀、小中大雪、霧崭孤、霾类嗤、浮塵以及雷暴。背景動效一共分為三層:

  • 背景顏色層辨宠。從上到下的漸變效果
  • 云層遗锣。只有一種圖片,對其位移彭羹、數(shù)量黄伊、染色做不同變化達到不同效果
  • 信息層。包括雨雪派殷、雷暴和晴晚流星效果

之前在 『Flutter-繪制篇』實現(xiàn)炫酷的雨雪特效 一文中介紹過雨雪的實現(xiàn)細節(jié)还最,今天我們聊一聊如何實現(xiàn) 夢幻的晴晚流星 效果,其實實現(xiàn)到不難毡惜,主要是實現(xiàn)的思路和方法拓轻。

話不多說,先看一下動態(tài)效果圖(為了更好預(yù)覽多樣的背景動效经伙,在右上角關(guān)于頁面加了入口扶叉,可以實時切換天氣類型勿锅,查看動態(tài)效果,感興趣的下載體驗):

night_star

陪你去看流星雨落在這地球上枣氧,讓你的淚落在我肩膀溢十,在我肩膀~

仔細觀察不難發(fā)現(xiàn),主要有兩部分組成:

  • 不斷閃爍的星星效果
  • 轉(zhuǎn)瞬即逝的流星效果

所以接下來會圍繞上面兩部分進行詳細講解达吞。

晴晚

Flutter 同 Android 的繪制有很多相似之處张弛,提供了 canvas 和 paint 類作為畫板和畫筆,可以繪制基礎(chǔ)的圖形文字和圖片酪劫,同樣有很多 api 為簡單的圖形添加漸變吞鸭、高斯模糊等炫酷的特效 。

初始化素材和參數(shù)

晴晚由群星組成覆糟,首先繪制一顆星星刻剥,簡單實現(xiàn),就不使用圖片滩字,直接通過 canvas 繪制造虏。Flutter 提供了 MaskFilter.blur(_style, _sigma),并通過 _paint.maskFilter 可以圖形設(shè)置模糊踢械,從而營造星星的發(fā)光效果酗电。

BlurStyle 一共有四種類別,分別為:normal内列、solid撵术、outer和outter,對應(yīng)下面的效果:

blur_style

_sigma 模糊系數(shù)越大越模糊话瞧,在 normal 下分別設(shè)置 0嫩与、1、3交排、7 效果:

sigma

有了星星划滋,接下來就需要創(chuàng)建星星,并賦予其屬性埃篓,讓其展示在屏幕上处坪。

class _StarParam {
  double x;
  double y;
  double alpha = 0.0;
  double scale;

  _StarParam();

  void init() {
    alpha = Random().nextDouble();
    scale = Random().nextDouble() * 0.1 + 0.6;
    x = Random().nextDouble() * 1.wp / scale;
    y = Random().nextDouble() * 0.3.hp / scale;
  }
}

除了坐標 x,y 屬性外,alpha 用于后面做動畫架专, scale 用于模擬遠近的效果同窘,我們創(chuàng)建 100 個隨機分布在 1*width0.3*height 的區(qū)域內(nèi)。

繪制

有參數(shù)后部脚,直接開始繪制想邦,只需要調(diào)用 canvas.drawCircle() 即可:

  void drawStar(_StarParam param, Canvas canvas) {
    if (param == 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, param.alpha, 0,
    ]);
    _paint.colorFilter = identity;
    canvas.scale(param.scale);
    canvas.drawCircle(Offset(param.x, param.y), 3, _paint);
    canvas.restore();
  }

實現(xiàn)效果如下:

image

動畫

接下來就是讓星星“動”起來。有點類似之前實現(xiàn)雨雪的邏輯委刘,創(chuàng)建一個持續(xù)運行的動畫丧没,在動畫回調(diào)中不斷的 setState()鹰椒,對于星星對象,用一個屬性 alpha 字段呕童,不斷自增或自減來達到閃爍的效果漆际。

  void move() {
    if (reverse == true) {
      alpha -= 0.01;
      if (alpha < 0) {
        reset();
      }
    } else {
      alpha += 0.01;
      if (alpha > 1.2) {
        reverse = true;
      }
    }
  }

這里,當(dāng) alpha 值達到閾值時拉庵,將 reverse 字段置為 true灿椅,此時開始自減,做消失動畫钞支,因為很多屬性都是隨機,最終就營造出群星閃爍的效果操刀。

stars

流星

初始化素材和參數(shù)

一開始準備從各種圖片素材網(wǎng)上試著找一下流星的資源烁挟,結(jié)果要么效果不滿意,要么就是要各種收費和關(guān)注等等骨坑。轉(zhuǎn)念一想撼嗓,還不如自己實現(xiàn)來的快,無非就是一條漸變細長形圓角矩形欢唾。

圓角矩形通過 canvas.drawRRect() 可以實現(xiàn)且警,為了實現(xiàn)流星的拖尾效果,借用 paint#shader 的屬性礁遣,達到漸變的效果斑芜。

  var gradient = ui.Gradient.linear(
    const Offset(0, 0),
    Offset(_meteorWidth, 0),
    <Color>[const Color(0xFFFFFFFF), const Color(0x00FFFFFF)],
  );
  _meteorPaint.shader = gradient;
image

我們隨機創(chuàng)建4組流星。

繪制

為了營造更真實的流星劃過效果祟霍,水平效果是不滿足的杏头,需要對其進行角度翻轉(zhuǎn)。

一開始沸呐,打算通過 y/x=tan(Θ) 方式進行繪制醇王,后來考慮到要做動畫,各種動態(tài)計算崭添,干脆直接使用 canvas.rotate()canvas.translate() 的方法寓娩,更加方便,更加的好理解呼渣。

  void drawMeteor(_MeteorParam param, Canvas canvas) {
    canvas.save();
    var gradient = ui.Gradient.linear(
      const Offset(0, 0),
      Offset(_meteorWidth, 0),
      <Color>[const Color(0xFFFFFFFF), const Color(0x00FFFFFF)],
    );
    _meteorPaint.shader = gradient;
    canvas.rotate(pi * param.radians);
    canvas.translate(param.translateX, tan(pi * 0.1) *_meteorWidth + param.translateY);
    canvas.drawRRect(
        RRect.fromLTRBAndCorners(0, 0, _meteorWidth, _meteorHeight,
            topLeft: _radius,
            topRight: _radius,
            bottomRight: _radius,
            bottomLeft: _radius),
        _meteorPaint);
    canvas.restore();
  }

這里 rotate 和 translate 的順序不能寫反棘伴,需要先旋轉(zhuǎn)再平移,因為旋轉(zhuǎn)的點在左側(cè)端徙邻,如果先平移再旋轉(zhuǎn)排嫌,會導(dǎo)致運動過程中,流星不再一條直線上運行缰犁。效果如下:

image

動畫

復(fù)用晴晚的 AnimationController,通過不斷的改變 translateX 值淳地,來完成劃過的動畫效果怖糊。

class _MeteorParam {
  double translateX;
  double translateY;
  double radians;
  void reset() {
    translateX = 1.0.wp + Random().nextDouble() * 20.0.wp;
    radians = -Random().nextDouble() * 0.07 - 0.05;
    translateY = Random().nextDouble() * 0.5.hp;
  }

  void move() {
    translateX -= 20;
    if (translateX <= -1.0.wp) {
      reset();
    }
  }
}

這里初始化 1.0.wp + Random().nextDouble() * 20.0.wp,使其初始化位置分布在 [1, 20] * width 的位置颇象,而在的動畫過程中不斷 translateX -= 20伍伤,當(dāng)滑過一個屏幕則重新初始化位置。

image

到這遣钳,夢幻的晴晚和流星效果就實現(xiàn)了扰魂,預(yù)告一下下期-炫酷的雷暴效果。

?著作權(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
  • 文/潘曉璐 我一進店門愿棋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來科展,“玉大人,你說我怎么就攤上這事糠雨〔哦茫” “怎么了?”我有些...
    開封第一講書人閱讀 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

推薦閱讀更多精彩內(nèi)容