books
This commit is contained in:
1
packages/idraw/lib/p16/p16.dart
Normal file
1
packages/idraw/lib/p16/p16.dart
Normal file
@@ -0,0 +1 @@
|
||||
export 'p16_page.dart';
|
||||
29
packages/idraw/lib/p16/p16_page.dart
Normal file
29
packages/idraw/lib/p16/p16_page.dart
Normal file
@@ -0,0 +1,29 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:components/components.dart';
|
||||
import 's01.dart' as s1;
|
||||
import 's02.dart' as s2;
|
||||
import 's03.dart' as s3;
|
||||
import 's04.dart' as s4;
|
||||
import 's05.dart' as s5;
|
||||
import 's06.dart' as s6;
|
||||
|
||||
class P16Page extends StatelessWidget {
|
||||
const P16Page({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const DemoShower(
|
||||
srcCodeDir: 'draw/p16',
|
||||
|
||||
demos: [
|
||||
s1.Paper(),
|
||||
s2.Paper(),
|
||||
s3.Paper(),
|
||||
s4.Paper(),
|
||||
s5.Paper(),
|
||||
s6.Paper(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
172
packages/idraw/lib/p16/s01.dart
Normal file
172
packages/idraw/lib/p16/s01.dart
Normal file
@@ -0,0 +1,172 @@
|
||||
import 'dart:math';
|
||||
|
||||
// import 'dart:ui' as ui;
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// create by 张风捷特烈 on 2020/11/5
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明:
|
||||
|
||||
class Paper extends StatelessWidget {
|
||||
const Paper({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
alignment: Alignment.center,
|
||||
child: const ICharts(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ICharts extends StatelessWidget {
|
||||
const ICharts({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(alignment: Alignment.topCenter, children: [
|
||||
Container(
|
||||
width: 350,
|
||||
height: 250,
|
||||
padding: EdgeInsets.only(top: 40, right: 20, bottom: 20, left: 20),
|
||||
child: CustomPaint(
|
||||
painter: ChartPainter(),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top:8.0),
|
||||
child: Text(
|
||||
"捷特数学成绩统计图 - 2040 年",
|
||||
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||
),
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
const double _kScaleHeight = 8; // 刻度高
|
||||
const double _kBarPadding = 10; // 柱状图前间隔
|
||||
|
||||
class ChartPainter extends CustomPainter {
|
||||
final TextPainter _textPainter =
|
||||
TextPainter(textDirection: TextDirection.ltr);
|
||||
|
||||
final List<double> yData = [88, 98, 70, 80, 100, 75];
|
||||
final List<String> xData = ["7月", "8月", "9月", "10月", "11月", "12月"];
|
||||
|
||||
// final List<String> xData = [ "语文","数学", "英语", "物理", "化学", "生物"];
|
||||
|
||||
Path axisPath = Path();
|
||||
Paint axisPaint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 1;
|
||||
|
||||
Paint gridPaint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..color = Colors.grey
|
||||
..strokeWidth = 0.5;
|
||||
Paint fillPaint = Paint()..color = Colors.red;
|
||||
|
||||
double xStep = 0; // x 间隔
|
||||
double yStep = 0; // y 间隔
|
||||
|
||||
double maxData = 0; // 数据最大值
|
||||
|
||||
ChartPainter() {
|
||||
maxData = yData.reduce(max);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
// canvas.drawRect(
|
||||
// Offset.zero & size, Paint()..color = Colors.black.withAlpha(22));
|
||||
canvas.translate(0, size.height);
|
||||
canvas.translate(_kScaleHeight, -_kScaleHeight);
|
||||
|
||||
axisPath.moveTo(-_kScaleHeight, 0);
|
||||
axisPath.relativeLineTo(size.width, 0);
|
||||
axisPath.moveTo(0, _kScaleHeight);
|
||||
axisPath.relativeLineTo(0, -size.height);
|
||||
canvas.drawPath(axisPath, axisPaint);
|
||||
|
||||
drawYText(canvas, size);
|
||||
drawXText(canvas, size);
|
||||
drawBarChart(canvas, size);
|
||||
}
|
||||
|
||||
void drawXText(Canvas canvas, Size size) {
|
||||
xStep = (size.width - _kScaleHeight) / xData.length;
|
||||
canvas.save();
|
||||
canvas.translate(xStep, 0);
|
||||
for (int i = 0; i < xData.length; i++) {
|
||||
canvas.drawLine(Offset(0, 0), Offset(0, _kScaleHeight), axisPaint);
|
||||
_drawAxisText(canvas, xData[i],
|
||||
alignment: Alignment.center, offset: Offset(-xStep / 2, 10));
|
||||
canvas.translate(xStep, 0);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void drawBarChart(Canvas canvas, Size size) {
|
||||
canvas.save();
|
||||
canvas.translate(xStep, 0);
|
||||
for (int i = 0; i < xData.length; i++) {
|
||||
canvas.drawRect(
|
||||
Rect.fromLTWH(_kBarPadding, 0, xStep - 2 * _kBarPadding,
|
||||
-(yData[i] / maxData * (size.height - _kScaleHeight)))
|
||||
.translate(-xStep, 0),
|
||||
fillPaint);
|
||||
canvas.translate(xStep, 0);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void drawYText(Canvas canvas, Size size) {
|
||||
canvas.save();
|
||||
yStep = (size.height - _kScaleHeight) / 5;
|
||||
double numStep = maxData / 5;
|
||||
for (int i = 0; i <= 5; i++) {
|
||||
if (i == 0) {
|
||||
_drawAxisText(canvas, '0', offset: Offset(-10, 2));
|
||||
canvas.translate(0, -yStep);
|
||||
continue;
|
||||
}
|
||||
|
||||
canvas.drawLine(
|
||||
Offset(0, 0), Offset(size.width - _kScaleHeight, 0), gridPaint);
|
||||
|
||||
canvas.drawLine(Offset(-_kScaleHeight, 0), Offset(0, 0), axisPaint);
|
||||
String str = '${(numStep * i).toStringAsFixed(0)}';
|
||||
_drawAxisText(canvas, str, offset: Offset(-10, 2));
|
||||
canvas.translate(0, -yStep);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void _drawAxisText(Canvas canvas, String str,
|
||||
{Color color = Colors.black,
|
||||
bool x = false,
|
||||
Alignment alignment = Alignment.centerRight,
|
||||
Offset offset = Offset.zero}) {
|
||||
TextSpan text = TextSpan(
|
||||
text: str,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: color,
|
||||
));
|
||||
|
||||
_textPainter.text = text;
|
||||
_textPainter.layout(); // 进行布局
|
||||
|
||||
Size size = _textPainter.size;
|
||||
|
||||
Offset offsetPos = Offset(-size.width / 2, -size.height / 2)
|
||||
.translate(-size.width / 2 * alignment.x + offset.dx, 0.0 + offset.dy);
|
||||
_textPainter.paint(canvas, offsetPos);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
}
|
||||
197
packages/idraw/lib/p16/s02.dart
Normal file
197
packages/idraw/lib/p16/s02.dart
Normal file
@@ -0,0 +1,197 @@
|
||||
import 'dart:math';
|
||||
|
||||
// import 'dart:ui' as ui;
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// create by 张风捷特烈 on 2020/11/5
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明:
|
||||
class Paper extends StatelessWidget {
|
||||
const Paper({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
alignment: Alignment.center,
|
||||
child: const ICharts(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ICharts extends StatefulWidget {
|
||||
const ICharts({super.key});
|
||||
|
||||
@override
|
||||
_IChartsState createState() => _IChartsState();
|
||||
}
|
||||
|
||||
class _IChartsState extends State<ICharts> with SingleTickerProviderStateMixin{
|
||||
|
||||
late AnimationController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
duration: const Duration(milliseconds: 800),
|
||||
vsync: this,
|
||||
)..forward();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(alignment: Alignment.topCenter, children: [
|
||||
Container(
|
||||
width: 350,
|
||||
height: 250,
|
||||
padding: EdgeInsets.only(top: 40, right: 20, bottom: 20, left: 20),
|
||||
child: CustomPaint(
|
||||
painter: ChartPainter(repaint: _controller),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top:8.0),
|
||||
child: Text(
|
||||
"捷特数学成绩统计图 - 2040 年",
|
||||
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||
),
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
const double _kScaleHeight = 8; // 刻度高
|
||||
const double _kBarPadding = 10; // 柱状图前间隔
|
||||
|
||||
class ChartPainter extends CustomPainter {
|
||||
final TextPainter _textPainter =
|
||||
TextPainter(textDirection: TextDirection.ltr);
|
||||
|
||||
final List<double> yData = [88, 98, 70, 80, 100, 75];
|
||||
final List<String> xData = ["7月", "8月", "9月", "10月", "11月", "12月"];
|
||||
|
||||
// final List<String> xData = [ "语文","数学", "英语", "物理", "化学", "生物"];
|
||||
|
||||
final Animation<double> repaint;
|
||||
|
||||
|
||||
Path axisPath = Path();
|
||||
Paint axisPaint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 1;
|
||||
|
||||
Paint gridPaint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..color = Colors.grey
|
||||
..strokeWidth = 0.5;
|
||||
Paint fillPaint = Paint()..color = Colors.red;
|
||||
|
||||
double xStep = 0; // x 间隔
|
||||
double yStep = 0; // y 间隔
|
||||
|
||||
double maxData = 0; // 数据最大值
|
||||
|
||||
ChartPainter({required this.repaint}):super(repaint: repaint) {
|
||||
maxData = yData.reduce(max);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
|
||||
canvas.translate(0, size.height);
|
||||
canvas.translate(_kScaleHeight, -_kScaleHeight);
|
||||
|
||||
axisPath.moveTo(-_kScaleHeight, 0);
|
||||
axisPath.relativeLineTo(size.width, 0);
|
||||
axisPath.moveTo(0, _kScaleHeight);
|
||||
axisPath.relativeLineTo(0, -size.height);
|
||||
canvas.drawPath(axisPath, axisPaint);
|
||||
|
||||
drawYText(canvas, size);
|
||||
drawXText(canvas, size);
|
||||
drawBarChart(canvas,size);
|
||||
}
|
||||
|
||||
void drawXText(Canvas canvas, Size size) {
|
||||
xStep = (size.width - _kScaleHeight) / xData.length;
|
||||
canvas.save();
|
||||
canvas.translate(xStep, 0);
|
||||
for (int i = 0; i < xData.length; i++) {
|
||||
canvas.drawLine(Offset(0, 0), Offset(0, _kScaleHeight), axisPaint);
|
||||
_drawAxisText(canvas, xData[i],
|
||||
alignment: Alignment.center, offset: Offset(-xStep / 2, 10));
|
||||
canvas.translate(xStep, 0);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void drawBarChart(Canvas canvas, Size size) {
|
||||
canvas.save();
|
||||
canvas.translate(xStep, 0);
|
||||
for (int i = 0; i < xData.length; i++) {
|
||||
double dataHeight = -(yData[i] / maxData * (size.height - _kScaleHeight));
|
||||
canvas.drawRect(
|
||||
Rect.fromLTWH(
|
||||
_kBarPadding, 0, xStep-2*_kBarPadding, dataHeight*repaint.value)
|
||||
.translate(-xStep, 0),
|
||||
fillPaint);
|
||||
canvas.translate(xStep, 0);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void drawYText(Canvas canvas, Size size) {
|
||||
canvas.save();
|
||||
yStep = (size.height - _kScaleHeight) / 5;
|
||||
double numStep = maxData / 5;
|
||||
for (int i = 0; i <= 5; i++) {
|
||||
if (i == 0) {
|
||||
_drawAxisText(canvas, '0', offset: Offset(-10, 2));
|
||||
canvas.translate(0, -yStep);
|
||||
continue;
|
||||
}
|
||||
|
||||
canvas.drawLine(
|
||||
Offset(0, 0), Offset(size.width - _kScaleHeight, 0), gridPaint);
|
||||
|
||||
canvas.drawLine(Offset(-_kScaleHeight, 0), Offset(0, 0), axisPaint);
|
||||
String str = '${(numStep * i).toStringAsFixed(0)}';
|
||||
_drawAxisText(canvas, str, offset: Offset(-10, 2));
|
||||
canvas.translate(0, -yStep);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void _drawAxisText(Canvas canvas, String str,
|
||||
{Color color = Colors.black,
|
||||
bool x = false,
|
||||
Alignment alignment = Alignment.centerRight,
|
||||
Offset offset = Offset.zero}) {
|
||||
TextSpan text = TextSpan(
|
||||
text: str,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: color,
|
||||
));
|
||||
|
||||
_textPainter.text = text;
|
||||
_textPainter.layout(); // 进行布局
|
||||
|
||||
Size size = _textPainter.size;
|
||||
|
||||
Offset offsetPos = Offset(-size.width / 2, -size.height / 2)
|
||||
.translate(-size.width / 2 * alignment.x + offset.dx, 0.0 + offset.dy);
|
||||
_textPainter.paint(canvas, offsetPos);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
}
|
||||
215
packages/idraw/lib/p16/s03.dart
Normal file
215
packages/idraw/lib/p16/s03.dart
Normal file
@@ -0,0 +1,215 @@
|
||||
import 'dart:math';
|
||||
import 'dart:ui';
|
||||
|
||||
// import 'dart:ui' as ui;
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// create by 张风捷特烈 on 2020/11/5
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明:
|
||||
class Paper extends StatelessWidget {
|
||||
const Paper({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
alignment: Alignment.center,
|
||||
child: const ICharts(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ICharts extends StatefulWidget {
|
||||
const ICharts({super.key});
|
||||
|
||||
@override
|
||||
_IChartsState createState() => _IChartsState();
|
||||
}
|
||||
|
||||
class _IChartsState extends State<ICharts> with SingleTickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
duration: const Duration(milliseconds: 1000),
|
||||
vsync: this,
|
||||
)
|
||||
..forward()
|
||||
;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(alignment: Alignment.topCenter, children: [
|
||||
Container(
|
||||
width: 350,
|
||||
height: 250,
|
||||
padding: EdgeInsets.only(top: 40, right: 20, bottom: 20, left: 20),
|
||||
child: CustomPaint(
|
||||
painter: ChartPainter(repaint: _controller),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
"捷特数学成绩统计图 - 2040 年",
|
||||
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||
),
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
const double _kScaleHeight = 8; // 刻度高
|
||||
const double _kBarPadding = 10; // 柱状图前间隔
|
||||
|
||||
class ChartPainter extends CustomPainter {
|
||||
final TextPainter _textPainter =
|
||||
TextPainter(textDirection: TextDirection.ltr);
|
||||
|
||||
final List<double> yData = [88, 98, 70, 80, 100, 75];
|
||||
final List<String> xData = ["7月", "8月", "9月", "10月", "11月", "12月"];
|
||||
|
||||
// final List<String> xData = [ "语文","数学", "英语", "物理", "化学", "生物"];
|
||||
|
||||
final Animation<double> repaint;
|
||||
|
||||
Path axisPath = Path();
|
||||
Paint axisPaint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 1;
|
||||
|
||||
Paint gridPaint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..color = Colors.grey
|
||||
..strokeWidth = 0.5;
|
||||
Paint fillPaint = Paint()..color = Colors.red;
|
||||
Paint linePaint = Paint()
|
||||
..color = Colors.red
|
||||
..strokeCap=StrokeCap.round
|
||||
..style = PaintingStyle.stroke;
|
||||
|
||||
double xStep = 0; // x 间隔
|
||||
double yStep = 0; // y 间隔
|
||||
|
||||
double maxData = 0; // 数据最大值
|
||||
|
||||
final List<Offset> line = []; // 折线点位信息
|
||||
|
||||
ChartPainter({required this.repaint}) : super(repaint: repaint) {
|
||||
maxData = yData.reduce(max);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
xStep = (size.width - _kScaleHeight) / xData.length;
|
||||
yStep = (size.height - _kScaleHeight) / 5;
|
||||
|
||||
canvas.translate(0, size.height);
|
||||
canvas.translate(_kScaleHeight, -_kScaleHeight);
|
||||
axisPath.moveTo(-_kScaleHeight, 0);
|
||||
axisPath.relativeLineTo(size.width, 0);
|
||||
axisPath.moveTo(0, _kScaleHeight);
|
||||
axisPath.relativeLineTo(0, -size.height);
|
||||
canvas.drawPath(axisPath, axisPaint);
|
||||
|
||||
drawYText(canvas, size);
|
||||
drawXText(canvas, size);
|
||||
collectPoints(canvas, size);
|
||||
drawLineChart(canvas);
|
||||
}
|
||||
|
||||
void drawXText(Canvas canvas, Size size) {
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(xStep, 0);
|
||||
for (int i = 0; i < xData.length; i++) {
|
||||
canvas.drawLine(Offset(0, 0), Offset(0, _kScaleHeight), axisPaint);
|
||||
_drawAxisText(canvas, xData[i],
|
||||
alignment: Alignment.center, offset: Offset(-xStep / 2, 10));
|
||||
canvas.translate(xStep, 0);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void collectPoints(Canvas canvas, Size size) {
|
||||
line.clear();
|
||||
canvas.translate(xStep, 0);
|
||||
for (int i = 0; i < xData.length; i++) {
|
||||
double dataHeight = -(yData[i] / maxData * (size.height - _kScaleHeight));
|
||||
line.add(Offset(xStep * i-xStep/2, dataHeight));
|
||||
}
|
||||
}
|
||||
|
||||
void drawLineChart(Canvas canvas){
|
||||
canvas.drawPoints(PointMode.points, line, linePaint..strokeWidth=5);
|
||||
|
||||
Offset p1 = line[0];
|
||||
Path path = Path()..moveTo(p1.dx, p1.dy);
|
||||
for (var i = 1; i < line.length; i++) {
|
||||
path.lineTo(line[i].dx, line[i].dy);
|
||||
}
|
||||
linePaint..strokeWidth=1;
|
||||
PathMetrics pms = path.computeMetrics();
|
||||
pms.forEach((pm) {
|
||||
canvas.drawPath(pm.extractPath(0, pm.length * repaint.value), linePaint);
|
||||
});
|
||||
}
|
||||
|
||||
void drawYText(Canvas canvas, Size size) {
|
||||
canvas.save();
|
||||
double numStep = maxData / 5;
|
||||
for (int i = 0; i <= 5; i++) {
|
||||
if (i == 0) {
|
||||
_drawAxisText(canvas, '0', offset: Offset(-10, 2));
|
||||
canvas.translate(0, -yStep);
|
||||
continue;
|
||||
}
|
||||
|
||||
canvas.drawLine(
|
||||
Offset(0, 0), Offset(size.width - _kScaleHeight, 0), gridPaint);
|
||||
|
||||
canvas.drawLine(Offset(-_kScaleHeight, 0), Offset(0, 0), axisPaint);
|
||||
String str = '${(numStep * i).toStringAsFixed(0)}';
|
||||
_drawAxisText(canvas, str, offset: Offset(-10, 2));
|
||||
canvas.translate(0, -yStep);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void _drawAxisText(Canvas canvas, String str,
|
||||
{Color color = Colors.black,
|
||||
bool x = false,
|
||||
Alignment alignment = Alignment.centerRight,
|
||||
Offset offset = Offset.zero}) {
|
||||
TextSpan text = TextSpan(
|
||||
text: str,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: color,
|
||||
));
|
||||
|
||||
_textPainter.text = text;
|
||||
_textPainter.layout(); // 进行布局
|
||||
|
||||
Size size = _textPainter.size;
|
||||
|
||||
Offset offsetPos = Offset(-size.width / 2, -size.height / 2)
|
||||
.translate(-size.width / 2 * alignment.x + offset.dx, 0.0 + offset.dy);
|
||||
_textPainter.paint(canvas, offsetPos);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
|
||||
}
|
||||
237
packages/idraw/lib/p16/s04.dart
Normal file
237
packages/idraw/lib/p16/s04.dart
Normal file
@@ -0,0 +1,237 @@
|
||||
import 'dart:math';
|
||||
import 'dart:ui';
|
||||
|
||||
// import 'dart:ui' as ui;
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// create by 张风捷特烈 on 2020/11/5
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明:
|
||||
class Paper extends StatelessWidget {
|
||||
const Paper({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
alignment: Alignment.center,
|
||||
child: const ICharts(),
|
||||
);
|
||||
}
|
||||
}
|
||||
class ICharts extends StatefulWidget {
|
||||
const ICharts({super.key});
|
||||
|
||||
@override
|
||||
_IChartsState createState() => _IChartsState();
|
||||
}
|
||||
|
||||
class _IChartsState extends State<ICharts> with SingleTickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
duration: const Duration(milliseconds: 1000),
|
||||
vsync: this,
|
||||
)
|
||||
..forward()
|
||||
;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(alignment: Alignment.topCenter, children: [
|
||||
Container(
|
||||
width: 350,
|
||||
height: 250,
|
||||
padding: EdgeInsets.only(top: 40, right: 20, bottom: 20, left: 20),
|
||||
child: CustomPaint(
|
||||
painter: ChartPainter(repaint: _controller),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
"捷特数学成绩统计图 - 2040 年",
|
||||
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||
),
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
const double _kScaleHeight = 8; // 刻度高
|
||||
const double _kBarPadding = 10; // 柱状图前间隔
|
||||
|
||||
class ChartPainter extends CustomPainter {
|
||||
final TextPainter _textPainter =
|
||||
TextPainter(textDirection: TextDirection.ltr);
|
||||
|
||||
final List<double> yData = [88, 98, 70, 80, 100, 75];
|
||||
final List<String> xData = ["7月", "8月", "9月", "10月", "11月", "12月"];
|
||||
|
||||
// final List<String> xData = [ "语文","数学", "英语", "物理", "化学", "生物"];
|
||||
|
||||
final Animation<double> repaint;
|
||||
|
||||
Path axisPath = Path();
|
||||
Paint axisPaint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 1;
|
||||
|
||||
Paint gridPaint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..color = Colors.grey
|
||||
..strokeWidth = 0.5;
|
||||
Paint fillPaint = Paint()..color = Colors.red;
|
||||
Paint linePaint = Paint()
|
||||
..color = Colors.orange
|
||||
..strokeCap=StrokeCap.round
|
||||
..style = PaintingStyle.stroke;
|
||||
|
||||
double xStep = 0; // x 间隔
|
||||
double yStep = 0; // y 间隔
|
||||
|
||||
double maxData = 0; // 数据最大值
|
||||
|
||||
final List<Offset> line = []; // 折线点位信息
|
||||
|
||||
ChartPainter({required this.repaint}) : super(repaint: repaint) {
|
||||
maxData = yData.reduce(max);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
xStep = (size.width - _kScaleHeight) / xData.length;
|
||||
yStep = (size.height - _kScaleHeight) / 5;
|
||||
|
||||
canvas.translate(0, size.height);
|
||||
canvas.translate(_kScaleHeight, -_kScaleHeight);
|
||||
axisPath.moveTo(-_kScaleHeight, 0);
|
||||
axisPath.relativeLineTo(size.width, 0);
|
||||
axisPath.moveTo(0, _kScaleHeight);
|
||||
axisPath.relativeLineTo(0, -size.height);
|
||||
canvas.drawPath(axisPath, axisPaint);
|
||||
|
||||
drawYText(canvas, size);
|
||||
drawXText(canvas, size);
|
||||
collectPoints(canvas, size);
|
||||
drawLineChart(canvas);
|
||||
}
|
||||
|
||||
void drawXText(Canvas canvas, Size size) {
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(xStep, 0);
|
||||
for (int i = 0; i < xData.length; i++) {
|
||||
canvas.drawLine(Offset(0, 0), Offset(0, _kScaleHeight), axisPaint);
|
||||
_drawAxisText(canvas, xData[i],
|
||||
alignment: Alignment.center, offset: Offset(-xStep / 2, 10));
|
||||
canvas.translate(xStep, 0);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void collectPoints(Canvas canvas, Size size) {
|
||||
line.clear();
|
||||
canvas.translate(xStep, 0);
|
||||
for (int i = 0; i < xData.length; i++) {
|
||||
double dataHeight = -(yData[i] / maxData * (size.height - _kScaleHeight));
|
||||
line.add(Offset(xStep * i-xStep/2, dataHeight));
|
||||
}
|
||||
}
|
||||
|
||||
void drawLineChart(Canvas canvas){
|
||||
canvas.drawPoints(PointMode.points, line, linePaint..strokeWidth=5);
|
||||
Path path = Path();
|
||||
addBezierPathWithPoints(path, line);
|
||||
linePaint..strokeWidth=1;
|
||||
PathMetrics pms = path.computeMetrics();
|
||||
pms.forEach((pm) {
|
||||
canvas.drawPath(pm.extractPath(0, pm.length * repaint.value), linePaint);
|
||||
});
|
||||
}
|
||||
|
||||
void drawYText(Canvas canvas, Size size) {
|
||||
canvas.save();
|
||||
double numStep = maxData / 5;
|
||||
for (int i = 0; i <= 5; i++) {
|
||||
if (i == 0) {
|
||||
_drawAxisText(canvas, '0', offset: Offset(-10, 2));
|
||||
canvas.translate(0, -yStep);
|
||||
continue;
|
||||
}
|
||||
|
||||
canvas.drawLine(
|
||||
Offset(0, 0), Offset(size.width - _kScaleHeight, 0), gridPaint);
|
||||
|
||||
canvas.drawLine(Offset(-_kScaleHeight, 0), Offset(0, 0), axisPaint);
|
||||
String str = '${(numStep * i).toStringAsFixed(0)}';
|
||||
_drawAxisText(canvas, str, offset: Offset(-10, 2));
|
||||
canvas.translate(0, -yStep);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void addBezierPathWithPoints(Path path, List<Offset> points) {
|
||||
for (int i = 0; i < points.length - 1; i++) {
|
||||
Offset current = points[i];
|
||||
Offset next = points[i+1];
|
||||
if (i == 0) {
|
||||
path.moveTo(current.dx, current.dy);
|
||||
// 控制点
|
||||
double ctrlX = current.dx + (next.dx - current.dx) / 2;
|
||||
double ctrlY = next.dy;
|
||||
path.quadraticBezierTo(ctrlX, ctrlY, next.dx, next.dy);
|
||||
} else if (i < points.length - 2) {
|
||||
// 控制点 1
|
||||
double ctrl1X = current.dx + (next.dx - current.dx) / 2;
|
||||
double ctrl1Y = current.dy;
|
||||
// 控制点 2
|
||||
double ctrl2X = ctrl1X;
|
||||
double ctrl2Y = next.dy;
|
||||
path.cubicTo(ctrl1X,ctrl1Y,ctrl2X,ctrl2Y,next.dx,next.dy);
|
||||
}else{
|
||||
// 控制点
|
||||
double ctrlX = (next.dx - current.dx) / 2;
|
||||
double ctrlY = 0;
|
||||
path.relativeQuadraticBezierTo(ctrlX, ctrlY, next.dx-current.dx, next.dy-current.dy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _drawAxisText(Canvas canvas, String str,
|
||||
{Color color = Colors.black,
|
||||
bool x = false,
|
||||
Alignment alignment = Alignment.centerRight,
|
||||
Offset offset = Offset.zero}) {
|
||||
TextSpan text = TextSpan(
|
||||
text: str,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: color,
|
||||
));
|
||||
|
||||
_textPainter.text = text;
|
||||
_textPainter.layout(); // 进行布局
|
||||
|
||||
Size size = _textPainter.size;
|
||||
|
||||
Offset offsetPos = Offset(-size.width / 2, -size.height / 2)
|
||||
.translate(-size.width / 2 * alignment.x + offset.dx, 0.0 + offset.dy);
|
||||
_textPainter.paint(canvas, offsetPos);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
|
||||
}
|
||||
232
packages/idraw/lib/p16/s05.dart
Normal file
232
packages/idraw/lib/p16/s05.dart
Normal file
@@ -0,0 +1,232 @@
|
||||
import 'dart:math';
|
||||
import 'dart:ui';
|
||||
|
||||
// import 'dart:ui' as ui;
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// create by 张风捷特烈 on 2020/11/5
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明:
|
||||
class Paper extends StatelessWidget {
|
||||
const Paper({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
alignment: Alignment.center,
|
||||
child: const ICharts(),
|
||||
);
|
||||
}
|
||||
}
|
||||
class ICharts extends StatefulWidget {
|
||||
const ICharts({super.key});
|
||||
|
||||
@override
|
||||
_IChartsState createState() => _IChartsState();
|
||||
}
|
||||
|
||||
class _IChartsState extends State<ICharts> with SingleTickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
duration: const Duration(milliseconds: 1000),
|
||||
vsync: this,
|
||||
)
|
||||
..forward()
|
||||
;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(alignment: Alignment.topCenter, children: [
|
||||
Container(
|
||||
width: 350,
|
||||
height: 250,
|
||||
padding: EdgeInsets.only(top: 40, right: 20, bottom: 20, left: 20),
|
||||
child: CustomPaint(
|
||||
painter: ChartPainter(repaint: _controller),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
"捷特数学成绩统计图 - 2040 年",
|
||||
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||
),
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
const double _kScaleHeight = 8; // 刻度高
|
||||
const double _kBarPadding = 10; // 柱状图前间隔
|
||||
|
||||
class ChartPainter extends CustomPainter {
|
||||
final TextPainter _textPainter =
|
||||
TextPainter(textDirection: TextDirection.ltr);
|
||||
|
||||
final List<double> yData = [88, 98, 70, 80, 100, 75];
|
||||
final List<String> xData = ["7月", "8月", "9月", "10月", "11月", "12月"];
|
||||
|
||||
// final List<String> xData = [ "语文","数学", "英语", "物理", "化学", "生物"];
|
||||
|
||||
final Animation<double> repaint;
|
||||
|
||||
Path axisPath = Path();
|
||||
Paint axisPaint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 1;
|
||||
|
||||
Paint gridPaint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..color = Colors.grey
|
||||
..strokeWidth = 0.5;
|
||||
Paint fillPaint = Paint()..color = Colors.red;
|
||||
Paint linePaint = Paint()
|
||||
..color = Colors.red
|
||||
..strokeCap=StrokeCap.round
|
||||
..style = PaintingStyle.stroke;
|
||||
|
||||
double xStep = 0; // x 间隔
|
||||
double yStep = 0; // y 间隔
|
||||
|
||||
double maxData = 0; // 数据最大值
|
||||
|
||||
final List<Offset> line = []; // 折线点位信息
|
||||
|
||||
ChartPainter({required this.repaint}) : super(repaint: repaint) {
|
||||
maxData = yData.reduce(max);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
xStep = (size.width - _kScaleHeight) / xData.length;
|
||||
yStep = (size.height - _kScaleHeight) / 5;
|
||||
|
||||
canvas.translate(0, size.height);
|
||||
canvas.translate(_kScaleHeight, -_kScaleHeight);
|
||||
axisPath.moveTo(-_kScaleHeight, 0);
|
||||
axisPath.relativeLineTo(size.width, 0);
|
||||
axisPath.moveTo(0, _kScaleHeight);
|
||||
axisPath.relativeLineTo(0, -size.height);
|
||||
canvas.drawPath(axisPath, axisPaint);
|
||||
|
||||
drawYText(canvas, size);
|
||||
drawXText(canvas, size);
|
||||
drawBarChart(canvas,size);
|
||||
collectPoints(canvas, size);
|
||||
drawLineChart(canvas);
|
||||
}
|
||||
|
||||
void drawXText(Canvas canvas, Size size) {
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(xStep, 0);
|
||||
for (int i = 0; i < xData.length; i++) {
|
||||
canvas.drawLine(Offset(0, 0), Offset(0, _kScaleHeight), axisPaint);
|
||||
_drawAxisText(canvas, xData[i],
|
||||
alignment: Alignment.center, offset: Offset(-xStep / 2, 10));
|
||||
canvas.translate(xStep, 0);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void collectPoints(Canvas canvas, Size size) {
|
||||
line.clear();
|
||||
canvas.translate(xStep, 0);
|
||||
for (int i = 0; i < xData.length; i++) {
|
||||
double dataHeight = -(yData[i] / maxData * (size.height - _kScaleHeight));
|
||||
line.add(Offset(xStep * i-xStep/2, dataHeight));
|
||||
}
|
||||
}
|
||||
|
||||
void drawBarChart(Canvas canvas, Size size) {
|
||||
fillPaint..color=Colors.lightBlue;
|
||||
canvas.save();
|
||||
canvas.translate(xStep, 0);
|
||||
for (int i = 0; i < xData.length; i++) {
|
||||
double dataHeight = -(yData[i] / maxData * (size.height - _kScaleHeight));
|
||||
canvas.drawRect(
|
||||
Rect.fromLTWH(
|
||||
_kBarPadding, 0, xStep-2*_kBarPadding, dataHeight*repaint.value)
|
||||
.translate(-xStep, 0),
|
||||
fillPaint);
|
||||
canvas.translate(xStep, 0);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
|
||||
void drawLineChart(Canvas canvas){
|
||||
canvas.drawPoints(PointMode.points, line, linePaint..strokeWidth=5);
|
||||
|
||||
Offset p1 = line[0];
|
||||
Path path = Path()..moveTo(p1.dx, p1.dy);
|
||||
for (var i = 1; i < line.length; i++) {
|
||||
path.lineTo(line[i].dx, line[i].dy);
|
||||
}
|
||||
linePaint..strokeWidth=1;
|
||||
PathMetrics pms = path.computeMetrics();
|
||||
pms.forEach((pm) {
|
||||
canvas.drawPath(pm.extractPath(0, pm.length * repaint.value), linePaint);
|
||||
});
|
||||
}
|
||||
|
||||
void drawYText(Canvas canvas, Size size) {
|
||||
canvas.save();
|
||||
double numStep = maxData / 5;
|
||||
for (int i = 0; i <= 5; i++) {
|
||||
if (i == 0) {
|
||||
_drawAxisText(canvas, '0', offset: Offset(-10, 2));
|
||||
canvas.translate(0, -yStep);
|
||||
continue;
|
||||
}
|
||||
|
||||
canvas.drawLine(
|
||||
Offset(0, 0), Offset(size.width - _kScaleHeight, 0), gridPaint);
|
||||
|
||||
canvas.drawLine(Offset(-_kScaleHeight, 0), Offset(0, 0), axisPaint);
|
||||
String str = '${(numStep * i).toStringAsFixed(0)}';
|
||||
_drawAxisText(canvas, str, offset: Offset(-10, 2));
|
||||
canvas.translate(0, -yStep);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void _drawAxisText(Canvas canvas, String str,
|
||||
{Color color = Colors.black,
|
||||
bool x = false,
|
||||
Alignment alignment = Alignment.centerRight,
|
||||
Offset offset = Offset.zero}) {
|
||||
TextSpan text = TextSpan(
|
||||
text: str,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: color,
|
||||
));
|
||||
|
||||
_textPainter.text = text;
|
||||
_textPainter.layout(); // 进行布局
|
||||
|
||||
Size size = _textPainter.size;
|
||||
|
||||
Offset offsetPos = Offset(-size.width / 2, -size.height / 2)
|
||||
.translate(-size.width / 2 * alignment.x + offset.dx, 0.0 + offset.dy);
|
||||
_textPainter.paint(canvas, offsetPos);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
|
||||
}
|
||||
254
packages/idraw/lib/p16/s06.dart
Normal file
254
packages/idraw/lib/p16/s06.dart
Normal file
@@ -0,0 +1,254 @@
|
||||
import 'dart:math';
|
||||
import 'dart:ui';
|
||||
|
||||
// import 'dart:ui' as ui;
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// create by 张风捷特烈 on 2020/11/5
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明:
|
||||
class Paper extends StatelessWidget {
|
||||
const Paper({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
alignment: Alignment.center,
|
||||
child: const ICharts(),
|
||||
);
|
||||
}
|
||||
}
|
||||
class ICharts extends StatefulWidget {
|
||||
const ICharts({super.key});
|
||||
|
||||
@override
|
||||
_IChartsState createState() => _IChartsState();
|
||||
}
|
||||
|
||||
class _IChartsState extends State<ICharts> with SingleTickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
duration: const Duration(milliseconds: 1000),
|
||||
vsync: this,
|
||||
)
|
||||
..forward()
|
||||
;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(alignment: Alignment.topCenter, children: [
|
||||
Container(
|
||||
width: 400,
|
||||
height: 300,
|
||||
padding: EdgeInsets.only(top: 40, right: 20, bottom: 20, left: 20),
|
||||
child: CustomPaint(
|
||||
painter: ChartPainter(repaint: _controller),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
"捷特 3 月支出统计图 - 2040 年",
|
||||
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||
),
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
const double _kScaleHeight = 8; // 刻度高
|
||||
const double _kBarPadding = 10; // 柱状图前间隔
|
||||
const double _kPiePadding = 20; // 饼状图边距
|
||||
|
||||
class ChartPainter extends CustomPainter {
|
||||
final TextPainter _textPainter =
|
||||
TextPainter(textDirection: TextDirection.ltr);
|
||||
|
||||
final List<double> yData = [0.12, 0.25, 0.1, 0.18, 0.15, 0.2];
|
||||
final List<Color> colors = [
|
||||
Colors.red,
|
||||
Colors.orangeAccent,
|
||||
Colors.blue,
|
||||
Colors.green,
|
||||
Colors.purple,
|
||||
Colors.pink
|
||||
];
|
||||
final List<String> xData = ["学习资料", "伙食费", "话费", "游玩", "游戏", "其他"];
|
||||
|
||||
final Animation<double> repaint;
|
||||
|
||||
Path axisPath = Path();
|
||||
Paint axisPaint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 1;
|
||||
|
||||
Paint gridPaint = Paint()
|
||||
..style = PaintingStyle.stroke
|
||||
..color = Colors.grey
|
||||
..strokeWidth = 0.5;
|
||||
Paint fillPaint = Paint()..color = Colors.red;
|
||||
Paint linePaint = Paint()
|
||||
..color = Colors.red
|
||||
..strokeCap = StrokeCap.round
|
||||
..style = PaintingStyle.stroke;
|
||||
|
||||
double radius = 0; // 饼图半径
|
||||
double yStep = 0; // y 间隔
|
||||
|
||||
double maxData = 0; // 数据最大值
|
||||
|
||||
final List<Offset> line = []; // 折线点位信息
|
||||
|
||||
ChartPainter({required this.repaint}) : super(repaint: repaint) {
|
||||
maxData = yData.reduce(max);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
radius = size.shortestSide / 2 - _kPiePadding;
|
||||
|
||||
canvas.translate(size.width / 2, size.height / 2);
|
||||
canvas.rotate(-pi / 2);
|
||||
|
||||
Path clipPath = Path();
|
||||
clipPath.lineTo(radius, 0);
|
||||
clipPath.arcTo(
|
||||
Rect.fromCenter(center: Offset.zero, width: radius * 4, height: radius * 4),
|
||||
0, 2 * pi * repaint.value, false);
|
||||
clipPath.close();
|
||||
if(repaint.value!=1.0){
|
||||
canvas.clipPath(clipPath);
|
||||
}
|
||||
|
||||
|
||||
drawPieChart(canvas);
|
||||
drawInfo(canvas);
|
||||
}
|
||||
|
||||
void drawInfo(Canvas canvas) {
|
||||
for (int i = 0; i < yData.length; i++) {
|
||||
Color color = colors[i % colors.length];
|
||||
|
||||
canvas.save();
|
||||
canvas.rotate(2 * pi * yData[i] / 2);
|
||||
_drawAxisText(canvas, "${(yData[i] * 100).toStringAsFixed(1)}%",
|
||||
color: Colors.white,
|
||||
alignment: Alignment.center,
|
||||
offset: Offset(radius / 2 + 5, 0));
|
||||
|
||||
Path showPath = Path();
|
||||
showPath.moveTo(radius, 0);
|
||||
showPath.relativeLineTo(15, 0);
|
||||
showPath.relativeLineTo(5, 10);
|
||||
canvas.drawPath(
|
||||
showPath,
|
||||
linePaint..color = color,
|
||||
);
|
||||
|
||||
_drawAxisText(canvas, xData[i],
|
||||
color: color,
|
||||
fontSize: 9,
|
||||
alignment: Alignment.centerLeft,
|
||||
offset: Offset(radius + 5, 18));
|
||||
canvas.restore();
|
||||
|
||||
canvas.rotate(2 * pi * yData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void drawPieChart(Canvas canvas) {
|
||||
for (int i = 0; i < yData.length; i++) {
|
||||
Color color = colors[i % colors.length];
|
||||
Path path = Path();
|
||||
path.lineTo(radius, 0);
|
||||
path.arcTo(
|
||||
Rect.fromCenter(
|
||||
center: Offset.zero, width: radius * 2, height: radius * 2),
|
||||
0,
|
||||
2 * pi * yData[i],
|
||||
false);
|
||||
path.close();
|
||||
canvas.drawPath(
|
||||
path,
|
||||
fillPaint
|
||||
..style = PaintingStyle.fill
|
||||
..color = color);
|
||||
canvas.rotate(2 * pi * yData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void drawLineChart(Canvas canvas) {
|
||||
canvas.drawPoints(PointMode.points, line, linePaint..strokeWidth = 5);
|
||||
|
||||
Offset p1 = line[0];
|
||||
Path path = Path()..moveTo(p1.dx, p1.dy);
|
||||
for (var i = 1; i < line.length; i++) {
|
||||
path.lineTo(line[i].dx, line[i].dy);
|
||||
}
|
||||
linePaint..strokeWidth = 1;
|
||||
PathMetrics pms = path.computeMetrics();
|
||||
pms.forEach((pm) {
|
||||
canvas.drawPath(pm.extractPath(0, pm.length * repaint.value), linePaint);
|
||||
});
|
||||
}
|
||||
|
||||
void drawYText(Canvas canvas, Size size) {
|
||||
canvas.save();
|
||||
double numStep = maxData / 5;
|
||||
for (int i = 0; i <= 5; i++) {
|
||||
if (i == 0) {
|
||||
_drawAxisText(canvas, '0', offset: Offset(-10, 2));
|
||||
canvas.translate(0, -yStep);
|
||||
continue;
|
||||
}
|
||||
|
||||
canvas.drawLine(
|
||||
Offset(0, 0), Offset(size.width - _kScaleHeight, 0), gridPaint);
|
||||
|
||||
canvas.drawLine(Offset(-_kScaleHeight, 0), Offset(0, 0), axisPaint);
|
||||
String str = '${(numStep * i).toStringAsFixed(0)}';
|
||||
_drawAxisText(canvas, str, offset: Offset(-10, 2));
|
||||
canvas.translate(0, -yStep);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void _drawAxisText(Canvas canvas, String str,
|
||||
{Color color = Colors.black,
|
||||
double fontSize = 11,
|
||||
bool x = false,
|
||||
Alignment alignment = Alignment.centerRight,
|
||||
Offset offset = Offset.zero}) {
|
||||
TextSpan text = TextSpan(
|
||||
text: str,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
color: color,
|
||||
));
|
||||
|
||||
_textPainter.text = text;
|
||||
_textPainter.layout(); // 进行布局
|
||||
|
||||
Size size = _textPainter.size;
|
||||
|
||||
Offset offsetPos = Offset(-size.width / 2, -size.height / 2)
|
||||
.translate(-size.width / 2 * alignment.x + offset.dx, 0.0 + offset.dy);
|
||||
_textPainter.paint(canvas, offsetPos);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
}
|
||||
Reference in New Issue
Block a user