juliansteenbakker / community_charts

This project is a fork of google/charts.
Apache License 2.0
84 stars 34 forks source link

First Y Axis Tick Label Sometimes Missing on Area Chart; Area Shading Sometimes Spills Over X Axis #17

Open cedarbob opened 9 months ago

cedarbob commented 9 months ago

When I create 2 Area Charts from the same data set, one which uses the default y extent, and a second which uses a computed extent I supplied, the first y axis tick mark in the second chart is unlabeled (see pic).

The second problem I noted is that the area shading sometimes spills over the x axis my a few pixels.

ChartTestScreenshot

import 'dart:math';

import 'package:flutter/material.dart';

import 'package:community_charts_flutter/community_charts_flutter.dart';

void main() {

  runApp(const MaterialApp(
    title: 'Area Test',
    home: TestPage(),
    debugShowCheckedModeBanner: false,
  ));
}

/// Shows 2 area charts (one with default y extent, other computed y extent)
class TestPage extends StatelessWidget {

  const TestPage({super.key});

  @override
  Widget build(BuildContext context) {

    var windowSize = MediaQuery.of(context).size;

    return Scaffold(
      appBar: AppBar(title: const Center(child:Text('Two Charts'))),
      body: Center(child:Column(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: <Widget>[
        ElevationChart(data, windowSize),
        ElevationChart(data, windowSize, computeYViewport: true),
      ]))
    );

  }
}

/// Draws area chart of elevation vs distance traveled.
class ElevationChart extends StatelessWidget {

  late final Series<Point, double> dataSeries;

  late final Size                  windowSize;

  late final NumericExtents?       yViewport;

  ElevationChart(List<Point> track, this.windowSize, {super.key,
    bool computeYViewport = false}) {

    yViewport = computeYViewport ? _computeYViewport(track) : null;

    dataSeries = Series<Point, double>(
      id: "test_chart",
      data: track,
      colorFn: (_, __) => MaterialPalette.blue.shadeDefault,
      domainFn: (Point point, _) => point.x,
      measureFn: (Point point, _) => point.y,
    );
  }

  @override
  Widget build(BuildContext context) {

    var width = 0.8 * windowSize.width;
    var height = 0.4 * windowSize.height;
    var domainTickSpec = const BasicNumericTickProviderSpec(
        desiredMinTickCount: 8, dataIsInWholeNumbers: false);
    var measureTicSpec = const BasicNumericTickProviderSpec(zeroBound: false,
        desiredMinTickCount: 8);

    return SizedBox(width: width, height: height,
        child: LineChart([dataSeries],
          defaultRenderer:
          LineRendererConfig(includeArea: true),
          animate: false,
          domainAxis: NumericAxisSpec(showAxisLine: true,
              tickProviderSpec: domainTickSpec),
          primaryMeasureAxis: yViewport != null ? NumericAxisSpec(showAxisLine: true,
              tickProviderSpec: measureTicSpec, viewport: yViewport) :
              NumericAxisSpec(showAxisLine: true, tickProviderSpec: measureTicSpec),
        ));
  }

  /// Computes y viewport with extra space around data at upper bound.
  ///
  /// Lower bound is set to be multiple of 100.  Upper bound is set to
  /// a multiple of 800 higher.
  NumericExtents _computeYViewport(List<Point> track) {

    var minElevation = track[0].y;

    var maxElevation = track[0].y;

    for (var point in track) {

      minElevation = min(minElevation, point.y);
      maxElevation = max(maxElevation, point.y);
    }

    var lowerBound = (minElevation.round() / 100) * 100.0;
    var upperBound = lowerBound + 800.0;
    while (upperBound <= maxElevation) {
      upperBound = upperBound + 800.0;
    }
    return NumericExtents(lowerBound, upperBound);
  }
}

class Point {
  double x;
  double y;
  Point(this.x, this.y);
}

var data = <Point>[Point(0.0, 1423.0),
  Point(0.25, 1439.0),
  Point(0.5, 1465.0),
  Point(0.75, 1490.0),
  Point(1.0, 1520.0),
  Point(1.25, 1565.0),
  Point(1.5, 1585.0),
  Point(2.0, 1591.0)];
yuyangkk commented 7 months ago

the same problem,Have you solved it?