Flutter进阶之实现动画效果(九)
作者:何小有 发布时间:2023-04-11 12:20:06
标签:Flutter,动画
在上一篇文章中,我们实现了统计每个产品和地区的销售额,如果现在需要统计每个产品和地区所占市场份额的百分比,那么使用堆叠条形图是不合适的,我们可以使用分组条形图,因为它可以同时在两个类别维度上进行定量比较。分组条形图的实际效果如下图所示:
要实现上面的效果,我们需要更新bar.dart文件的代码:
import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';
import 'dart:ui' show lerpDouble;
import 'dart:math';
import 'color_palette.dart';
import 'tween.dart';
class BarChart {
BarChart(this.groups);
final List<BarGroup> groups;
factory BarChart.empty(Size size) {
return new BarChart(<BarGroup>[]);
}
factory BarChart.random(Size size, Random random) {
const groupWidthFraction = 0.75;
const barWidthFraction = 0.9;
final groupRanks = _selectRanks(random, 5);
final groupCount = groupRanks.length;
final groupDistance = size.width / (1+groupCount);
final groupWidth = groupDistance * groupWidthFraction;
final startX = groupDistance - groupWidth/2;
final barRanks = _selectRanks(random, ColorPalette.primary.length ~/ 2);
final barCount = barRanks.length;
final barDistance = groupWidth / barCount;
final barWidth = barDistance * barWidthFraction;
final groups = new List.generate(
groupCount,
(i) {
final bars = new List.generate(
barCount,
(j) => new Bar(
barRanks[j],
startX + i * groupDistance + j * barDistance,
barWidth,
random.nextDouble() * size.height,
ColorPalette.primary[barRanks[j]],
)
);
return new BarGroup(
groupRanks[i],
bars
);
}
);
return new BarChart(groups);
}
static List<int> _selectRanks(Random random, int cap) {
final ranks = <int>[];
var rank = 0;
while(true) {
rank += random.nextInt(2);
if(cap <= rank) break;
ranks.add(rank);
rank++;
}
return ranks;
}
}
class BarChartTween extends Tween<BarChart> {
BarChartTween(BarChart begin, BarChart end)
: _groupsTween = new MergeTween<BarGroup>(begin.groups, end.groups),
super(begin: begin, end: end);
final MergeTween<BarGroup> _groupsTween;
@override
BarChart lerp(double t) => new BarChart(_groupsTween.lerp(t));
}
class BarGroup implements MergeTweenable<BarGroup> {
BarGroup(this.rank, this.bars);
final int rank;
final List<Bar> bars;
@override
BarGroup get empty => new BarGroup(rank, <Bar>[]);
@override
bool operator <(BarGroup other) => rank < other.rank;
@override
Tween<BarGroup> tweenTo(BarGroup other) => new BarGroupTween(this, other);
}
class BarGroupTween extends Tween<BarGroup> {
BarGroupTween(BarGroup begin, BarGroup end)
: _barsTween = new MergeTween<Bar>(begin.bars, end.bars),
super(begin: begin, end: end) {
assert(begin.rank == end.rank);
}
final MergeTween<Bar> _barsTween;
@override
BarGroup lerp(double t) => new BarGroup(
begin.rank,
_barsTween.lerp(t)
);
}
class Bar extends MergeTweenable<Bar> {
Bar(this.rank, this.x, this.width, this.height, this.color);
final int rank;
final double x;
final double width;
final double height;
final Color color;
@override
Bar get empty => new Bar(rank, x, 0.0, 0.0, color);
@override
bool operator <(Bar other) => rank < other.rank;
@override
Tween<Bar> tweenTo(Bar other) => new BarTween(this, other);
static Bar lerp(Bar begin, Bar end, double t) {
assert(begin.rank == end.rank);
return new Bar(
begin.rank,
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) {
assert(begin.rank == end.rank);
}
@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 stack in chart.groups) {
for(final bar in stack.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;
}
接着学习下一篇:Flutter进阶之实现动画效果(十)
来源:https://blog.csdn.net/hekaiyou/article/details/72831144
0
投稿
猜你喜欢
- 为了能正常输出XML格式的内容,必须要对不被XML允许的那些特殊字符进行转换。本文介绍的正是如何使用C#判断XML字符串是否含特殊字符并进行
- 1.准备工作1、新建一个SpringBoot项目加上web依赖, 所有依赖<dependency><groupId>
- 本文实例为大家分享了Java身份证号码校验工具类的具体代码,供大家参考,具体内容如下import java.text.ParseExcept
- 本文实例为大家分享了Java实现五子棋游戏的具体代码,供大家参考,具体内容如下一、功能分析五子棋的实现还是较为简单的,通过下期的流程我们可以
- 在学习操作系统这本书的时候,我们使用的是汤小丹老师的《计算机操作系统》接下来我将会使用java语言去实现内部代码。Swap指令最佳置换算法是
- Rss 是一种描述和同步网站内容的格式,是目前使用最广泛的XML应用。RSS 搭建了信息迅速传播的一个技术平台,使得每个
- MAC算法之消息摘要算法HmacMD5的实现MAC算法主要用于消息验证以下为算法实现:import javax.crypto.KeyGene
- 注解版步骤新建一个module,添加web的支持由于Maven可能存在资源过滤的问题,我们将配置完善pom.xml<build>
- AIDL:Android Interface Definition Language,它是一种android内部进程通信接口的描述语言,通过
- 详解HDFS多文件Join操作的实例最近在做HDFS文件处理之时,遇到了多文件Join操作,其中包括:All Join以及常用的Left J
- System.Collections.ArrayList类是一个特殊的数组。通过添加和删除元素,就可以动态改变数组的长度。一.优点1. 支持
- 注:作者使用IDEA + Gradle注:需要有一定的java SpringBoot and SSM+Springcloud基础程序测试错误
- 本Demo使用三个类一个Test类一个自定义的Stack类一个自定义的Queue类可以实现的功能:1.对于一个写在文本文件中的迷宫,能够将其
- 在Spring Boot Actuator中提供很多像health、metrics等实时监控接口,可以方便我们随时跟踪服务的性能指标。Spr
- 本文实例为大家分享了C#实现学生档案查询的具体代码,供大家参考,具体内容如下using System;using System.Collec
- 前言《黄金矿工》游戏是一个经典的抓金子小游戏,它可以锻炼人的反应能力。。该游戏中,可以通过“挖矿”获
- 前言Android 8.0系统更新之后,app的更新将不再像之前的系统版本一样能够直接下载安装包之后直接安装(以前安装未知来源应用的时候一般
- 简介机器学习在全球范围内越来越受欢迎和使用。 它已经彻底改变了某些应用程序的构建方式,并且可能会继续成为我们日常生活中一个巨大的(并且正在增
- 一、常见游戏规则从扑克中每次取出4张牌。使用加减乘除,第一个能得出24者为赢。(其中,J代表11,Q代表12,K代表13,A代表1),按照要
- 本文实例讲述了C#利用Windows自带gdi32.dll实现抓取屏幕功能,是C#应用程序设计中一个非常实用的功能,现分享给大家供大家参考借