Search code examples
fluttersyncfusion-chart

Chart not being rendered in Flutter


I have a flutter project where I am using Syncfusion to render the JSON data into charts. I don't get any error when I debug my code but the chart is not rendering when the build is complete. I am not sure if there are mistakes in the codes but it worked fine for other charts.

In addition, some of the reasons I feel responsible for the chart not being rendered could be:

  1. There is too much data to plot. (This may not be the problem since I also tried after reducing data)
  2. The values to plot are too small since they mostly range from some negative values to some positive values and also the values are in decimal (eg 0.7, -0.6, and so on).

These are just my assumption on what could have gone wrong. Please correct me if I am mistaken.

Any ideas to resolve or at least help me understand what is wrong would be great. And yes please help me out :)). Below is the code that I have.

   import 'package:flutter/material.dart';
   import 'package:fyp/model/rainApiCall.dart';
   import 'package:syncfusion_flutter_charts/charts.dart';

   class Past extends StatefulWidget{
     @override
       _Past createState() => _Past();
   }

   class _Past extends State<Past>{

   List<String> t = [];
   List<String> ampA = [];
   List<String> ampB = [];
   List<String> ampC = [];

   @override
     void initState() {
      fetchEQData();
      super.initState();
   }

   @override
     Widget build(BuildContext context) {
      return Container(
        child: Center(
          child: FutureBuilder(
            future: fetchEQData(),
            builder: (context, snapshot){
              if(snapshot.hasData) {
              var stationID = '4853';

              for(int i=0; i<snapshot.data.length; i++){
                if(snapshot.data[i].stationId==stationID){
                  t.add(snapshot.data[i].recordLength);
                  ampA.add(snapshot.data[i].amplitudemaxa);
                  ampB.add(snapshot.data[i].amplitudemaxb);
                  ampC.add(snapshot.data[i].amplitudemaxc);
                }
              }
          return Card(
            child: SfCartesianChart(
              series: <ChartSeries>[
                StackedLineSeries<EqAmpData, double>(
                  dataSource: getColumnData(t, ampA, ampB, ampC),
                  dashArray: <double>[5,5],
                  xValueMapper: (EqAmpData eqdata, _) => double.parse(eqdata.x),
                  yValueMapper: (EqAmpData eqdata, _) => int.parse(eqdata.y1),
                ),
                StackedLineSeries<EqAmpData, double>(
                  dataSource: getColumnData(t, ampA, ampB, ampC),
                  dashArray: <double>[5,5],
                  xValueMapper: (EqAmpData eqdata, _) => double.parse(eqdata.x),
                  yValueMapper: (EqAmpData eqdata, _) => int.parse(eqdata.y2),
                ),
                StackedLineSeries<EqAmpData, double>(
                  dataSource: getColumnData(t, ampA, ampB, ampC),
                  dashArray: <double>[5,5],
                  xValueMapper: (EqAmpData eqdata, _) => double.parse(eqdata.x),
                  yValueMapper: (EqAmpData eqdata, _) => int.parse(eqdata.y3),
                ),
              ]
            )
          );
        }
        return CircularProgressIndicator();
      },
    ),),);}}


   class EqAmpData{
     String x;
     String y1;
     String y2;
     String y3;
     EqAmpData(this.x, this.y1, this.y2, this.y3);
   }

   dynamic getColumnData(List xval, List yval1, List yval2, List yval3) {
     List rtime = xval;
     List y1 = yval1;
     List y2 = yval2;
     List y3 = yval3;

     List<EqAmpData> columnData = <EqAmpData>[];
       for (int i = 0; i < rtime.length; i++) {
         columnData.add(EqAmpData(rtime[i], y1[i], y2[i], y3[i]));
       }
     return columnData;
   }

Screen after build: enter image description here

Screenshot of the data I have: enter image description here


Solution

  • When you define your StackedLineSeries, your yValueMapper should provide double instead of int:

    StackedLineSeries<EqAmpData, double>(
      dataSource: getColumnData(t, ampA, ampB, ampC),
      dashArray: <double>[5, 5],
      xValueMapper: (EqAmpData eqdata, _) => double.parse(eqdata.x),
      yValueMapper: (EqAmpData eqdata, _) => double.parse(eqdata.y1),
    ),
    

    enter image description here

    Full source code for easy copy-paste

    import 'dart:math' as math;
    
    import 'package:flutter/material.dart';
    import 'package:syncfusion_flutter_charts/charts.dart';
    
    void main() {
      runApp(
        MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Charts Demo',
          home: Past(),
        ),
      );
    }
    
    class Past extends StatefulWidget {
      @override
      _Past createState() => _Past();
    }
    
    class _Past extends State<Past> {
      List<String> t = [];
      List<String> ampA = [];
      List<String> ampB = [];
      List<String> ampC = [];
    
      @override
      void initState() {
        fetchEQData();
        super.initState();
      }
    
      Future<List<RawData>> fetchEQData() async {
        await Future.delayed(Duration(seconds: 2));
        return data;
      }
    
      StackedLineSeries<EqAmpData, double> prepareSerie({
        List<EqAmpData> dataSource,
        num Function(EqAmpData, int) yValueMapper,
      }) {
        return StackedLineSeries<EqAmpData, double>(
          dataSource: dataSource,
          dashArray: <double>[5, 5],
          xValueMapper: (EqAmpData eqdata, _) => double.parse(eqdata.x),
          yValueMapper: yValueMapper,
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Center(
            child: FutureBuilder<List<RawData>>(
              future: fetchEQData(),
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  snapshot.data
                      .where((item) => item.stationId == '4853')
                      .forEach((item) {
                    t.add(item.recordLength);
                    ampA.add(item.amplitudemaxa);
                    ampB.add(item.amplitudemaxb);
                    ampC.add(item.amplitudemaxc);
                  });
    
                  final dataSource = getColumnData(t, ampA, ampB, ampC);
    
                  return Card(
                    child: SfCartesianChart(
                      series: <ChartSeries>[
                        prepareSerie(
                          dataSource: dataSource,
                          yValueMapper: (eqdata, _) => double.parse(eqdata.y1),
                        ),
                        prepareSerie(
                          dataSource: dataSource,
                          yValueMapper: (eqdata, _) => double.parse(eqdata.y2),
                        ),
                        prepareSerie(
                          dataSource: dataSource,
                          yValueMapper: (eqdata, _) => double.parse(eqdata.y3),
                        ),
                      ],
                    ),
                  );
                }
                return CircularProgressIndicator();
              },
            ),
          ),
        );
      }
    }
    
    // DOMAIN
    
    class EqAmpData {
      final String x;
      final String y1;
      final String y2;
      final String y3;
      EqAmpData(this.x, this.y1, this.y2, this.y3);
    }
    
    dynamic getColumnData(List rtime, List y1, List y2, List y3) {
      return List.generate(
        rtime.length,
        (i) => EqAmpData(rtime[i], y1[i], y2[i], y3[i]),
      );
    }
    
    class RawData {
      final String stationId;
      final String recordLength;
      final String amplitudemaxa;
      final String amplitudemaxb;
      final String amplitudemaxc;
    
      RawData(
        this.stationId,
        this.recordLength,
        this.amplitudemaxa,
        this.amplitudemaxb,
        this.amplitudemaxc,
      );
    }
    
    // DATA
    
    final random = math.Random();
    final data = List.generate(
      100,
      (index) => RawData(
        "4853",
        (index * 0.01).toString(),
        ((random.nextInt(100) - 50) / 500).toString(),
        ((random.nextInt(100) - 50) / 1000).toString(),
        ((random.nextInt(100) - 50) / 1000).toString(),
      ),
    );