欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用Android實現(xiàn)光影流動特效的方法詳解

 更新時間:2022年07月04日 08:51:51   作者:島上碼農(nóng)  
Flutter 的畫筆類 Paint 提供了很多圖形繪制的配置屬性,來供我們繪制更豐富多彩的圖形。本篇我們引入一個 Paint 類新的屬性:maskFilter,再結(jié)合之前的 shader 和動畫,制作出光影流動特效,感興趣的可以嘗試一下

前言

Flutter 的畫筆類 Paint 提供了很多圖形繪制的配置屬性,來供我們繪制更豐富多彩的圖形。前面幾篇我們介紹了 shader 屬性來繪制全屏漸變的聊天氣泡背景、漸變流動的邊框和毛玻璃效果的背景圖片,具體可以參考下面幾篇文章。

本篇我們引入一個 Paint 類新的屬性:maskFilter,再結(jié)合之前的 shader 和動畫,看看能玩出什么花樣。

MaskFilter 類簡介

MaskFilter 類,顧名思義是遮罩過濾器,也就是在繪制過程中給圖像加一層遮罩效果,這個遮罩效果是通過某種變換函數(shù)實現(xiàn)的。Flutter 官方文檔的說明如下,可以看出其實就是對位圖的顏色處理。

A mask filter to apply to shapes as they are painted. A mask filter is a function that takes a bitmap of color pixels, and returns another bitmap of color pixels. 遮罩過濾器應(yīng)用于要繪制的形狀,其實就是一個函數(shù),接收一個彩色像素位圖,然后返回另一個彩色像素位圖。

在 Flutter 里面,目前只提供了一個 MaskFilter 的命名構(gòu)造函數(shù)方式實例化,就是模糊效果。這個模糊效果和我們的圖片模糊有點類似,也是使用高斯模糊,只是多了一個模糊樣式參數(shù)。定義如下:

const MaskFilter.blur(
  this._style,
  this._sigma,
)

關(guān)于這個方法的說明,為了便于理解,將官方的文檔翻譯如下:

Creates a mask filter that takes the shape being drawn and blurs it. This is commonly used to approximate shadows. The style argument controls the kind of effect to draw; The sigma argument controls the size of the effect. It is the standard deviation of the Gaussian blur to apply. The value must be greater than zero. The sigma corresponds to very roughly half the radius of the effect in pixels. A blur is an expensive operation and should therefore be used sparingly. The arguments must not be null. 創(chuàng)建一個遮罩過濾器將要繪制的形狀進行模糊處理。通常用于實現(xiàn)近似陰影的效果。style 參數(shù)控制繪制的效果類型 (BlurStyle 枚舉);sigma 參數(shù)控制效果的尺寸,實際就是使用的高斯模糊的標準差。sigma 的值必須大于0,這個值在像素上,大致是效果范圍的半徑值。模糊處理比較耗性能,因此要有節(jié)制地使用。

因為效果有點類似陰影,而且比較耗性能,因此如果僅僅是要繪制陰影的話,官方推薦是使用 Canvas 的 drawShadow 方法替代這個效果。

MaskFilter 的幾種效果對比

看文檔使用起來比較簡單,我們來看看 MaskFilter 的幾種不同的模糊樣式的區(qū)別。模糊樣式通過 style 參數(shù)控制,BlurStyle 枚舉取值有以下四種。

  • normal:形狀內(nèi)外都會做模糊處理,可以用于繪制圖形表面投影的陰影效果。
  • solid:內(nèi)部不模糊,外側(cè)模糊,會讓圖形看起來更明亮,類似熒光的效果。
  • outer:外側(cè)模糊,內(nèi)部沒有東西,適用于繪制半透明圖形的陰影。
  • inner:外側(cè)不處理,內(nèi)部模糊,看起來有種內(nèi)發(fā)光的效果。

看文檔說明我們是體會不到具體的呈現(xiàn)效果的,我們繪制同一個圖形的不同效果對比看看。

outer 類型有點奇怪,中間掏空了,不過看上去還挺酷的。我畫了一個不模糊的疊加上去,發(fā)現(xiàn)組合后的效果就和 solid 模式一樣。

上面繪制的代碼如下。

@override
void paint(Canvas canvas, Size size) {
  var paint = Paint();
  paint.style = PaintingStyle.fill;
  var center = Offset(size.width / 2, size.height / 2);
  var radius = 80.0;
  paint.color = Colors.blue[400]!;
  paint.maskFilter = MaskFilter.blur(BlurStyle.outer, 20.0);
  canvas.drawCircle(center, radius, paint);
}

光影流動

通過繪制的效果發(fā)現(xiàn),其實 MaskFilter 實現(xiàn)的效果有點像設(shè)計師給的各種發(fā)光效果,比如內(nèi)發(fā)光、外發(fā)光。這時候,配合動畫可以玩點有趣的東西了。

光影流動效果1

我們利用之前實現(xiàn)的全屏漸變色聊天氣泡中的效果,通過動畫控制一個圓形上下移動看看會有什么效果,感覺是一個彩色的光球在上升和下降。

上面效果的實現(xiàn)代碼如下,基本的邏輯如下:

  • 整個繪圖范圍通過 shader 預(yù)填充,使得圓形移動過程的填充色漸變變化,和我們聊天氣泡中的效果一樣;
  • 通過 transform 動畫控制顏色旋轉(zhuǎn),使得繪制的圓形的填充顏色旋轉(zhuǎn),看起來會有立體感;
  • 通過 maskFilter,設(shè)置為 solid 模式讓圓形有熒光的效果;
  • 通過動畫控制圓形上升和下降。
void _drawMovingCircle(Canvas canvas, Size size, Paint paint) {
  var radius = 80.0;
  paint.shader = LinearGradient(
    begin: Alignment.topCenter,
    end: Alignment.bottomCenter,
    colors: [
      Colors.black87,
      Colors.purple,
      Colors.blue,
      Colors.green,
      Colors.yellow[500]!,
      Colors.orange,
      Colors.red[400]!
    ].reversed.toList(),
    tileMode: TileMode.clamp,
    transform: GradientRotation(
      animationValue * 2 * pi,
    ),
  ).createShader(Offset(0, 0) & size);

  paint.maskFilter = MaskFilter.blur(BlurStyle.solid, 20.0);
  canvas.drawCircle(
      Offset(size.width / 2, size.height * animationValue), radius, paint);
}

光影流動效果2

上面的效果是一個圓形的,我們換成多個并排的矩形來看看,這種效果感覺整個填充區(qū)域的顏色在不停流動變幻,就好像有霓虹燈照耀的感覺。

上面效果的實現(xiàn)代碼如下,其實就是通過循環(huán)繪制了一排矩形,然后通過動畫控制上下移動位置。

void _drawMultiMovingRect(Canvas canvas, Size size, Paint paint) {
  paint.shader = LinearGradient(
    begin: Alignment.topCenter,
    end: Alignment.bottomCenter,
    colors: [
      Colors.black87,
      Colors.purple,
      Colors.blue,
      Colors.green,
      Colors.yellow[500]!,
      Colors.orange,
      Colors.red[400]!
    ].reversed.toList(),
    tileMode: TileMode.clamp,
    transform: GradientRotation(
      animationValue * 2 * pi,
    ),
  ).createShader(Offset(0, 0) & size);

  paint.maskFilter = MaskFilter.blur(BlurStyle.solid, 20.0);
  var count = 10;
  for (var i = 0; i < count + 1; ++i) {
    canvas.drawRect(
      Offset(size.width / count * i, size.height * animationValue) &
          Size(size.width / count, size.width / count * 2),
      paint,
    );
  }
}

光影流動效果3

這一次我們使用 outer 類型的模糊效果,然后讓一串圓形沿屏幕對角線從收起到展開,再從展開到收起,效果如下所示,光束球發(fā)出來的時候,感覺就像是從左上角發(fā)了一個大招。

上面的實現(xiàn)代碼如下所示,就是通過控制圓形的中心位置實現(xiàn)對角線移動的,間距則是隨著動畫值的增加而拉大,因此會有發(fā)射的效果。

void _drawMultiMovingCircle(Canvas canvas, Size size, Paint paint) {
  paint.shader = LinearGradient(
    begin: Alignment.topCenter,
    end: Alignment.bottomCenter,
    colors: [
      Colors.black87,
      Colors.purple,
      Colors.blue,
      Colors.green,
      Colors.yellow[500]!,
      Colors.orange,
      Colors.red[400]!
    ].reversed.toList(),
    tileMode: TileMode.clamp,
    transform: GradientRotation(
      animationValue * 2 * pi,
    ),
  ).createShader(Offset(0, 0) & size);

  paint.maskFilter = MaskFilter.blur(BlurStyle.outer, 20.0);
  var count = 10;
  for (var i = 0; i < count + 1; ++i) {
    canvas.drawCircle(
      Offset(size.width * i / count * animationValue,
          size.height * i / count * animationValue),
      size.width / count,
      paint,
    );
  }
}

光影流動效果4:光影沿貝塞爾曲線流動

我們來把圖形通過貝塞爾曲線控制繪制位置,來畫一組圖形,就能夠?qū)崿F(xiàn)光影沿著貝塞爾曲線流動的效果了。這里我們沿著兩條首尾相接的貝塞爾曲線,繪制了一組正方形,看起來就像光影在一個閉合的圖形中來回穿梭一樣。

實現(xiàn)代碼和之前的類似,只是矩形的位置通過貝塞爾曲線生成,如下所示。

void _drawRectsUsingBezier(Canvas canvas, Size size, Paint paint) {
  paint.shader = LinearGradient(
    begin: Alignment.topCenter,
    end: Alignment.bottomCenter,
    colors: [
      Colors.black87,
      Colors.purple,
      Colors.blue,
      Colors.green,
      Colors.yellow[500]!,
      Colors.orange,
      Colors.red[400]!
    ].reversed.toList(),
    tileMode: TileMode.clamp,
    transform: GradientRotation(
      animationValue * 2 * pi,
    ),
  ).createShader(Offset(0, 0) & size);

  paint.maskFilter = MaskFilter.blur(BlurStyle.outer, 2);
  final height = 120.0;
  var p0 = Offset(0, size.height / 2 + height);
  var p1 = Offset(size.width / 4, size.height / 2 - height);
  var p2 = Offset(size.width * 3 / 4, size.height / 2 + height);
  var p3 = Offset(size.width, size.height / 2 - height);
  var count = 150;
  var squareSize = 20.0;
  for (var t = 1; t <= count; t += 1) {
    var curvePoint =
        BezierUtil.get3OrderBezierPoint(p0, p1, p2, p3, t / count);

    canvas.drawRect(
      curvePoint & Size(squareSize, squareSize),
      paint,
    );
  }

  for (var t = 1; t <= count; t += 1) {
    var curvePoint =
        BezierUtil.get3OrderBezierPoint(p3, p1, p2, p0, t / count);

    canvas.drawRect(
      curvePoint & Size(squareSize, squareSize),
      paint,
    );
  }
}

總結(jié)

本篇介紹了 Flutter 畫筆類 PainterMaskFilter 的使用,MaskFilter 的應(yīng)用效果就是讓形狀能有類似發(fā)光的效果。我們結(jié)合之前的幾篇文章用到的繪制效果完成了一場“光影秀”,視覺上看起來還是很美的。這也是開發(fā)過程中繪圖的樂趣之一,看著自己畫出來很美的效果也還是很有成就感的。

到此這篇關(guān)于利用Android實現(xiàn)光影流動特效的方法詳解的文章就介紹到這了,更多相關(guān)Android光影流動特效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論