Skip to content

Instantly share code, notes, and snippets.

@damywise
Created April 10, 2023 16:43
Show Gist options
  • Save damywise/22b5e3ba9f1ee76e6a6b4fa078660e60 to your computer and use it in GitHub Desktop.
Save damywise/22b5e3ba9f1ee76e6a6b4fa078660e60 to your computer and use it in GitHub Desktop.
fl_chart reveal animation
import 'dart:math';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
//
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
double targetValue = 0;
bool showDot1 = false;
bool showDot2 = false;
final showDotDuration = const Duration(milliseconds: 500);
final duration = const Duration(milliseconds: 1000);
final duration2 = const Duration(milliseconds: 700);
void _incrementCounter() {
setState(() {
_counter++;
if (showDot1) {
showDot2 = false;
targetValue = targetValue == 0 ? 350 : 0;
Future.delayed(duration, () => setState(() => showDot1 = false),);
} else {
showDot1 = true;
Future.delayed(showDotDuration, () => setState(() => targetValue = targetValue == 0 ? 350 : 0));
Future.delayed(duration, () => setState(() => showDot2 = true),);
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
width: 300,
height: 300,
child: Stack(
children: [
LineChart(
LineChartData(
maxX: 10,
maxY: 10,
minX: 0,
minY: 0,
titlesData: FlTitlesData(
show: true,
topTitles: AxisTitles(),
rightTitles: AxisTitles(),
),
gridData: FlGridData(show: false),
borderData: FlBorderData(show: false),
),
),
TweenAnimationBuilder(
tween: Tween<double>(begin: 0, end: targetValue),
duration: duration,
builder: (context, value, child) {
return ShaderMask(
blendMode: BlendMode.dstIn,
shaderCallback: (Rect bounds) {
return const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [1, 1],
colors: [Colors.black, Colors.transparent])
.createShader(
Rect.fromLTWH(
35, 300 - 75 - (6 / 10 * 300), value, value),
);
},
child: ShaderMask(
blendMode: BlendMode.dstIn,
shaderCallback: (Rect bounds) {
return const LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
stops: [
1,
1
],
colors: [
Colors.black,
Colors.transparent
]).createShader(
Rect.fromLTWH(
35, 300 - 75 - (6 / 10 * 300), value, value),
);
},
child: LineChart(
LineChartData(
maxX: 10,
maxY: 10,
minX: 0,
minY: 0,
titlesData: FlTitlesData(
show: true,
topTitles: AxisTitles(),
rightTitles: AxisTitles(),
),
rangeAnnotations: RangeAnnotations(
horizontalRangeAnnotations: [],
verticalRangeAnnotations: []),
gridData: FlGridData(show: false),
borderData: FlBorderData(show: false),
lineBarsData: [
LineChartBarData(
color: Colors.red,
barWidth: 8,
isStrokeCapRound: true,
dotData: FlDotData(show: false),
spots: [
const FlSpot(0, 8),
const FlSpot(1, 7),
const FlSpot(3, 5),
const FlSpot(10, 3)
],
isCurved: true,
belowBarData: BarAreaData(
show: true, color: Colors.redAccent),
),
],
clipData: FlClipData.all(),
),
),
),
);
}),
TweenAnimationBuilder(
tween: Tween<double>(begin: 0, end: targetValue),
duration: duration2,
builder: (context, value, child) {
return ShaderMask(
blendMode: BlendMode.dstIn,
shaderCallback: (Rect bounds) {
return const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [1, 1],
colors: [Colors.black, Colors.transparent])
.createShader(
Rect.fromLTWH(
35, 300 - 75 - (6 / 10 * 300), value, value),
);
},
child: ShaderMask(
blendMode: BlendMode.dstIn,
shaderCallback: (Rect bounds) {
return const LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
stops: [1, 1],
colors: [Colors.black, Colors.transparent])
.createShader(
Rect.fromLTWH(
35, 300 - 75 - (6 / 10 * 300), value, value),
);
},
child: LineChart(
LineChartData(
maxX: 10,
maxY: 10,
minX: 0,
minY: 0,
titlesData: FlTitlesData(
show: true,
topTitles: AxisTitles(),
rightTitles: AxisTitles(),
),
rangeAnnotations: RangeAnnotations(
horizontalRangeAnnotations: [],
verticalRangeAnnotations: []),
gridData: FlGridData(show: false),
borderData: FlBorderData(show: false),
lineBarsData: [
LineChartBarData(
barWidth: 8,
isStrokeCapRound: true,
dotData: FlDotData(show: false),
spots: [
const FlSpot(0, 8),
const FlSpot(3, 4),
const FlSpot(5, 3),
const FlSpot(10, 1)
],
isCurved: true,
belowBarData: BarAreaData(
show: true, color: Colors.blueGrey),
),
],
clipData: FlClipData.all(),
),
),
),
);
},
),
AnimatedPositioned(
duration: const Duration(milliseconds: 100),
top: 2 / 10 * 300,
left: 40,
child: Transform.translate(
offset: const Offset(0, -4 - (2 / 10 * 34)),
child: Stack(
children: [
AnimatedScale(
scale: !showDot1 ? 0.0 : 2.0,
duration: showDotDuration,
curve: Curves.easeInOutBack,
child: const CircleAvatar(
radius: 5,
),
),
AnimatedScale(
scale: !showDot1 ? 0.0 : 1.0,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOutBack,
child: const CircleAvatar(
radius: 5,
backgroundColor: Colors.lightBlueAccent,
),
),
],
),
),
),
AnimatedPositioned(
duration: const Duration(milliseconds: 100),
top: 9 / 10 * 300,
left: 10 / 10 * 300 - 10,
child: Transform.translate(
offset: const Offset(0, -4 - (9 / 10 * 34)),
child: Stack(
children: [
AnimatedScale(
scale: !showDot2 ? 0.0 : 2.0,
duration: showDotDuration,
curve: Curves.easeInOutBack,
child: const CircleAvatar(
radius: 5,
),
),
AnimatedScale(
scale: !showDot2 ? 0.0 : 1.0,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOutBack,
child: const CircleAvatar(
radius: 5,
backgroundColor: Colors.lightBlueAccent,
),
),
],
),
),
),
],
),
),
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment