Android利用Flutter实现立体旋转效果
作者:岛上码农 发布时间:2023-06-20 08:20:32
前言
之前我们提到了 CustomPaint er
的 Paint
可以使用渐变(GradientShader
)来填充绘制的图形,本篇我们来介绍使用图片填充,并且配合动画实现“立体”旋转效果,之所以给“立体”加上引号,是因为实际是通过填充图片自身的光影效果旋转后看起来像是立体效果一样。下面是实现的效果图。
ImageShader 简介
ImageShader
的定义如下,我们来看看各个参数的用途。
image
:用于填充的图像,是Image
类,注意这个Image
类定义在dart:ui
库中,并不是我们用于构建图像组件的Widget
下面的Image
类。tmx
:图形在 x 轴的处理方式,即当被填充的宽度与图片宽度不匹配时,在横轴方向如何填充。tmy
:图形在y 轴的处理方式,即当被填充的高度与图片高度不匹配时,在纵轴方向如何填充。matrix4
:对填充图像的三维空间的平移、旋转等变换操作。filterQuality
:当图片尺寸和被填充图形的尺寸不一致时,采样的质量,有高(high
)、中 (medium
)、低(low
)三类。
ImageShader(
Image image,
TileMode tmx,
TileMode tmy,
Float64List matrix4,
{
FilterQuality? filterQuality,
}
)
tmx
和 tmy
是 TileMode
枚举,有以下几种取值:
clamp
:图片不能完整填充图形时,使用最接近图形边缘的颜色进行填充,其实就是边缘的延伸。比如同时这是 tmx 和 tmy 都为 TileMode.clamp
的时候的效果图如下。
repeated
:这个好理解,就是在各自方向重复。
decal
:就是这个方向不做任何处理,使用透明填充,比如我们将上面的 tmy
改成 decal
,就只会在 x 轴重复了。
mirror
:顾名思义,就是镜像填充,下面是 tmx
为 mirror
,tmy
为 repeated
的效果图。
构建 ui.Image对象
要使用 ImageShader
,我们首先要从图片资源中构建ui.Image
对象。这需要将图片文件按ByteData
二进制方式读取,在将二进制文件解码成为 ui.Image
对象。这个操作是异步的,因此在操作没完成前不能使用图像资源,我们设置了一个isImageLoaded
布尔值标识图像是否加载完成。
final ByteData data = await rootBundle.load('images/beauty.jpg');
fillImage = await loadImage(Uint8List.view(data.buffer));
Future<ui.Image> loadImage(Uint8List img) async {
final Completer<ui.Image> completer = Completer();
ui.decodeImageFromList(img, (ui.Image img) {
setState(() {
isImageLoaded = true;
});
return completer.complete(img);
});
return completer.future;
}
使用 ImageShader 填充形状
使用 ImageShader
填充和 GradientShader
类似,按我们上面说的参数构建一个 ImageShader
对象就可以了,代码如下。注意,Paint
对象的填充方式必须是 fill
,如果是空心的话是看不到效果的。
@override
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.style = PaintingStyle.fill;
paint.shader = ImageShader(
image,
TileMode.mirror,
TileMode.repeated,
Matrix4.identity().storage,
filterQuality: FilterQuality.high,
);
canvas.drawRect(Rect.fromLTRB(0, 0, size.width, size.height), paint);
}
立体旋转效果实现
立体效果需要利用填充图像的光影效果,因此我们需要找一张图片,比如明暗不同,或色彩不同的,这样旋转起来就会感觉是立体的。旋转的话使用 Matrix4的旋转变换就行。同时,为了让旋转过程展示的图像不固定,我们旋转的时候可以通过Matrix4的平移显示不同图形的区域。下面是我们用于测试的两张图片。
实现的代码如下所示,其中animationValue
是动画过程中 Animation
对象的值,我们的动画时长设置为10秒。这里我们绘制的其实是一个圆形,只是因为填充图像在不停的旋转,且展示的图像不同就看起来有了立体效果。
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.style = PaintingStyle.fill;
paint.shader = ImageShader(
image,
TileMode.mirror,
TileMode.mirror,
(Matrix4.identity()
..translate(5 * animationValue, 5 * animationValue)
..scaled(0.5)
..rotateZ(2 * pi * animationValue))
.storage,
filterQuality: FilterQuality.high,
);
Offset center = Offset(size.width / 2, size.height / 2);
canvas.drawCircle(center, 200, paint);
}
下图是换了星球图片的运行效果,大家也可以调整 ImageShader
的参数看看其他参数的效果。
来源:https://juejin.cn/post/7110955358445076487


猜你喜欢
- java 多线程死锁 相信有过多线程编程经验的朋友,都吃过死锁的苦。除非你不使用多线程,否则死锁的可能性会一直存在。为什么会出现
- 一、直接插入排序基本思想:将一个记录插入到已排序的有序表中,使插入后的表仍然有序对初始关键字{49 38 65 97 76 13 27 49
- 本文实例为大家分享了java实现画图板功能的具体代码,供大家参考,具体内容如下一、介绍这个画图板主要实现的功能是画矩形(矩形使用的是一个函数
- 下面我们来探究Android如何实现关机,重启;在Android中这种操作往往需要管理员级别,或者rootAndroid实现的方式如下几种:
- 在android studio中存储数据有三个方法,分别是:(1)简单存储——SharedPreferences(2)文件存储:内部存储——
- 这篇文章主要介绍了Java Collection集合iterator方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的
- Java时间格式转换大全import java.text.*;import java.util.Calendar;public class
- 1.任何一门编程语言均有相关数据类型。C#也不例外,其基本数据类型有int,short,long,float,double,string等。
- SpringMVC异常处理机制(一)项目前准备首先参照文章Spring课程工程构建+SpringMVC简介及其快速入门搭建项目搭建好一个项目
- 1.springBoot的依赖确定项目中包含可以注解的依赖<dependency> <group
- java POI合并两个word文档有需要的可以将主函数中写死的地方改为一个Listimport java.io.FileInputStre
- like模糊查询特殊字符报错转义处理方案1 <if test="projectName!
- 我就废话不多说了,大家还是直接看代码吧~import java.io.UnsupportedEncodingException;import
- 这两天因为要做一个随机的地图生成系统,所以一直在研究随机迷宫生成算法,好吧,算是有一点小小的成果。随机迷宫生成我自己的理解简而言之分为以下几
- 在上面的例子中多次使用到了Thread类的join方法。我想大家可能已经猜出来join方法的功能是什么了。对,join方法的功能就是使异步执
- Android动画 实现开关按钮动画(属性动画之平移动画),最近做项目,根据项目需求,有一个这样的功能,实现类似开关的动画效果,经过自己琢磨
- 解决方案1:禁用缓存,前一次使用的方法,在电脑上各浏览器都没问题,但在ipad、安卓手机上仍有问题解决方案2:禁用浏览器后退键 javasc
- 控制器Controller控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现。控制器负责解析用户的请求并将其转换为一个
- 一、Mybatis执行流程具体分析Mybatis是如何操作数据库的!1、定义我们的核心配置文件的路径,这个路径是从target/classe
- Android 打开相册选择单张图片实现代码