您好,登錄后才能下訂單哦!
本篇內容主要講解“如何利用Android實現光影流動特效”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何利用Android實現光影流動特效”吧!
MaskFilter 類,顧名思義是遮罩過濾器,也就是在繪制過程中給圖像加一層遮罩效果,這個遮罩效果是通過某種變換函數實現的。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. 遮罩過濾器應用于要繪制的形狀,其實就是一個函數,接收一個彩色像素位圖,然后返回另一個彩色像素位圖。
在 Flutter 里面,目前只提供了一個 MaskFilter 的命名構造函數方式實例化,就是模糊效果。這個模糊效果和我們的圖片模糊有點類似,也是使用高斯模糊,只是多了一個模糊樣式參數。定義如下:
const MaskFilter.blur( this._style, this._sigma, )
關于這個方法的說明,為了便于理解,將官方的文檔翻譯如下:
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; Thesigma
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. 創建一個遮罩過濾器將要繪制的形狀進行模糊處理。通常用于實現近似陰影的效果。style
參數控制繪制的效果類型 (BlurStyle
枚舉);sigma
參數控制效果的尺寸,實際就是使用的高斯模糊的標準差。sigma
的值必須大于0,這個值在像素上,大致是效果范圍的半徑值。模糊處理比較耗性能,因此要有節制地使用。
因為效果有點類似陰影,而且比較耗性能,因此如果僅僅是要繪制陰影的話,官方推薦是使用 Canvas 的 drawShadow
方法替代這個效果。
看文檔使用起來比較簡單,我們來看看 MaskFilter
的幾種不同的模糊樣式的區別。模糊樣式通過 style 參數控制,BlurStyle
枚舉取值有以下四種。
normal
:形狀內外都會做模糊處理,可以用于繪制圖形表面投影的陰影效果。
solid
:內部不模糊,外側模糊,會讓圖形看起來更明亮,類似熒光的效果。
outer
:外側模糊,內部沒有東西,適用于繪制半透明圖形的陰影。
inner
:外側不處理,內部模糊,看起來有種內發光的效果。
看文檔說明我們是體會不到具體的呈現效果的,我們繪制同一個圖形的不同效果對比看看。
outer
類型有點奇怪,中間掏空了,不過看上去還挺酷的。我畫了一個不模糊的疊加上去,發現組合后的效果就和 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); }
通過繪制的效果發現,其實 MaskFilter 實現的效果有點像設計師給的各種發光效果,比如內發光、外發光。這時候,配合動畫可以玩點有趣的東西了。
我們利用之前實現的全屏漸變色聊天氣泡中的效果,通過動畫控制一個圓形上下移動看看會有什么效果,感覺是一個彩色的光球在上升和下降。
上面效果的實現代碼如下,基本的邏輯如下:
整個繪圖范圍通過 shader
預填充,使得圓形移動過程的填充色漸變變化,和我們聊天氣泡中的效果一樣;
通過 transform
動畫控制顏色旋轉,使得繪制的圓形的填充顏色旋轉,看起來會有立體感;
通過 maskFilter,設置為 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); }
上面的效果是一個圓形的,我們換成多個并排的矩形來看看,這種效果感覺整個填充區域的顏色在不停流動變幻,就好像有霓虹燈照耀的感覺。
上面效果的實現代碼如下,其實就是通過循環繪制了一排矩形,然后通過動畫控制上下移動位置。
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, ); } }
這一次我們使用 outer
類型的模糊效果,然后讓一串圓形沿屏幕對角線從收起到展開,再從展開到收起,效果如下所示,光束球發出來的時候,感覺就像是從左上角發了一個大招。
上面的實現代碼如下所示,就是通過控制圓形的中心位置實現對角線移動的,間距則是隨著動畫值的增加而拉大,因此會有發射的效果。
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, ); } }
我們來把圖形通過貝塞爾曲線控制繪制位置,來畫一組圖形,就能夠實現光影沿著貝塞爾曲線流動的效果了。這里我們沿著兩條首尾相接的貝塞爾曲線,繪制了一組正方形,看起來就像光影在一個閉合的圖形中來回穿梭一樣。
實現代碼和之前的類似,只是矩形的位置通過貝塞爾曲線生成,如下所示。
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, ); } }
到此,相信大家對“如何利用Android實現光影流動特效”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。