`web/github_dataviz`: Migrate to null safety (#919)

pull/925/head
Brett Morgan 4 years ago committed by GitHub
parent 8932e60976
commit 83d3ea99f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,6 @@
include: package:flutter_lints/flutter.yaml
linter:
rules:
avoid_print: false
prefer_single_quotes: true

@ -1,8 +1,8 @@
import 'package:github_dataviz/mathutils.dart';
class ControlPointAndValue {
int point;
double value;
late int point;
double? value;
ControlPointAndValue() {
value = 0;
@ -37,9 +37,9 @@ class CatmullInterpolator implements Interpolator {
}
ControlPointAndValue progressiveGet(ControlPointAndValue cpv) {
double v = cpv.value;
double? v = cpv.value;
for (int i = cpv.point; i < controlPoints.length - 1; i++) {
if (controlPoints[i].x >= v) {
if (controlPoints[i].x >= v!) {
double t = (v - controlPoints[i - 1].x) /
(controlPoints[i].x - controlPoints[i - 1].x);
double p0 = controlPoints[i - 2].y;

@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
import 'dart:ui';
class Constants {
static final Color backgroundColor = const Color(0xFF000020);
static final Color timelineLineColor = Color(0x60FFFFFF);
static final Color milestoneColor = Color(0x40FFFFFF);
static final Color milestoneTimelineColor = Colors.white;
static const Color backgroundColor = Color(0xFF000020);
static const Color timelineLineColor = Color(0x60FFFFFF);
static const Color milestoneColor = Color(0x40FFFFFF);
static const Color milestoneTimelineColor = Colors.white;
}

@ -8,7 +8,7 @@ class ContributionData {
static ContributionData fromJson(Map<String, dynamic> jsonMap) {
ContributionData data = ContributionData(
jsonMap["w"], jsonMap["a"], jsonMap["d"], jsonMap["c"]);
jsonMap['w'], jsonMap['a'], jsonMap['d'], jsonMap['c']);
return data;
}
}

@ -6,7 +6,7 @@ class User {
User(this.id, this.username, this.avatarUrl);
static User fromJson(Map<String, dynamic> jsonMap) {
User user = User(jsonMap["id"], jsonMap["login"], jsonMap["avatar_url"]);
User user = User(jsonMap['id'], jsonMap['login'], jsonMap['avatar_url']);
return user;
}
}

@ -8,11 +8,11 @@ class UserContribution {
UserContribution(this.user, this.contributions);
static UserContribution fromJson(Map<String, dynamic> jsonMap) {
List<ContributionData> contributionList = (jsonMap["weeks"] as List)
List<ContributionData> contributionList = (jsonMap['weeks'] as List)
.map((e) => ContributionData.fromJson(e))
.toList();
var userContribution =
UserContribution(User.fromJson(jsonMap["author"]), contributionList);
UserContribution(User.fromJson(jsonMap['author']), contributionList);
return userContribution;
}
}

@ -1,24 +1,23 @@
import 'package:intl/intl.dart';
class WeekLabel {
int weekNum;
int? weekNum;
String label;
WeekLabel(this.weekNum, this.label);
WeekLabel.forDate(DateTime date, String label) {
this.label = label;
WeekLabel.forDate(DateTime date, this.label) {
int year = getYear(date);
int weekOfYearNum = getWeekNumber(date);
this.weekNum = 9 + ((year - 2015) * 52) + weekOfYearNum;
weekNum = 9 + ((year - 2015) * 52) + weekOfYearNum;
}
int getYear(DateTime date) {
return int.parse(DateFormat("y").format(date));
return int.parse(DateFormat('y').format(date));
}
int getWeekNumber(DateTime date) {
int dayOfYear = int.parse(DateFormat("D").format(date));
int dayOfYear = int.parse(DateFormat('D').format(date));
return ((dayOfYear - date.weekday + 10) / 7).floor();
}
}

@ -14,7 +14,9 @@ class LayeredChart extends StatefulWidget {
final List<WeekLabel> milestones;
final double animationValue;
LayeredChart(this.dataToPlot, this.milestones, this.animationValue);
const LayeredChart(this.dataToPlot, this.milestones, this.animationValue,
{Key? key})
: super(key: key);
@override
State<StatefulWidget> createState() {
@ -23,14 +25,14 @@ class LayeredChart extends StatefulWidget {
}
class LayeredChartState extends State<LayeredChart> {
List<Path> paths;
List<Path> capPaths;
List<double> maxValues;
double theta;
double graphHeight;
List<TextPainter> labelPainter;
List<TextPainter> milestonePainter;
Size lastSize;
late List<Path> paths;
late List<Path> capPaths;
late List<double> maxValues;
late double theta;
late double graphHeight;
late List<TextPainter> labelPainter;
late List<TextPainter> milestonePainter;
Size? lastSize;
void buildPaths(
Size size,
@ -89,7 +91,7 @@ class LayeredChartState extends State<LayeredChart> {
j.toDouble(), 0, (numPoints - 1).toDouble(), 0, (n - 1).toDouble());
curve.progressiveGet(cpv);
curvePoints.add(MathUtils.map(
max(0, cpv.value), 0, maxValues[i].toDouble(), 0, graphHeight));
max(0, cpv.value!), 0, maxValues[i].toDouble(), 0, graphHeight));
}
paths.add(Path());
capPaths.add(Path());
@ -136,7 +138,7 @@ class LayeredChartState extends State<LayeredChart> {
labelPainter = <TextPainter>[];
for (int i = 0; i < dataToPlot.length; i++) {
TextSpan span = TextSpan(
style: TextStyle(
style: const TextStyle(
color: Color.fromARGB(255, 255, 255, 255), fontSize: 12),
text: dataToPlot[i].label.toUpperCase());
TextPainter tp = TextPainter(
@ -149,7 +151,7 @@ class LayeredChartState extends State<LayeredChart> {
milestonePainter = <TextPainter>[];
for (int i = 0; i < milestones.length; i++) {
TextSpan span = TextSpan(
style: TextStyle(
style: const TextStyle(
color: Color.fromARGB(255, 255, 255, 255), fontSize: 10),
text: milestones[i].label.toUpperCase());
TextPainter tp = TextPainter(
@ -174,15 +176,15 @@ class LayeredChartState extends State<LayeredChart> {
}
class ChartPainter extends CustomPainter {
static List<Color> colors = [
static List<Color?> colors = [
Colors.red[900],
Color(0xffc4721a),
const Color(0xffc4721a),
Colors.lime[900],
Colors.green[900],
Colors.blue[900],
Colors.purple[900],
];
static List<Color> capColors = [
static List<Color?> capColors = [
Colors.red[500],
Colors.amber[500],
Colors.lime[500],
@ -196,17 +198,17 @@ class ChartPainter extends CustomPainter {
double margin;
double graphGap;
double capTheta;
late double capTheta;
double capSize;
int numPoints;
double amount = 1.0;
Paint pathPaint;
Paint capPaint;
Paint textPaint;
Paint milestonePaint;
Paint linePaint;
Paint fillPaint;
late Paint pathPaint;
late Paint capPaint;
late Paint textPaint;
late Paint milestonePaint;
late Paint linePaint;
late Paint fillPaint;
LayeredChartState state;
@ -220,13 +222,13 @@ class ChartPainter extends CustomPainter {
this.capSize,
this.numPoints,
this.amount) {
this.capTheta = pi * capDegrees / 180;
capTheta = pi * capDegrees / 180;
pathPaint = Paint();
pathPaint.style = PaintingStyle.fill;
capPaint = Paint();
capPaint.style = PaintingStyle.fill;
textPaint = Paint();
textPaint.color = Color(0xFFFFFFFF);
textPaint.color = const Color(0xFFFFFFFF);
milestonePaint = Paint();
milestonePaint.color = Constants.milestoneColor;
milestonePaint.style = PaintingStyle.stroke;
@ -236,19 +238,19 @@ class ChartPainter extends CustomPainter {
linePaint.strokeWidth = 0.5;
fillPaint = Paint();
fillPaint.style = PaintingStyle.fill;
fillPaint.color = Color(0xFF000000);
fillPaint.color = const Color(0xFF000000);
}
@override
void paint(Canvas canvas, Size size) {
if (dataToPlot.length == 0) {
if (dataToPlot.isEmpty) {
return;
}
if (state.lastSize == null ||
size.width != state.lastSize.width ||
size.height != state.lastSize.height) {
print("Building paths, lastsize = ${state.lastSize}");
size.width != state.lastSize!.width ||
size.height != state.lastSize!.height) {
print('Building paths, lastsize = ${state.lastSize}');
state.buildPaths(size, dataToPlot, milestones, numPoints, graphGap,
margin, capTheta, capSize);
}
@ -266,7 +268,7 @@ class ChartPainter extends CustomPainter {
{
for (int i = 0; i < milestones.length; i++) {
WeekLabel milestone = milestones[i];
double p = (milestone.weekNum.toDouble() / numWeeks) + (1 - amount);
double p = (milestone.weekNum!.toDouble() / numWeeks) + (1 - amount);
if (p < 1) {
double x1 = MathUtils.map(p, 0, 1, startX, endX);
double y1 = MathUtils.map(p, 0, 1, startY, endY);
@ -282,7 +284,7 @@ class ChartPainter extends CustomPainter {
canvas.translate(textX, textY);
canvas.skew(tan(capTheta * 1.0), -tan(state.theta));
canvas.translate(-tp.width / 2, 0);
tp.paint(canvas, Offset(0, 0));
tp.paint(canvas, const Offset(0, 0));
canvas.restore();
}
}
@ -302,11 +304,11 @@ class ChartPainter extends CustomPainter {
canvas.skew(0, -tan(state.theta));
canvas.drawRect(
Rect.fromLTWH(-1, -1, tp.width + 2, tp.height + 2), fillPaint);
tp.paint(canvas, Offset(0, 0));
tp.paint(canvas, const Offset(0, 0));
canvas.restore();
}
linePaint.color = capColors[i];
linePaint.color = capColors[i]!;
canvas.drawLine(Offset(startX, startY), Offset(endX, endY), linePaint);
Path clipPath = Path();
@ -317,8 +319,8 @@ class ChartPainter extends CustomPainter {
clipPath.close();
canvas.clipPath(clipPath);
pathPaint.color = colors[i];
capPaint.color = capColors[i];
pathPaint.color = colors[i]!;
capPaint.color = capColors[i]!;
double offsetX = MathUtils.map(1 - amount, 0, 1, startX, endX);
double offsetY = MathUtils.map(1 - amount, 0, 1, startY, endY);
canvas.translate(offsetX - startX, offsetY - startY);

@ -19,21 +19,23 @@ import 'package:github_dataviz/mathutils.dart';
import 'package:github_dataviz/timeline.dart';
class MainLayout extends StatefulWidget {
const MainLayout({Key? key}) : super(key: key);
@override
_MainLayoutState createState() => _MainLayoutState();
}
class _MainLayoutState extends State<MainLayout> with TickerProviderStateMixin {
AnimationController _animation;
List<UserContribution> contributions;
List<StatForWeek> starsByWeek;
List<StatForWeek> forksByWeek;
List<StatForWeek> pushesByWeek;
List<StatForWeek> issueCommentsByWeek;
List<StatForWeek> pullRequestActivityByWeek;
List<WeekLabel> weekLabels;
static final double earlyInterpolatorFraction = 0.8;
AnimationController? _animation;
List<UserContribution>? contributions;
List<StatForWeek>? starsByWeek;
List<StatForWeek>? forksByWeek;
List<StatForWeek>? pushesByWeek;
List<StatForWeek>? issueCommentsByWeek;
List<StatForWeek>? pullRequestActivityByWeek;
late List<WeekLabel> weekLabels;
static const double earlyInterpolatorFraction = 0.8;
static final EarlyInterpolator interpolator =
EarlyInterpolator(earlyInterpolatorFraction);
double animationValue = 1.0;
@ -47,14 +49,14 @@ class _MainLayoutState extends State<MainLayout> with TickerProviderStateMixin {
createAnimation(0);
weekLabels = <WeekLabel>[];
weekLabels.add(WeekLabel.forDate(DateTime(2019, 2, 26), "v1.2"));
weekLabels.add(WeekLabel.forDate(DateTime(2018, 12, 4), "v1.0"));
weekLabels.add(WeekLabel.forDate(DateTime(2019, 2, 26), 'v1.2'));
weekLabels.add(WeekLabel.forDate(DateTime(2018, 12, 4), 'v1.0'));
// weekLabels.add(WeekLabel.forDate(new DateTime(2018, 9, 19), "Preview 2"));
weekLabels.add(WeekLabel.forDate(DateTime(2018, 6, 21), "Preview 1"));
weekLabels.add(WeekLabel.forDate(DateTime(2018, 6, 21), 'Preview 1'));
// weekLabels.add(WeekLabel.forDate(new DateTime(2018, 5, 7), "Beta 3"));
weekLabels.add(WeekLabel.forDate(DateTime(2018, 2, 27), "Beta 1"));
weekLabels.add(WeekLabel.forDate(DateTime(2017, 5, 1), "Alpha"));
weekLabels.add(WeekLabel(48, "Repo Made Public"));
weekLabels.add(WeekLabel.forDate(DateTime(2018, 2, 27), 'Beta 1'));
weekLabels.add(WeekLabel.forDate(DateTime(2017, 5, 1), 'Alpha'));
weekLabels.add(WeekLabel(48, 'Repo Made Public'));
loadGitHubData();
}
@ -66,10 +68,10 @@ class _MainLayoutState extends State<MainLayout> with TickerProviderStateMixin {
duration: const Duration(milliseconds: 14400),
vsync: this,
)..repeat();
_animation.addListener(() {
_animation!.addListener(() {
setState(() {
if (!timelineOverride) {
animationValue = _animation.value;
animationValue = _animation!.value;
interpolatedAnimationValue = interpolator.get(animationValue);
}
});
@ -82,7 +84,7 @@ class _MainLayoutState extends State<MainLayout> with TickerProviderStateMixin {
List<DataSeries> dataToPlot = [];
if (contributions != null) {
List<int> series = [];
for (UserContribution userContrib in contributions) {
for (UserContribution userContrib in contributions!) {
for (int i = 0; i < userContrib.contributions.length; i++) {
ContributionData data = userContrib.contributions[i];
if (series.length > i) {
@ -92,32 +94,32 @@ class _MainLayoutState extends State<MainLayout> with TickerProviderStateMixin {
}
}
}
dataToPlot.add(DataSeries("Added Lines", series));
dataToPlot.add(DataSeries('Added Lines', series));
}
if (starsByWeek != null) {
dataToPlot
.add(DataSeries("Stars", starsByWeek.map((e) => e.stat).toList()));
.add(DataSeries('Stars', starsByWeek!.map((e) => e.stat).toList()));
}
if (forksByWeek != null) {
dataToPlot
.add(DataSeries("Forks", forksByWeek.map((e) => e.stat).toList()));
.add(DataSeries('Forks', forksByWeek!.map((e) => e.stat).toList()));
}
if (pushesByWeek != null) {
dataToPlot
.add(DataSeries("Pushes", pushesByWeek.map((e) => e.stat).toList()));
.add(DataSeries('Pushes', pushesByWeek!.map((e) => e.stat).toList()));
}
if (issueCommentsByWeek != null) {
dataToPlot.add(DataSeries(
"Issue Comments", issueCommentsByWeek.map((e) => e.stat).toList()));
'Issue Comments', issueCommentsByWeek!.map((e) => e.stat).toList()));
}
if (pullRequestActivityByWeek != null) {
dataToPlot.add(DataSeries("Pull Request Activity",
pullRequestActivityByWeek.map((e) => e.stat).toList()));
dataToPlot.add(DataSeries('Pull Request Activity',
pullRequestActivityByWeek!.map((e) => e.stat).toList()));
}
LayeredChart layeredChart =
@ -126,15 +128,13 @@ class _MainLayoutState extends State<MainLayout> with TickerProviderStateMixin {
const double timelinePadding = 60.0;
var timeline = Timeline(
numWeeks: dataToPlot != null && dataToPlot.length > 0
? dataToPlot.last.series.length
: 0,
numWeeks: dataToPlot.isNotEmpty ? dataToPlot.last.series.length : 0,
animationValue: interpolatedAnimationValue,
weekLabels: weekLabels,
mouseDownCallback: (double xFraction) {
setState(() {
timelineOverride = true;
_animation.stop();
_animation?.stop();
interpolatedAnimationValue = xFraction;
});
},
@ -176,53 +176,55 @@ class _MainLayoutState extends State<MainLayout> with TickerProviderStateMixin {
@override
void dispose() {
_animation.dispose();
_animation?.dispose();
super.dispose();
}
Future loadGitHubData() async {
String contributorsJsonStr =
(await http.get("assets/github_data/contributors.json")).body;
(await http.get(Uri.parse('assets/github_data/contributors.json')))
.body;
List jsonObjs = jsonDecode(contributorsJsonStr) as List;
List<UserContribution> contributionList =
jsonObjs.map((e) => UserContribution.fromJson(e)).toList();
print(
"Loaded ${contributionList.length} code contributions to /flutter/flutter repo.");
'Loaded ${contributionList.length} code contributions to /flutter/flutter repo.');
int numWeeksTotal = contributionList[0].contributions.length;
String starsByWeekStr =
(await http.get("assets/github_data/stars.tsv")).body;
(await http.get(Uri.parse('assets/github_data/stars.tsv'))).body;
List<StatForWeek> starsByWeekLoaded =
summarizeWeeksFromTSV(starsByWeekStr, numWeeksTotal);
String forksByWeekStr =
(await http.get("assets/github_data/forks.tsv")).body;
(await http.get(Uri.parse('assets/github_data/forks.tsv'))).body;
List<StatForWeek> forksByWeekLoaded =
summarizeWeeksFromTSV(forksByWeekStr, numWeeksTotal);
String commitsByWeekStr =
(await http.get("assets/github_data/commits.tsv")).body;
(await http.get(Uri.parse('assets/github_data/commits.tsv'))).body;
List<StatForWeek> commitsByWeekLoaded =
summarizeWeeksFromTSV(commitsByWeekStr, numWeeksTotal);
String commentsByWeekStr =
(await http.get("assets/github_data/comments.tsv")).body;
(await http.get(Uri.parse('assets/github_data/comments.tsv'))).body;
List<StatForWeek> commentsByWeekLoaded =
summarizeWeeksFromTSV(commentsByWeekStr, numWeeksTotal);
String pullRequestActivityByWeekStr =
(await http.get("assets/github_data/pull_requests.tsv")).body;
(await http.get(Uri.parse('assets/github_data/pull_requests.tsv')))
.body;
List<StatForWeek> pullRequestActivityByWeekLoaded =
summarizeWeeksFromTSV(pullRequestActivityByWeekStr, numWeeksTotal);
setState(() {
this.contributions = contributionList;
this.starsByWeek = starsByWeekLoaded;
this.forksByWeek = forksByWeekLoaded;
this.pushesByWeek = commitsByWeekLoaded;
this.issueCommentsByWeek = commentsByWeekLoaded;
this.pullRequestActivityByWeek = pullRequestActivityByWeekLoaded;
contributions = contributionList;
starsByWeek = starsByWeekLoaded;
forksByWeek = forksByWeekLoaded;
pushesByWeek = commitsByWeekLoaded;
issueCommentsByWeek = commentsByWeekLoaded;
pullRequestActivityByWeek = pullRequestActivityByWeekLoaded;
});
}
@ -230,18 +232,18 @@ class _MainLayoutState extends State<MainLayout> with TickerProviderStateMixin {
String statByWeekStr, int numWeeksTotal) {
List<StatForWeek> loadedStats = [];
HashMap<int, StatForWeek> statMap = HashMap();
statByWeekStr.split("\n").forEach((s) {
List<String> split = s.split("\t");
statByWeekStr.split('\n').forEach((s) {
List<String> split = s.split('\t');
if (split.length == 2) {
int weekNum = int.parse(split[0]);
statMap[weekNum] = StatForWeek(weekNum, int.parse(split[1]));
}
});
print("Loaded ${statMap.length} weeks.");
print('Loaded ${statMap.length} weeks.');
// Convert into a list by week, but fill in empty weeks with 0
for (int i = 0; i < numWeeksTotal; i++) {
StatForWeek starsForWeek = statMap[i];
StatForWeek? starsForWeek = statMap[i];
if (starsForWeek == null) {
loadedStats.add(StatForWeek(i, 0));
} else {
@ -253,5 +255,5 @@ class _MainLayoutState extends State<MainLayout> with TickerProviderStateMixin {
}
void main() {
runApp(Center(child: MainLayout()));
runApp(const Center(child: MainLayout()));
}

@ -14,17 +14,19 @@ class Timeline extends StatefulWidget {
final double animationValue;
final List<WeekLabel> weekLabels;
final MouseDownCallback mouseDownCallback;
final MouseMoveCallback mouseMoveCallback;
final MouseUpCallback mouseUpCallback;
Timeline(
{@required this.numWeeks,
@required this.animationValue,
@required this.weekLabels,
final MouseDownCallback? mouseDownCallback;
final MouseMoveCallback? mouseMoveCallback;
final MouseUpCallback? mouseUpCallback;
const Timeline(
{required this.numWeeks,
required this.animationValue,
required this.weekLabels,
this.mouseDownCallback,
this.mouseMoveCallback,
this.mouseUpCallback});
this.mouseUpCallback,
Key? key})
: super(key: key);
@override
State<StatefulWidget> createState() {
@ -39,17 +41,17 @@ class TimelineState extends State<Timeline> {
void initState() {
super.initState();
for (int year = 2015; year < 2020; year++) {
String yearLabel = "$year";
String yearLabel = '$year';
labelPainters[yearLabel] =
_makeTextPainter(Constants.timelineLineColor, yearLabel);
}
widget.weekLabels.forEach((WeekLabel weekLabel) {
for (var weekLabel in widget.weekLabels) {
labelPainters[weekLabel.label] =
_makeTextPainter(Constants.milestoneTimelineColor, weekLabel.label);
labelPainters[weekLabel.label + "_red"] =
labelPainters[weekLabel.label + '_red'] =
_makeTextPainter(Colors.redAccent, weekLabel.label);
});
}
}
@override
@ -57,19 +59,22 @@ class TimelineState extends State<Timeline> {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onHorizontalDragDown: (DragDownDetails details) {
if (widget.mouseDownCallback != null) {
widget.mouseDownCallback(
final mouseDownCallback = widget.mouseDownCallback;
if (mouseDownCallback != null) {
mouseDownCallback(
_getClampedXFractionLocalCoords(context, details.globalPosition));
}
},
onHorizontalDragEnd: (DragEndDetails details) {
if (widget.mouseUpCallback != null) {
widget.mouseUpCallback();
final mouseUpCallback = widget.mouseUpCallback;
if (mouseUpCallback != null) {
mouseUpCallback();
}
},
onHorizontalDragUpdate: (DragUpdateDetails details) {
if (widget.mouseMoveCallback != null) {
widget.mouseMoveCallback(
final mouseMoveCallback = widget.mouseMoveCallback;
if (mouseMoveCallback != null) {
mouseMoveCallback(
_getClampedXFractionLocalCoords(context, details.globalPosition));
}
},
@ -95,17 +100,17 @@ class TimelineState extends State<Timeline> {
double _getClampedXFractionLocalCoords(
BuildContext context, Offset globalOffset) {
final RenderBox box = context.findRenderObject();
final RenderBox box = context.findRenderObject() as RenderBox;
final Offset localOffset = box.globalToLocal(globalOffset);
return MathUtils.clamp(localOffset.dx / context.size.width, 0, 1);
return MathUtils.clamp(localOffset.dx / context.size!.width, 0, 1);
}
}
class TimelinePainter extends CustomPainter {
TimelineState state;
Paint mainLinePaint;
Paint milestoneLinePaint;
late Paint mainLinePaint;
late Paint milestoneLinePaint;
Color lineColor = Colors.white;
@ -164,7 +169,7 @@ class TimelinePainter extends CustomPainter {
var mappedValue =
MathUtils.clampedMap(currTimeXDiff, 0, 0.025, 0, 1);
var lerpedColor = Color.lerp(Constants.milestoneTimelineColor,
Constants.timelineLineColor, mappedValue);
Constants.timelineLineColor, mappedValue)!;
mainLinePaint.color = lerpedColor;
} else {
mainLinePaint.color = Constants.timelineLineColor;
@ -174,8 +179,8 @@ class TimelinePainter extends CustomPainter {
}
if (isYear) {
var yearLabel = "$yearNumber";
state.labelPainters[yearLabel]
var yearLabel = '$yearNumber';
state.labelPainters[yearLabel]!
.paint(canvas, Offset(currX, size.height - labelHeight));
yearNumber++;
}
@ -185,17 +190,17 @@ class TimelinePainter extends CustomPainter {
{
for (int i = 0; i < weekLabels.length; i++) {
WeekLabel weekLabel = weekLabels[i];
double currX = (weekLabel.weekNum / numWeeks.toDouble()) * size.width;
double currX = (weekLabel.weekNum! / numWeeks.toDouble()) * size.width;
var timelineXDiff = (currTimeX - currX) / size.width;
double maxTimelineDiff = 0.08;
TextPainter textPainter = state.labelPainters[weekLabel.label];
TextPainter textPainter = state.labelPainters[weekLabel.label]!;
if (timelineXDiff > 0 &&
timelineXDiff < maxTimelineDiff &&
animationValue < 1) {
var mappedValue =
MathUtils.clampedMap(timelineXDiff, 0, maxTimelineDiff, 0, 1);
var lerpedColor = Color.lerp(
Colors.redAccent, Constants.milestoneTimelineColor, mappedValue);
Colors.redAccent, Constants.milestoneTimelineColor, mappedValue)!;
milestoneLinePaint.strokeWidth =
MathUtils.clampedMap(timelineXDiff, 0, maxTimelineDiff, 6, 1);
milestoneLinePaint.color = lerpedColor;

@ -1,13 +1,20 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.2"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
version: "1.2.0"
charcode:
dependency: transitive
description:
@ -15,6 +22,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
collection:
dependency: transitive
description:
@ -27,27 +41,41 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
http:
dependency: "direct main"
description:
name: http
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.2"
version: "0.13.4"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.4"
version: "4.0.0"
intl:
dependency: "direct main"
description:
name: intl
url: "https://pub.dartlang.org"
source: hosted
version: "0.16.1"
version: "0.17.0"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
meta:
dependency: transitive
description:
@ -62,13 +90,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
pedantic:
dependency: transitive
description:
name: pedantic
url: "https://pub.dartlang.org"
source: hosted
version: "1.11.1"
sky_engine:
dependency: transitive
description: flutter
@ -110,4 +131,4 @@ packages:
source: hosted
version: "2.1.0"
sdks:
dart: ">=2.12.0 <3.0.0"
dart: ">=2.14.0 <3.0.0"

@ -1,13 +1,17 @@
name: github_dataviz
environment:
sdk: ">=2.2.0 <3.0.0"
sdk: '>=2.12.0 <3.0.0'
dependencies:
flutter:
sdk: flutter
intl: ^0.16.0
http: ^0.12.0
intl: ^0.17.0
http: ^0.13.4
dev_dependencies:
flutter_lints: ^1.0.4
flutter:
assets:
- preview.png

Loading…
Cancel
Save