- 3、我们是否可以将背景形状、颜色、动画随机改变以使它:a. 看起来很酷,b. 足够满足1和2的随机性,c. 不会分散你看时间的注意力?
我以前从未完成过任何艺术,或者根本没有做过Flutter,所以我着手建造这样的时钟。
粒子与随机性
第一次迭代只是一个时钟。如上所述,我从示例数字时钟项目
开始,而不是从头开始。创建的第一个Widget是一个CustomPainter
,仅绘制了一个圆圈。很不错,但是从长远来看不是很有趣。
随机性增加了,从颜色开始,然后确定位置和大小。所有逻辑仍然在单个CustomPainter
的paint()
方法中,这几乎使动画变得不可能,因此需要将一堆逻辑重构成一个简单的粒子系统。我看了Flutter Vignettes
项目,以寻求启发。
https://flutter.gskinner.com/
这时候,制作模拟粒子时钟的想法变得更加明显了。
将粒子变成模拟时钟
提出想法后,我要做的就是编写代码以实现所有目标。数学部分花费了我最多的时间才最终完成,大多是我多年以前学过的数学,不过好多我都忘记了,角度,弧度,PI和类似的东西,网上又许多解决方案,但是你将不得不做一些修改以适应您的用例。
以下是获取时针弧度的方法:
/// Gets the radians of the hour hand.
double _getHourRadians() =>
(time.hour * pi / 6) +
(time.minute * pi / (6 * 60)) +
(time.second * pi / (360 * 60));
我在计算中包括了time.minute
和time.second
,以使时针在数小时之间平滑地动画。
然后,从弧度获得2D运动矢量就很简单了。
// Particle movement vector.
p.vx = sin(-angle);
p.vy = cos(-angle);
现在,p.vx
和p.vy
拥有 有关粒子在每个动画滴答声中
应该移动多远的信息,同时保持在时针的角度里。
除了钟针外,粒子还可能作为噪音产生。然后它将从中心沿随机方向发射。在发出时,还将为所有粒子分配随机的速度
,颜色
,大小
和绘画样式
(填充或笔划)。这使时钟看起来更有趣。
时钟的早期版本中。这有四分之一标记,有些粒子有速度标记。时钟的第一个版本只是粒子,这里就不花时间截图演示了。
使用Flutter Widgets 添加图层
到现在为止,所有内容都使用单个CustomPainter
小部件(即widget,下文也一样)绘制。时钟看起来不错,但是很难告诉你时间。而且,背景是单色,看上去很无聊。
Flutter非常适合构建复杂的布局。毕竟,它是一个用于用户界面的工具包。将一堆小部件彼此堆叠,您只需将它们包装在Stack widget中。粒子时钟的最后一个场景小部件负责构建3个主要层:
-
1、
Background
:一个带有CustomPaint
小部件的堆栈,该小部件绘制不同颜色和绘画样式的随机形状,以及一个应用了模糊效果的BackdropFilter
。 -
2、
Clock Face
: 带有2个CustomPaint
小部件的堆栈, -
a.
时钟标记
-绘制时钟标记。每分钟标记,每5分钟标记具有额外的可见性。 -
b.
秒针
-绘制两秒的针弧。 -
3、
Particle FX
: 一个CustomPaint
小部件,用于绘制所有粒子。
@override
Widget build(BuildContext context) {
return AnimatedContainer(
duration: Duration(milliseconds: 1500),
curve: Curves.easeOut,
color: _bgColor,
child: ClipRect(
child: Stack(
children: [
_buildBgBlurFx(),
_buildClockFace(),
CustomPaint(
painter: ClockFxPainter(fx: _fx),
child: Container(),
),
],
),
),
);
}
即使底层代码很复杂,Flutter仍可以通过小部件组合来管理布局。
时钟绘图层和覆盖层。
这是与上述相同的图片,但没有覆盖层。
与时间同步的动画
我很早就想到,如果动画与时钟的滴答声同步发生,那就太酷了。最终版本中的解决方案非常简单。没有到达到想象中的目标。最初,我把它变成了一个非常复杂的问题,并尝试了各种怪异的技巧使它起作用。
@override
void tick(Duration duration) {
var secFrac = DateTime.now().millisecond / 1000;
var vecSpeed = duration.compareTo(easingDelayDuration) > 0
? max(.2, Curves.easeInOutSine.transform(1 - secFrac))
: 1;
particles.asMap().forEach((i, p) {
// Movement
p.x -= p.vx * vecSpeed;
p.y -= p.vy * vecSpeed;
// etc…
}
}
以上代码在每个动画刻度上运行。通过结合使用DateTime.now()
(以毫秒为单位)和Curves
,我们得到一个介于0
和1
之间的值。max
函数确保该数字保持在0.2
以上,以始终保持粒子随着每个刻度移动。
然后,在计算粒子的新x
和y
位置时,将vecSpeed
编号与运动矢量结合使用。
调色板和清晰度
在图形用户界面中随机分配颜色时,通常会让人感到厌烦。当然,这是有充分的理由,因为它通常会使GUI的访问性降低。在保持易读性的同时将随机颜色应用于GUI并不是一个容易解决的问题。幸运的是,Flutter有一些工具可以使我们更轻松。
首先,我使用了ColourLovers
API来获取其用户最喜欢的一些调色板。简而言之,许多调色板的颜色之间的对比度很差。我根据WCAG Contrast
指南,创建了一个过滤调色板阵列的脚本来解决了这一问题。过滤后,该列表仅包含调色板,其中至少存在一种对比度大于或等于4.5
的颜色组合。
然后,在Flutter中,我们仅需使用Color
类的computeLuminance
方法即可找到良好的匹配项。
/// Gets a random palette from a list of palettes and sorts its’
/// colors by luminance.
///
/// Given if [dark] or not, this method makes sure the luminance
/// of the background color is valid.
static Palette getPalette(List palettes, bool dark) {
Palette result;
while (result == null) {
Palette palette = Rnd.getItem(palettes);
List colors = Rnd.shuffle(palette.components);
var luminance = colors[0].computeLuminance();
if (dark ? luminance <= .1 : luminance >= .1) {
var lumDiff = colors
.sublist(1)
.asMap()
.map(
(i, color) => MapEntry(
i,
[i, (luminance - color.computeLuminance()).abs()],
),
)
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
当然我也为你们整理好了百度、阿里、腾讯、字节跳动等等互联网超级大厂的历年面试真题集锦。这也是我这些年来养成的习惯,一定要学会把好的东西,归纳整理,然后系统的消化吸收,这样才能极大的提高学习效率和成长进阶。碎片、零散化的东西,我觉得最没有价值的。就好比你给我一张扑克牌,我只会觉得它是一张废纸,但如果你给我一副扑克牌,它便有了它的价值。这和我们收集资料就要收集那些系统化的,是一个道理。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
进阶。碎片、零散化的东西,我觉得最没有价值的。就好比你给我一张扑克牌,我只会觉得它是一张废纸,但如果你给我一副扑克牌,它便有了它的价值。这和我们收集资料就要收集那些系统化的,是一个道理。
[外链图片转存中…(img-a42gC4pu-1712614879919)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!