我的编程空间,编程开发者的网络收藏夹
学习永远不晚

利用Android实现光影流动特效的方法详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

利用Android实现光影流动特效的方法详解

前言

Flutter 的画笔类 Paint 提供了很多图形绘制的配置属性,来供我们绘制更丰富多彩的图形。前面几篇我们介绍了 shader 属性来绘制全屏渐变的聊天气泡背景、渐变流动的边框和毛玻璃效果的背景图片,具体可以参考下面几篇文章。

  • 让你的聊天气泡丰富多彩!
  • 手把手教你实现一个流动的渐变色边框
  • 利用光影变化构建立体旋转效果
  • Flutter 实现背景图片毛玻璃效果

本篇我们引入一个 Paint 类新的属性:maskFilter,再结合之前的 shader 和动画,看看能玩出什么花样。

MaskFilter 类简介

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; 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. 创建一个遮罩过滤器将要绘制的形状进行模糊处理。通常用于实现近似阴影的效果。style 参数控制绘制的效果类型 (BlurStyle 枚举);sigma 参数控制效果的尺寸,实际就是使用的高斯模糊的标准差。sigma 的值必须大于0,这个值在像素上,大致是效果范围的半径值。模糊处理比较耗性能,因此要有节制地使用。

因为效果有点类似阴影,而且比较耗性能,因此如果仅仅是要绘制阴影的话,官方推荐是使用 Canvas 的 drawShadow 方法替代这个效果。

MaskFilter 的几种效果对比

看文档使用起来比较简单,我们来看看 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 实现的效果有点像设计师给的各种发光效果,比如内发光、外发光。这时候,配合动画可以玩点有趣的东西了。

光影流动效果1

我们利用之前实现的全屏渐变色聊天气泡中的效果,通过动画控制一个圆形上下移动看看会有什么效果,感觉是一个彩色的光球在上升和下降。

上面效果的实现代码如下,基本的逻辑如下:

  • 整个绘图范围通过 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);
}

光影流动效果2

上面的效果是一个圆形的,我们换成多个并排的矩形来看看,这种效果感觉整个填充区域的颜色在不停流动变幻,就好像有霓虹灯照耀的感觉。

上面效果的实现代码如下,其实就是通过循环绘制了一排矩形,然后通过动画控制上下移动位置。

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 类型的模糊效果,然后让一串圆形沿屏幕对角线从收起到展开,再从展开到收起,效果如下所示,光束球发出来的时候,感觉就像是从左上角发了一个大招。

上面的实现代码如下所示,就是通过控制圆形的中心位置实现对角线移动的,间距则是随着动画值的增加而拉大,因此会有发射的效果。

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:光影沿贝塞尔曲线流动

我们来把图形通过贝塞尔曲线控制绘制位置,来画一组图形,就能够实现光影沿着贝塞尔曲线流动的效果了。这里我们沿着两条首尾相接的贝塞尔曲线,绘制了一组正方形,看起来就像光影在一个闭合的图形中来回穿梭一样。

实现代码和之前的类似,只是矩形的位置通过贝塞尔曲线生成,如下所示。

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,
    );
  }
}

总结

本篇介绍了 Flutter 画笔类 PainterMaskFilter 的使用,MaskFilter 的应用效果就是让形状能有类似发光的效果。我们结合之前的几篇文章用到的绘制效果完成了一场“光影秀”,视觉上看起来还是很美的。这也是开发过程中绘图的乐趣之一,看着自己画出来很美的效果也还是很有成就感的。

到此这篇关于利用Android实现光影流动特效的方法详解的文章就介绍到这了,更多相关Android光影流动特效内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

利用Android实现光影流动特效的方法详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何利用Android实现光影流动特效

本篇内容主要讲解“如何利用Android实现光影流动特效”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何利用Android实现光影流动特效”吧!MaskFilter 类简介MaskFilter
2023-07-02

Android中View的炸裂特效实现方法详解

本文实例讲述了Android中View的炸裂特效实现方法。分享给大家供大家参考,具体如下: 前几天微博上被一个很优秀的 Android 开源组件刷屏了 - ExplosionField,效果非常酷炫,有点类似 MIUI 卸载 APP 时的动
2022-06-06

详解Android Material设计中阴影效果的实现方法

View可以投下的阴影,一个View的elevation值决定了它的阴影的大小和绘制的顺序。可以设置一个视图的elevation,在布局中使用属性:android:elevation
2022-06-06

Android实现左右滑动效果的方法详解

本示例演示在Android中实现图片左右滑动效果。关于滑动效果,在Android中用得比较多,本示例实现的滑动效果是使用ViewFlipper来实现的,当然也可以使用其它的View来实现。接下来就让我们开始实现这种效果。为了方便大家理解,我
2022-06-06

利用CSS实现鼠标悬停时的投影特效的技巧和方法

利用CSS实现鼠标悬停时的投影特效的技巧和方法在现代网页设计中,利用CSS实现各种特效已经成为一种常见的做法。其中,鼠标悬停时的投影效果常常被用来增加交互性和视觉效果。本文将介绍实现这种特效的技巧和方法,并提供具体的代码示例。首先,我们需要
2023-10-25

利用CSS实现鼠标悬停时的阴影特效的技巧和方法

在网页设计中,鼠标悬停效果是常见的交互方式之一。通过让元素在鼠标悬停时显示特定的效果,可以增加用户的体验和网站的吸引力。其中,利用CSS实现鼠标悬停时的阴影特效是一种常用且简单的方法。本文将介绍该技巧的实现方法,并给出具体的代码示例。一、简
2023-10-21

利用CSS实现元素的投影效果的方法

利用CSS实现元素的投影效果的方法,需要具体代码示例在网页设计中,投影效果可以为页面元素增添立体感和层次感,使页面更加丰富和生动。CSS(层叠样式表)为实现投影效果提供了多种方法和属性。一、box-shadow属性box-shadow属性是
利用CSS实现元素的投影效果的方法
2023-11-21

利用CSS实现元素的阴影效果的方法

利用CSS实现元素的阴影效果的方法,需要具体代码示例在网页设计中,为元素添加阴影效果能够使页面更加生动、立体。利用CSS,我们可以通过简单的代码实现各种不同的阴影效果。本文将为大家介绍几种常见的实现元素阴影效果的方法,并给出具体的代码示例。
利用CSS实现元素的阴影效果的方法
2023-11-21

利用CSS实现元素的边框阴影效果的方法

利用CSS实现元素的边框阴影效果的方法,需要具体代码示例近年来,网页设计越来越重视用户体验,目标是尽可能提供更真实、更有层次感的页面效果。元素阴影效果就是其中之一,它能够给页面增添一种立体的感觉,使得元素更加突出和吸引人。本文将介绍如何利用
利用CSS实现元素的边框阴影效果的方法
2023-11-21

Android实现Activity界面切换添加动画特效的方法

本文以实例形式展示了Android实现Activity界面切换添加动画特效的方法,对于Android程序设计人员来说有很好的参考借鉴价值。具体方法如下: 了解Android程序设计的人应该知道,在Android 2.0之后有了overrid
2022-06-06

利用CSS实现鼠标悬停时的抖动特效的技巧和方法

鼠标悬停时的抖动特效可以为网页添加一些动感和趣味性,吸引用户的注意力。在这篇文章中,我们将介绍一些利用CSS实现鼠标悬停抖动特效的技巧和方法,并提供具体的代码示例。抖动的原理在CSS中,我们可以使用关键帧动画(keyframes)和tran
2023-10-21

Android中利用动态加载实现手机淘宝的节日特效

相信去年圣诞节打开过手机淘宝的童鞋都会对当时的特效记忆犹新吧:全屏飘雪,旁边还有个小雪人来控制八音盒背景音乐的播放,让人有种身临其境的感觉,甚至忍不住想狠狠购物了呢(误),大概就是下面这个样子滴:嗯,确实很炫,那么我们一步步去分析是如何实现
2022-06-06

利用CSS实现图片遮罩特效的技巧和方法

在网页设计中,为图片增加一些特效可以提升用户的浏览体验。其中,图片遮罩特效是一种常见且具有吸引力的效果,可以为图片增添一种神秘感和美感。本文将介绍利用CSS实现图片遮罩特效的技巧和方法,并提供具体的代码示例供参考。一、利用CSS的伪元素实现
2023-10-21

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录