Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added axis titles #115

Merged
merged 6 commits into from
Dec 30, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions example/lib/line_chart/samples/line_chart_sample4.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ class LineChartSample4 extends StatelessWidget {
@override
Widget build(BuildContext context) {
const cutOffYValue = 5.0;
const dateTextStyle = TextStyle(
fontSize: 10, color: Colors.purple, fontWeight: FontWeight.bold);

return SizedBox(
width: 300,
Expand Down Expand Up @@ -54,8 +56,8 @@ class LineChartSample4 extends StatelessWidget {
titlesData: FlTitlesData(
bottomTitles: SideTitles(
showTitles: true,
textStyle:
TextStyle(fontSize: 10, color: Colors.purple, fontWeight: FontWeight.bold),
reservedSize: 14,
textStyle: dateTextStyle,
getTitles: (value) {
switch (value.toInt()) {
case 0:
Expand Down Expand Up @@ -93,6 +95,15 @@ class LineChartSample4 extends StatelessWidget {
},
),
),
axisTitleData: const FlAxisTitleData(
leftTitle:
AxisTitle(showTitle: true, titleText: 'Value', margin: 4),
bottomTitle: AxisTitle(
showTitle: true,
margin: 0,
titleText: '2019',
textStyle: dateTextStyle,
textAlign: TextAlign.right)),
gridData: FlGridData(
show: true,
checkToShowHorizontalGrid: (double value) {
Expand Down
7 changes: 7 additions & 0 deletions example/lib/line_chart/samples/line_chart_sample5.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ class LineChartSample5 extends StatelessWidget {
fontSize: 18,
)),
),
axisTitleData: const FlAxisTitleData(
rightTitle: AxisTitle(showTitle: true, titleText: 'count'),
leftTitle: AxisTitle(showTitle: true, titleText: 'count'),
topTitle: AxisTitle(
showTitle: true,
titleText: 'Wall clock',
textAlign: TextAlign.left)),
gridData: const FlGridData(show: false),
borderData: FlBorderData(
show: true,
Expand Down
6 changes: 6 additions & 0 deletions lib/src/chart/bar_chart/bar_chart_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:flutter/material.dart';
/// This class is responsible to holds data to draw Bar Chart
/// [barGroups] holds list of bar groups to show together,
/// [groupsSpace] space between groups, it applies only when the [alignment] is [Alignment.center],
/// [axisTitleData] to show a description of each axis
/// [alignment] is the alignment of showing groups,
/// [titlesData] holds data about drawing left and bottom titles.
class BarChartData extends AxisChartData {
Expand All @@ -30,11 +31,13 @@ class BarChartData extends AxisChartData {
show: false,
),
FlBorderData borderData,
FlAxisTitleData axisTitleData = const FlAxisTitleData(),
double maxY,
Color backgroundColor,
}) : super(
gridData: gridData,
borderData: borderData,
axisTitleData: axisTitleData,
backgroundColor: backgroundColor,
touchData: barTouchData,
) {
Expand Down Expand Up @@ -91,6 +94,7 @@ class BarChartData extends AxisChartData {
double groupsSpace,
BarChartAlignment alignment,
FlTitlesData titlesData,
FlAxisTitleData axisTitleData,
BarTouchData barTouchData,
FlGridData gridData,
FlBorderData borderData,
Expand All @@ -102,6 +106,7 @@ class BarChartData extends AxisChartData {
groupsSpace: groupsSpace ?? this.groupsSpace,
alignment: alignment ?? this.alignment,
titlesData: titlesData ?? this.titlesData,
axisTitleData: axisTitleData ?? this.axisTitleData,
barTouchData: barTouchData ?? this.barTouchData,
gridData: gridData ?? this.gridData,
borderData: borderData ?? this.borderData,
Expand All @@ -118,6 +123,7 @@ class BarChartData extends AxisChartData {
groupsSpace: lerpDouble(a.groupsSpace, b.groupsSpace, t),
alignment: b.alignment,
titlesData: FlTitlesData.lerp(a.titlesData, b.titlesData, t),
axisTitleData: FlAxisTitleData.lerp(a.axisTitleData, b.axisTitleData, t),
barTouchData: b.barTouchData,
gridData: FlGridData.lerp(a.gridData, b.gridData, t),
borderData: FlBorderData.lerp(a.borderData, b.borderData, t),
Expand Down
1 change: 1 addition & 0 deletions lib/src/chart/bar_chart/bar_chart_painter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class BarChartPainter extends AxisChartPainter<BarChartData> with TouchHandler<B
groupBarsPosition = calculateGroupAndBarsPosition(size, groupsX, data.barGroups);

drawBars(canvas, size, groupBarsPosition);
drawAxisTitles(canvas, size);
drawTitles(canvas, size, groupBarsPosition);

for (int i = 0; i < targetData.barGroups.length; i++) {
Expand Down
2 changes: 2 additions & 0 deletions lib/src/chart/base/axis_chart/axis_chart_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'package:flutter/material.dart';
/// each child have to set it in their constructor.
abstract class AxisChartData extends BaseChartData {
final FlGridData gridData;
final FlAxisTitleData axisTitleData;

double minX, maxX;
double minY, maxY;
Expand All @@ -26,6 +27,7 @@ abstract class AxisChartData extends BaseChartData {
this.gridData = const FlGridData(),
FlBorderData borderData,
FlTouchData touchData,
this.axisTitleData,
this.minX,
this.maxX,
this.minY,
Expand Down
148 changes: 148 additions & 0 deletions lib/src/chart/base/axis_chart/axis_chart_painter.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:math' as math;

import 'package:fl_chart/src/chart/bar_chart/bar_chart_painter.dart';
import 'package:fl_chart/src/chart/base/base_chart/base_chart_painter.dart';
import 'package:fl_chart/src/chart/line_chart/line_chart_painter.dart';
Expand Down Expand Up @@ -28,6 +30,152 @@ abstract class AxisChartPainter<D extends AxisChartData> extends BaseChartPainte
drawGrid(canvas, size);
}


void drawAxisTitles(Canvas canvas, Size viewSize) {
if (!data.axisTitleData.show) {
return;
}
viewSize = getChartUsableDrawSize(viewSize);

final axisTitles = data.axisTitleData;

// Left Title
final leftTitle = axisTitles.leftTitle;
if (leftTitle.showTitle) {
final TextSpan span =
TextSpan(style: leftTitle.textStyle, text: leftTitle.titleText);
final TextPainter tp = TextPainter(
text: span,
textAlign: leftTitle.textAlign,
textDirection: TextDirection.ltr);
tp.layout(minWidth: viewSize.height);
canvas.save();
canvas.rotate(-math.pi * 0.5);
tp.paint(
canvas,
Offset(-viewSize.height - getTopOffsetDrawSize(),
leftTitle.reservedSize - tp.height));
canvas.restore();
}

// Top title
final topTitle = axisTitles.topTitle;
if (topTitle.showTitle) {
final TextSpan span =
TextSpan(style: topTitle.textStyle, text: topTitle.titleText);
final TextPainter tp = TextPainter(
text: span,
textAlign: topTitle.textAlign,
textDirection: TextDirection.ltr);
tp.layout(minWidth: viewSize.width);
tp.paint(canvas,
Offset(getLeftOffsetDrawSize(), topTitle.reservedSize - tp.height));
}

// Right Title
final rightTitle = axisTitles.rightTitle;
if (rightTitle.showTitle) {
final TextSpan span =
TextSpan(style: rightTitle.textStyle, text: rightTitle.titleText);
final TextPainter tp = TextPainter(
text: span,
textAlign: rightTitle.textAlign,
textDirection: TextDirection.ltr);
tp.layout(minWidth: viewSize.height);
canvas.save();
canvas.rotate(-math.pi * 0.5);
tp.paint(
canvas,
Offset(
-viewSize.height - getTopOffsetDrawSize(),
viewSize.width +
getExtraNeededHorizontalSpace() -
rightTitle.reservedSize));
canvas.restore();
}

// Bottom title
final bottomTitle = axisTitles.bottomTitle;
if (bottomTitle.showTitle) {
final TextSpan span =
TextSpan(style: bottomTitle.textStyle, text: bottomTitle.titleText);
final TextPainter tp = TextPainter(
text: span,
textAlign: bottomTitle.textAlign,
textDirection: TextDirection.ltr);
tp.layout(minWidth: viewSize.width);
tp.paint(
canvas,
Offset(
getLeftOffsetDrawSize(),
getExtraNeededVerticalSpace() -
bottomTitle.reservedSize +
viewSize.height));
}
}

@override
double getExtraNeededHorizontalSpace() {
double sum = super.getExtraNeededHorizontalSpace();

if (data.axisTitleData.show) {
final leftSide = data.axisTitleData.leftTitle;
if (leftSide.showTitle) {
sum += leftSide.reservedSize + leftSide.margin;
}

final rightSide = data.axisTitleData.rightTitle;
if (rightSide.showTitle) {
sum += rightSide.reservedSize + rightSide.margin;
}
}

return sum;
}

@override
double getExtraNeededVerticalSpace() {
double sum = super.getExtraNeededVerticalSpace();

if (data.axisTitleData.show) {
final topSide = data.axisTitleData.topTitle;
if (topSide.showTitle) {
sum += topSide.reservedSize + topSide.margin;
}

final bottomSide = data.axisTitleData.bottomTitle;
if (bottomSide.showTitle) {
sum += bottomSide.reservedSize + bottomSide.margin;
}
}

return sum;
}

@override
double getLeftOffsetDrawSize() {
var sum = super.getLeftOffsetDrawSize();

final leftAxisTitle = data.axisTitleData.leftTitle;
if (data.axisTitleData.show && leftAxisTitle.showTitle) {
sum += leftAxisTitle.reservedSize + leftAxisTitle.margin;
}

return sum;
}

@override
double getTopOffsetDrawSize() {
var sum = super.getTopOffsetDrawSize();

final topAxisTitle = data.axisTitleData.topTitle;
if (data.axisTitleData.show && topAxisTitle.showTitle) {
sum += topAxisTitle.reservedSize + topAxisTitle.margin;
}

return sum;
}

void drawGrid(Canvas canvas, Size viewSize) {
if (!data.gridData.show || data.gridData == null) {
return;
Expand Down
65 changes: 64 additions & 1 deletion lib/src/chart/base/base_chart/base_chart_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class FlBorderData {
);
}


}

/***** TouchData *****/
Expand All @@ -72,6 +72,69 @@ class FlTouchData {
const FlTouchData(this.enabled, this.enableNormalTouch);
}

///***** AxisTitleData *****/

/// This class holds data about the description for each axis of the chart.
class FlAxisTitleData {
final bool show;

final AxisTitle leftTitle, topTitle, rightTitle, bottomTitle;

const FlAxisTitleData({
this.show = true,
this.leftTitle = const AxisTitle(reservedSize: 16),
this.topTitle = const AxisTitle(reservedSize: 16),
this.rightTitle = const AxisTitle(reservedSize: 16),
this.bottomTitle = const AxisTitle(reservedSize: 16),
});

static FlAxisTitleData lerp(FlAxisTitleData a, FlAxisTitleData b, double t) {
return FlAxisTitleData(
show: b.show,
leftTitle: AxisTitle.lerp(a.leftTitle, b.leftTitle, t),
rightTitle: AxisTitle.lerp(a.rightTitle, b.rightTitle, t),
bottomTitle: AxisTitle.lerp(a.bottomTitle, b.bottomTitle, t),
topTitle: AxisTitle.lerp(a.topTitle, b.topTitle, t),
);
}
}

/// specify each axis titles data
class AxisTitle {
final bool showTitle;
final double reservedSize;
final TextStyle textStyle;
final TextAlign textAlign;
final double margin;
final String titleText;

const AxisTitle({
this.showTitle = false,
this.titleText = '',
this.reservedSize = 14,
this.textStyle = const TextStyle(
color: Colors.black,
fontSize: 11,
),
this.textAlign = TextAlign.center,
this.margin = 4,
});

static AxisTitle lerp(AxisTitle a, AxisTitle b, double t) {
return AxisTitle(
showTitle: b.showTitle,
titleText: b.titleText,
reservedSize: lerpDouble(a.reservedSize, b.reservedSize, t),
textStyle: TextStyle.lerp(
a.textStyle.copyWith(fontSize: a.textStyle.fontSize),
b.textStyle.copyWith(fontSize: b.textStyle.fontSize),
t),
textAlign: b.textAlign,
margin: lerpDouble(a.margin, b.margin, t),
);
}
}

/***** TitlesData *****/

/// we use this typedef to determine which titles
Expand Down
Loading