时间:2021-05-20
在本篇文章开始前,我们先来回顾一下之前我们都做了哪些事情。在第一篇文章中,我们在动画值更改时调用double lerpDouble(num a, num b, double t)重新绘制条形。在第二篇文章中,我们首先用Tween类帮助我们管理动画值,并重新绘制条形,然后把绘制条形动画相关的类提取到bar.dart文件。在第三篇文章中,我们首先在Bar类中增加颜色的字段,再新建color_palette.dart文件,用于获取颜色值,同时用工厂构造函数Bar.empty和Bar.random分别创建空白Bar实例和随机Bar实例。在第四篇文章中,我们新增了BarChart类,用于创建指定数量的Bar实例列表,并将绘制条形的代码更改为绘制条形图。
接下来,我们为Bar类增加x坐标和宽度属性,然后我们使BarChart支持具有不同列数的图表。我们的新图表将适用于数据集,其中bar i代表某些系列中的第i个值,如产品发布后第i天的销售额。这样的图表涉及0..n个条形,但一个图表的条形数量n可能不同于下一个图表。
比如有两个图表,分别有5个和7个条形。5个条形的表格可以按照之前的方法进行动画化。bars的索引5和6在另一个动画终点没有对方,但是现在我们可以自由地给每个条形自己的位置和宽度,我们可以引入两个不可见的条形来扮演这个角色。视觉上效果是随着动画的进行,bars的索引5和6成长为最终的外观。如果是相反方向的动画,则bars的索引5和6将会减弱或淡入隐形。
复合值之间的线性插值(lerp)通过相应的组件相关联,如果某个组件在一个终点丢失,则在其位置使用一个不可见组件。通常有几种方法来选择不可见的组件,假设我们的产品经理决定使用零宽度、零高度的条形,其x坐标和颜色从其可见对象继承,我们将为Bar添加一个方法来创建给定实例的collapsed版本。
import 'package:flutter/material.dart';import 'package:flutter/animation.dart';import 'dart:ui' show lerpDouble;import 'dart:math';import 'color_palette.dart';class BarChart { final List<Bar> bars; BarChart(this.bars); factory BarChart.empty(Size size) { return new BarChart(<Bar>[]); } factory BarChart.random(Size size, Random random) { const barWidthFraction = 0.75; const minBarDistance = 20.0; // floor():返回不大于此的最大整数 final barCount = random.nextInt((size.width/minBarDistance).floor()) + 1; final barDistance = size.width / (1+barCount); final barWidth = barDistance * barWidthFraction; final startX = barDistance - barWidth/2; final color = ColorPalette.primary.random(random); final bars = new List.generate( barCount, (i)=> new Bar( startX + i * barDistance, barWidth, random.nextDouble() * size.height, color, ), ); return new BarChart(bars); } static BarChart lerp(BarChart begin, BarChart end, double t) { // max:返回两个数字中较大的一个 final barCount = max(begin.bars.length, end.bars.length); final bars = new List.generate( barCount, (i) => Bar.lerp( // ??:如果为空时取的默认值 begin._barOrNull(i) ?? end.bars[i].collapsed, end._barOrNull(i) ?? begin.bars[i].collapsed, t, ) ); return new BarChart(bars); } Bar _barOrNull(int index) => (index<bars.length ? bars[index] : null);}class BarChartTween extends Tween<BarChart> { BarChartTween(BarChart begin, BarChart end) : super(begin: begin, end: end); @override BarChart lerp(double t) => BarChart.lerp(begin, end, t);}class Bar { Bar(this.x, this.width, this.height, this.color); final double x; final double width; final double height; final Color color; Bar get collapsed => new Bar(x, 0.0, 0.0, color); static Bar lerp(Bar begin, Bar end, double t) { return new Bar( lerpDouble(begin.x, end.x, t), lerpDouble(begin.width, end.width, t), lerpDouble(begin.height, end.height, t), Color.lerp(begin.color, end.color, t) ); }}class BarTween extends Tween<Bar> { BarTween(Bar begin, Bar end) : super(begin: begin, end: end); @override Bar lerp(double t) => Bar.lerp(begin, end, t);}class BarChartPainter extends CustomPainter { BarChartPainter(Animation<BarChart> animation) : animation = animation, super(repaint: animation); final Animation<BarChart> animation; @override void paint(Canvas canvas, Size size) { final paint = new Paint()..style = PaintingStyle.fill; final chart = animation.value; for(final bar in chart.bars) { paint.color = bar.color; canvas.drawRect( new Rect.fromLTWH( bar.x, size.height - bar.height, bar.width, bar.height ), paint ); } } @override bool shouldRepaint(BarChartPainter old) => false;}将上述代码整合到我们的应用程序中,包括为此新设置重新定义BarChart.random和BarChart.empty。现在可以合理地使用空白图表来包含空图表零条形,而随机的条形图可以包含所有相同随机颜色的随机数量的条形,并且每个具有随机选择的高度。但是由于位置和宽度现在是Bar定义的一部分,我们需要BarChart.random来指定这些属性。为BarChart.random提供图表Size参数是合理的,可以缓解BarChartPainter.paint的大部分计算。
最后我们需要更新main.dart文件,让我们的应用程序可以重新显示。
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin { static const size = const Size(200.0, 100.0); // ... @override void initState() { // ... tween = new BarChartTween( new BarChart.empty(size), new BarChart.random(size, random)); animation.forward(); } // ... void changeData() { setState(() { tween = new BarChartTween( tween.evaluate(animation), new BarChart.random(size, random), ); animation.forward(from: 0.0); }); } // ... }}以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
在上一篇文章:Flutter进阶—实现动画效果(二)的最后,我们实现了一个控件,其中包含各种布局和状态处理控件。以及使用自定义的动画感知绘图代码绘制单个Bar的
在上一篇文章:Flutter进阶—实现动画效果(三)中,实现了一个随机高度、颜色的条形。这一篇文章我们会实现多个条形,同样是随机高度、颜色。首先在bar.dar
在上一篇文章:Flutter进阶—实现动画效果(一)的最后,我们说到需要一个处理程序混乱的概念。在这一篇文章中,我们会引入补间,它是构建动画代码的一个非常简单的
前言此动画效果是我在浏览文章时发现的一个非常酷炫的效果,于是就使用Flutter实现了。更多动画效果及Flutter资源:https://github.com/
本文介绍了css3进阶之less实现星空动画的示例代码,分享给大家,具体如下:效果动图如下:预览链接和代码在我的codepen:https://codepen.