Code Monkey home page Code Monkey logo

imanneo / fl_chart Goto Github PK

View Code? Open in Web Editor NEW
6.4K 55.0 1.7K 58.2 MB

FL Chart is a highly customizable Flutter chart library that supports Line Chart, Bar Chart, Pie Chart, Scatter Chart, and Radar Chart.

Home Page: https://flchart.dev

License: MIT License

Dart 96.79% Objective-C 0.01% Kotlin 0.01% Swift 0.09% HTML 0.18% Makefile 0.06% CMake 1.15% C 0.09% C++ 1.44% Shell 0.03% Ruby 0.16%
flutter-widget flutter chart charts fl-chart graph linechart barchart piechart datasets

fl_chart's Introduction

FL Chart Logo

pub package codecov Awesome Flutter GitHub Repo stars GitHub contributors GitHub closed issues GitHub Sponsors Buy Me A Coffee donate button

Our Financial Heroes

Your financial support acts as fuel for fl_chart's development. Support here.

Become a sponsor

Overview

FL Chart is a highly customizable Flutter chart library that supports Line Chart, Bar Chart, Pie Chart, Scatter Chart, and Radar Chart.

Chart Types

LineChart BarChart PieChart
Read More Read More Read More
ScatterChart RadarChart Coming Soon
Read More Read More

Banner designed by Soheil Saffar, and samples inspired from David Kovalev, Ricardo Salazar, Dmitro Petrenko, Ghani Pradita, MONUiXD. Thank you all!

Let's get started

First of all, you need to add the fl_chart in your project. In order to do that, follow this guide.

Then you need to read the docs. Start from here.

We suggest you to check samples source code.

- You can read about the animation handling here
Sample1 Sample2 Sample3

Donation

Your donation motivates me to work more on the fl_chart and resolve more issues. There are multiple ways to donate me:

  1. You can be my sponsor on GitHub (This is the most reliable way to donate me)
  2. You can buy me a coffee!
  3. Or if you are a fan of crypto, you can donate me Bitcoins here: 1L7ghKdcmgydmUJAnmYmMaiVjT1LoP4a45

Contributing

🍺 Pull requests are welcome!

Don't forget that open-source makes no sense without contributors. No matter how big your changes are, it helps us a lot even it is a line of change.

There might be a lot of grammar issues in the docs. It's a big help to us to fix them if you are fluent in English.

Check out CONTRIBUTING.md, which contains a guide for those who want to contribute to the FL Chart.

Reporting bugs and issues are contribution too, yes it is.

Below are the people who has contributed to the FL Chart. We hope we have your picture here soon.

fl_chart's People

Contributors

adamsocrat avatar arefhosseini avatar bytesizedwizard avatar dependabot[bot] avatar dhiyaaulauliyaa avatar hbdejesus avatar ica4c avatar imanneo avatar j4nk3e avatar jamesblasco avatar jlubeck avatar josh-ksr avatar joshmart avatar jrc2139 avatar julien4215 avatar k0psutin avatar krispypen avatar kzlakowski avatar liangxianzhe avatar lsaudon avatar motionz-von avatar payam-zahedi avatar prajwal27 avatar prajwal27wiijii avatar shamilovtim avatar shripal17 avatar tamasapps avatar tomwyr avatar triallax avatar uraskin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fl_chart's Issues

Subsampling data before displaying line

I need to display 6000 points (distance and altitude).
Do I need to make a subsampling of the data ?
If I do that, I will probably not be useful if you add support to zoom in / zoom out

Do you plan to manage subsampling in this lib or do I need to make this subsampling before displaying the points ?

minY value for LineChartData not respected

Take one of the samples and set the minY and maxY values to something, notice that the minY is always 0 no matter what you set. maxY seems to be respected, but not minY.

Exception when sink is passed to touchResponseSink

When I pass sink to the chart (touchResponseSink: controller.sink), the app throws following exception on touch event end (when I lift finger off the screen):

I/flutter (12415): ══║ EXCEPTION CAUGHT BY FOUNDATION LIBRARY β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
I/flutter (12415): The following assertion was thrown while dispatching notifications for FlTouchInputNotifier:
I/flutter (12415): 'package:flutter/src/rendering/object.dart': Failed assertion: line 1930 pos 12: 'owner == null ||
I/flutter (12415): !owner.debugDoingPaint': is not true.
I/flutter (12415): 
I/flutter (12415): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter (12415): more information in this error message to help you determine and fix the underlying cause.
I/flutter (12415): In either case, please report this assertion by filing a bug on GitHub:
I/flutter (12415):   https://github.com/flutter/flutter/issues/new?template=BUG.md
I/flutter (12415): 
I/flutter (12415): When the exception was thrown, this was the stack:
I/flutter (12415): #2      RenderObject.markNeedsPaint (package:flutter/src/rendering/object.dart:1930:12)
I/flutter (12415): #3      ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:206:21)
I/flutter (12415): #4      ValueNotifier.value= (package:flutter/src/foundation/change_notifier.dart:273:5)
I/flutter (12415): #5      BaseChartPainter.releaseIfEndTouch (package:fl_chart/src/chart/base/base_chart/base_chart_painter.dart:132:26)
I/flutter (12415): #6      LineChartPainter.paint (package:fl_chart/src/chart/line_chart/line_chart_painter.dart:104:7)
I/flutter (12415): #7      RenderCustomPaint._paintWithPainter (package:flutter/src/rendering/custom_paint.dart:528:13)
I/flutter (12415): #8      RenderCustomPaint.paint (package:flutter/src/rendering/custom_paint.dart:566:7)
I/flutter (12415): #9      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (12415): #10     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (12415): #11     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (12415): #12     RenderPointerListener.paint (package:flutter/src/rendering/proxy_box.dart:2669:11)
I/flutter (12415): #13     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (12415): #14     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (12415): #15     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (12415): #16     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (12415): #17     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (12415): #18     RenderShiftedBox.paint (package:flutter/src/rendering/shifted_box.dart:70:15)
I/flutter (12415): #19     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (12415): #20     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (12415): #21     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (12415): #22     RenderDecoratedBox.paint (package:flutter/src/rendering/proxy_box.dart:1953:11)
I/flutter (12415): #23     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (12415): #24     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (12415): #25     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (12415): #26     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (12415): #27     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (12415): #28     _RenderCustomMultiChildLayoutBox&RenderBox&ContainerRenderObjectMixin&RenderBoxContainerDefaultsMixin.defaultPaint (package:flutter/src/rendering/box.dart:2509:15)
I/flutter (12415): #29     RenderCustomMultiChildLayoutBox.paint (package:flutter/src/rendering/custom_layout.dart:361:5)
I/flutter (12415): #30     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (12415): #31     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (12415): #32     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (12415): #33     _RenderInkFeatures.paint (package:flutter/src/material/material.dart:510:11)
I/flutter (12415): #34     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (12415): #35     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (12415): #36     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (12415): #37     PaintingContext.pushLayer (package:flutter/src/rendering/object.dart:369:12)
I/flutter (12415): #38     RenderPhysicalModel.paint (package:flutter/src/rendering/proxy_box.dart:1724:15)
I/flutter (12415): #39     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (12415): #40     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (12415): #41     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (12415): #42     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (12415): #43     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (12415): #44     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (12415): #45     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (12415): #46     PaintingContext._repaintCompositedChild (package:flutter/src/rendering/object.dart:127:11)
I/flutter (12415): #47     PaintingContext.repaintCompositedChild (package:flutter/src/rendering/object.dart:95:5)
I/flutter (12415): #48     PipelineOwner.flushPaint (package:flutter/src/rendering/object.dart:858:29)
I/flutter (12415): #49     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:348:19)
I/flutter (12415): #50     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:701:13)
I/flutter (12415): #51     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:285:5)
I/flutter (12415): #52     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1016:15)
I/flutter (12415): #53     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:958:9)
I/flutter (12415): #54     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:874:5)
I/flutter (12415): #58     _invoke (dart:ui/hooks.dart:236:10)
I/flutter (12415): #59     _drawFrame (dart:ui/hooks.dart:194:3)
I/flutter (12415): (elided 5 frames from class _AssertionError and package dart:async)
I/flutter (12415): 
I/flutter (12415): The FlTouchInputNotifier sending notification was:
I/flutter (12415):   FlTouchInputNotifier#c0f42(Instance of 'NonTouch')
I/flutter (12415): ════════════════════════════════════════════════════════════════════════════════════════════════════

Sample:

import 'dart:async';

import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      title: "Chart",
      home: Scaffold(
        appBar: AppBar(title: Text("Chart"),),
        body: LineChartSample2(),
      ),
    )
  );
}


class LineChartSample2 extends StatefulWidget {

  @override
  _LineChartSample2State createState() => _LineChartSample2State();
}

class _LineChartSample2State extends State<LineChartSample2> {

  StreamController<LineTouchResponse> controller;

  @override
  void initState() {
    super.initState();
    controller = StreamController();
    controller.stream.distinct().listen((LineTouchResponse response){
      /// do whatever you want and change any property of the chart.
    });
  }

  @override
  void dispose() {
    controller.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AspectRatio(
      aspectRatio: 1,
      child: Container(
        decoration: BoxDecoration(
            color: Color(0xff232d37)
        ),
        child: Padding(
          padding: const EdgeInsets.only(right: 18.0, left: 12.0, top: 24, bottom: 12),
          child: FlChart(
            chart: LineChart(
              LineChartData(
                lineTouchData: LineTouchData(touchResponseSink: controller.sink),
                gridData: FlGridData(
                  show: true,
                  drawHorizontalGrid: true,
                  getDrawingVerticalGridLine: (value) {
                    return const FlLine(
                      color: Color(0xff37434d),
                      strokeWidth:  1,
                    );
                  },
                  getDrawingHorizontalGridLine: (value) {
                    return const FlLine(
                      color: Color(0xff37434d),
                      strokeWidth: 1,
                    );
                  },
                ),
                titlesData: FlTitlesData(
                  show: true,
                  bottomTitles: SideTitles(
                    showTitles: true,
                    reservedSize: 22,
                    textStyle: TextStyle(
                        color: const Color(0xff68737d),
                        fontWeight: FontWeight.bold,
                        fontSize: 16
                    ),
                    getTitles: (value) {
                      switch(value.toInt()) {
                        case 2: return 'MAR';
                        case 5: return 'JUN';
                        case 8: return 'SEP';
                      }

                      return '';
                    },
                    margin: 8,
                  ),
                  leftTitles: SideTitles(
                    showTitles: true,
                    textStyle: TextStyle(
                      color: const Color(0xff67727d),
                      fontWeight: FontWeight.bold,
                      fontSize: 15,
                    ),
                    getTitles: (value) {
                      switch(value.toInt()) {
                        case 1: return '10k';
                        case 3: return '30k';
                        case 5: return '50k';
                      }
                      return '';
                    },
                    reservedSize: 28,
                    margin: 12,
                  ),
                ),
                borderData: FlBorderData(
                    show: true,
                    border: Border.all(color: Color(0xff37434d), width: 1)
                ),
                minX: 0,
                maxX: 11,
                minY: 0,
                maxY: 6,
                lineBarsData: [
                  LineChartBarData(
                    spots: [
                      FlSpot(0, 3),
                      FlSpot(2.6, 2),
                      FlSpot(4.9, 5),
                      FlSpot(6.8, 3.1),
                      FlSpot(8, 4),
                      FlSpot(9.5, 3),
                      FlSpot(11, 4),
                    ],
                    isCurved: true,
                    barWidth: 5,
                    isStrokeCapRound: true,
                    dotData: FlDotData(show: false),
                    belowBarData: BelowBarData(show: false),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Recover API numbers and include in chart

Hello everyone,

I am needing in my application to perform the query on an API that returns numbers and transform into graphics.

Does any developer know how I can do this in a simple way?

Bug: Round Bars Rendering Invalid (when differences are too high?)

As seen in the screenshots below, when using rounded bars, and having the difference between the bars - we get this weird behavior.

When the Y values are something like 0,0,3,4 - everything is ok.
When the Y values are something like 0,0,30,1750 - the last bar is cut at the bottom.

(the longer one doesn't reach the real widget bottom or the shorter one overreaches. not sure.)

When turning off the rounded corners - the bars seem fine.

I tried debugging it for a bit but didn't really understand what's going on.
Let me know if there's anything else I can help you with.

Screenshot_20190711-003649
Screenshot_20190711-003700

Performance Issues with Tooltip

Charts are working fine and smoothly when spots are having smaller values.

Issues happens when spots are having larger integers, Try to show Tooltip with code below and it will hang the app.

Device: Samsung Galaxy S10+

Here's my rough code:

import 'dart:convert';

import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class ChartPage extends StatefulWidget {
  @override
  _ChartPageState createState() => _ChartPageState();
}

class _ChartPageState extends State<ChartPage> {
  var format = DateFormat("d MMM");
  int highPrice = 0;

  List<Color> gradientColors = [
    Color(0xffF3A183),
    Color(0xffEC6F66),
  ];

  @override
  Widget build(BuildContext context) {
    var rawResult =
        '{ "status": true, "title": "Apple iPhone X (64GB) - Silver:Amazon:Electronics", "store": "Amazon", "myData": "1555698600:74000,1555785000:74000,1555871400:74000,1555957800:74000,1556044200:74000,1556130600:74000,1556217000:74000,1556303400:74000,1556389800:74000,1556476200:74000,1556562600:74000,1556649000:73950,1556735400:73950,1556821800:69999,1556908200:69999,1556994600:69999,1557081000:69999,1557167400:69999,1557253800:73999,1557340200:73999,1557426600:73999,1557513000:73999,1557599400:73999,1557685800:73999,1557772200:73999,1557858600:73999,1557945000:91900,1558031400:91900,1558117800:73999,1558204200:73999,1558290600:69999,1558377000:69999,1558463400:69999,1558549800:69999,1558636200:69999,1558722600:69999,1558809000:69999,1558895400:66499,1558981800:66499,1559068200:66499,1559154600:66499,1559241000:66499,1559327400:66499,1559413800:73799,1559500200:69999,1559586600:69999,1559673000:69999,1559759400:69999,1559845800:69999,1559932200:69999,1560018600:69999,1560105000:68999,1560191400:68999,1560277800:68999,1560364200:68999,1560450600:68999,1560537000:69999,1560623400:69999,1560709800:66499,1560796200:66499,1560882600:66499,1560969000:66499,1561055400:66499,1561141800:69999,1561228200:69999,1561314600:66499,1561401000:66499,1561487400:66499,1561573800:66499,1561660200:66499,1561746600:66499,1561833000:66499,1561919400:66499,1562005800:66499,1562092200:66499,1562178600:68999,1562265000:68999,1562351400:68999,1562437800:68999,1562524200:68999", "avg_price": "70,699", "low_price": "66,499", "curr_price": "68,999", "productUrl": "https:\/\/www.amazon.in\/Apple-iPhone-Silver-64GB-Storage\/dp\/B0711T2L8K\/", "drop_chance": "26" }';
    var result = json.decode(rawResult);
    var priceDataRaw = result["myData"].split(",");
    double totalPrices = priceDataRaw.length.toDouble();
    List<String> dates = new List(priceDataRaw.length);
    List<FlSpot> prices = new List(priceDataRaw.length);
    for (var i = 0; i < priceDataRaw.length; i++) {
      var singleRawPrice = priceDataRaw[i];
      var priceArr = singleRawPrice.split(":");
      var date = new DateTime.fromMillisecondsSinceEpoch(
          int.parse(priceArr[0]) * 1000);
      var hoomanDate = format.format(date);
      dates[i] = hoomanDate;
      if (double.parse(priceArr[1]).floor() > highPrice) {
        highPrice = double.parse(priceArr[1]).floor();
      }

      prices[i] = FlSpot(double.parse(i.toString()), double.parse(priceArr[1]));
    }
    int priceSpaceTop = (highPrice / 5).floor();
    double maxPrice = (priceSpaceTop + highPrice).toDouble();

    return Scaffold(
      appBar: AppBar(
        title: Text(result["title"]),
      ),
      body: SingleChildScrollView(
        child: SizedBox(
          width: double.infinity,
          height: 200.0,
          child: Container(
            child: Padding(
              padding: const EdgeInsets.only(right: 10.0, left: 10.0, top: 24),
              child: FlChart(
                chart: LineChart(
                  LineChartData(
                      gridData: FlGridData(
                        show: false,
                        drawHorizontalGrid: false,
                        getDrawingVerticalGridLine: (value) {
                          return const FlLine(
                            color: Color(0xff37434d),
                            strokeWidth: 1,
                          );
                        },
                        getDrawingHorizontalGridLine: (value) {
                          return const FlLine(
                            color: Color(0xff37434d),
                            strokeWidth: 0,
                          );
                        },
                      ),
                      titlesData: FlTitlesData(
                        show: true,
                        horizontalTitlesTextStyle:
                            TextStyle(color: Color(0xff000000), fontSize: 8),
                        getHorizontalTitles: (value) {
                          return "";
                        },
                        verticalTitlesTextStyle: TextStyle(
                          color: Color(0xff000000),
                          fontSize: 8,
                        ),
                        getVerticalTitles: (value) {
                          return "";
                        },
                        verticalTitlesReservedWidth: 25,
                        verticalTitleMargin: 8,
                        horizontalTitleMargin: 8,
                      ),
                      borderData: FlBorderData(show: false),
                      minX: 0,
                      maxX: totalPrices,
                      minY: 0,
                      maxY: maxPrice,
                      lineBarsData: [
                        LineChartBarData(
                          spots: prices,
                          isCurved: true,
                          colors: gradientColors,
                          barWidth: 1.5,
                          isStrokeCapRound: false,
                          dotData: FlDotData(
                            show: false,
                            dotColor: Colors.black.withOpacity(0.2),
                          ),
                          belowBarData: BelowBarData(
                            show: true,
                            colors: gradientColors
                                .map((color) => color.withOpacity(0.3))
                                .toList(),
                          ),
                        ),
                      ],
                      lineTouchData: LineTouchData(
                          touchTooltipData: TouchTooltipData(
                        tooltipBgColor: Colors.white.withOpacity(0.8),
                      ))),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

JSON with Smaller values for testing (Works just fine and smooth):

{ "status": true, "title": "Destination Success: Discovering the Entrepreneurial Journey:Amazon:Kindle Store", "store": "Amazon", "myData": "1507633169:64.72,1510191470:64.72,1513258319:64.72,1514037780:64.72,1515516055:64.72,1516978145:64.72,1518226927:64.72,1519370596:64.72,1520566714:64.15,1527515383:67.33,1529294384:78.76,1534952637:81.69,1538572111:81.67,1550820561:73.93,1552158657:73.54,1552714165:73.54,1555313399:71.89,1555856888:71.89,1556240207:71.89,1556811021:71.89,1557485399:72.15,1558860933:72.42,1561360193:72.26,1562529376:71.13", "avg_price": "70", "low_price": "64", "curr_price": "71", "productUrl": "https:\/\/www.amazon.in\/Destination-Success-Discovering-Entrepreneurial-Journey-ebook\/dp\/B07499SX9S\/", "drop_chance": "42" }

Inverted y axis

Is it possible to add an invert axis feature, so you can have a y axis with an origin in the top left corner. This would also render the x axis + horizontal titles to the top.
I currently somehow achieved it by setting minY to the negative max value and multiply each value with -1. But the x axis and horizontal values are still on the bottom.

Performance Issue with getTitles with large range between flSpots.

Hello,

I am having a similar issue to that described in #54.

For example, the following:
FlSpot(1,-1000000) ,
FlSpot(1, 1000000)],
minY = -1000000,
leads to 1,000,000+ calls to the function that getTitles in the FlTitlesData() widget points too. This results in my app becoming completely non-responsive for a while until all these calls have completed.

Here's the code for my line chart:
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(
height: 18,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: MediaQuery.of(context).size.width * .95,
height: MediaQuery.of(context).size.height * .8,
child: FlChart(
chart: LineChart(
LineChartData(
lineTouchData: const LineTouchData(enabled: false),
lineBarsData: [
LineChartBarData(
spots: getSpots(),
isCurved: false,
barWidth: 8,
colors: [
Colors.indigo,
],
belowBarData: BelowBarData(
show: true,
colors: [Colors.deepPurple.withOpacity(0.2)],
),
dotData: FlDotData(
show: false,
),
),
],
minY: widget.minY,
titlesData: FlTitlesData(
bottomTitles: SideTitles(
showTitles: true,
textStyle: TextStyle(
fontSize: 10,
color: Colors.purple,
fontWeight: FontWeight.bold),
getTitles: (value) {
return value.toStringAsFixed(0);
}),
leftTitles: SideTitles(
showTitles: true,
getTitles: (value) {
return getLeftTitle(value); //This function gets called 1,000,000+ times
},
),
),
),
),
),
),
),
],
);

Map<double, String> leftTileValues = {};

String getLeftTitle(double value) {
return widget.leftTileValues[value]; //it doesn't seem to matter what I do here, this function is called 1,000,000+ times.
}

Here, the getLeftListTile(value) function gets called 1,000,000 + times.

Since my FlSpots are created dynamically, and minY and maxY values are determined at runtime, I am not using a switch to return the titles as you do in the examples provided. Instead, I created a Map<double,String> with 10 entries that are spaced evenly between the range of FlSpots. In other words (maxY - minY).

Is there a better way for me to dynamically create 10 titles evenly spaced between a large range of values over the Y axis (set an interval for Y axis titles) or is this a bug?

Issue if all data = 0

Hello, I have this issue if all data = 0

I/flutter ( 1389): Another exception was thrown: Offset argument contained a NaN value.
When I change one data more that 0 it's ok.

There is no visual bug, just error that I don't know if it important for google when I push the app on the playstore

version 0.0.8

Thank you for your work

Chart out of boundaries with custom minY

As you can see from the screenshots there is a problem when I set my minY value. If I set 0 everything works fine but if I set it programmatically it has strange behaviour.

In this example I would like to set the min to 4 or 3, based on the data I have

I have already tried to change the style and the position to the one that we can find on the examples but nothing changes. I had 0.1.2 and everything worked well: this error is only after the 0.1.4 update.

Screenshot_20190712-172336
Screenshot_20190712-172503

Error: The getter 'spot' was called on null

Getting the below error every time the charts are drawn.

I/flutter (18757): ══║ EXCEPTION CAUGHT BY RENDERING LIBRARY β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
I/flutter (18757): The following NoSuchMethodError was thrown during paint():
I/flutter (18757): The getter 'spot' was called on null.
I/flutter (18757): Receiver: null
I/flutter (18757): Tried calling: spot
I/flutter (18757): 
I/flutter (18757): When the exception was thrown, this was the stack:
I/flutter (18757): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
I/flutter (18757): #1      defaultTitlesStyle.<anonymous closure> (package:fl_chart/src/chart/base/axis_chart/axis_chart_data.dart:136:45)
I/flutter (18757): #2      MappedListIterable.elementAt (dart:_internal/iterable.dart:414:29)
I/flutter (18757): #3      ListIterable.toList (dart:_internal/iterable.dart:219:19)
I/flutter (18757): #4      defaultTitlesStyle (package:fl_chart/src/chart/base/axis_chart/axis_chart_data.dart:148:6)
I/flutter (18757): #5      AxisChartPainter.drawTouchTooltip (package:fl_chart/src/chart/base/axis_chart/axis_chart_painter.dart:128:56)
I/flutter (18757): #6      BarChartPainter.paint (package:fl_chart/src/chart/bar_chart/bar_chart_painter.dart:41:11)
I/flutter (18757): #7      RenderCustomPaint._paintWithPainter (package:flutter/src/rendering/custom_paint.dart:528:13)
I/flutter (18757): #8      RenderCustomPaint.paint (package:flutter/src/rendering/custom_paint.dart:566:7)
I/flutter (18757): #9      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #10     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (18757): #11     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (18757): #12     RenderPointerListener.paint (package:flutter/src/rendering/proxy_box.dart:2669:11)
I/flutter (18757): #13     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #14     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (18757): #15     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (18757): #16     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #17     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (18757): #18     _RenderFlex&RenderBox&ContainerRenderObjectMixin&RenderBoxContainerDefaultsMixin.defaultPaint (package:flutter/src/rendering/box.dart:2509:15)
I/flutter (18757): #19     RenderFlex.paint (package:flutter/src/rendering/flex.dart:947:7)
I/flutter (18757): #20     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #21     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (18757): #22     RenderShiftedBox.paint (package:flutter/src/rendering/shifted_box.dart:70:15)
I/flutter (18757): #23     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #24     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (18757): #25     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (18757): #26     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #27     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (18757): #28     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (18757): #29     _RenderInkFeatures.paint (package:flutter/src/material/material.dart:510:11)
I/flutter (18757): #30     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #31     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (18757): #32     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (18757): #33     RenderCustomPaint.paint (package:flutter/src/rendering/custom_paint.dart:569:11)
I/flutter (18757): #34     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #35     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (18757): #36     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (18757): #37     PaintingContext.pushLayer (package:flutter/src/rendering/object.dart:369:12)
I/flutter (18757): #38     RenderPhysicalShape.paint (package:flutter/src/rendering/proxy_box.dart:1818:15)
I/flutter (18757): #39     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #40     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (18757): #41     RenderShiftedBox.paint (package:flutter/src/rendering/shifted_box.dart:70:15)
I/flutter (18757): #42     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #43     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (18757): #44     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (18757): #45     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #46     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (18757): #47     _RenderFlex&RenderBox&ContainerRenderObjectMixin&RenderBoxContainerDefaultsMixin.defaultPaint (package:flutter/src/rendering/box.dart:2509:15)
I/flutter (18757): #48     RenderFlex.paint (package:flutter/src/rendering/flex.dart:947:7)
I/flutter (18757): #49     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #50     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (18757): #51     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (18757): #52     RenderDecoratedBox.paint (package:flutter/src/rendering/proxy_box.dart:1953:11)
I/flutter (18757): #53     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #54     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:172:13)
I/flutter (18757): #55     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:123:15)
I/flutter (18757): #56     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2089:7)
I/flutter (18757): #57     PaintingContext._repaintCompositedChild (package:flutter/src/rendering/object.dart:127:11)
I/flutter (18757): #58     PaintingContext.repaintCompositedChild (package:flutter/src/rendering/object.dart:95:5)
I/flutter (18757): #59     PipelineOwner.flushPaint (package:flutter/src/rendering/object.dart:858:29)
I/flutter (18757): #60     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:348:19)
I/flutter (18757): #61     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:701:13)
I/flutter (18757): #62     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:285:5)
I/flutter (18757): #63     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1016:15)
I/flutter (18757): #64     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:958:9)
I/flutter (18757): #65     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:874:5)
I/flutter (18757): #69     _invoke (dart:ui/hooks.dart:236:10)
I/flutter (18757): #70     _drawFrame (dart:ui/hooks.dart:194:3)
I/flutter (18757): (elided 3 frames from package dart:async)
I/flutter (18757): 
I/flutter (18757): The following RenderObject was being processed when the exception was fired: RenderCustomPaint#374c4:
I/flutter (18757):   creator: CustomPaint ← Listener ← _GestureSemantics ← RawGestureDetector ← GestureDetector ← FlChart
I/flutter (18757):     ← Expanded ← Column ← Padding ← Semantics ← DefaultTextStyle ← AnimatedDefaultTextStyle ← β‹―
I/flutter (18757):   parentData: <none> (can use size)
I/flutter (18757):   constraints: BoxConstraints(w=323.2, h=116.2)
I/flutter (18757):   size: Size(323.2, 116.2)
I/flutter (18757): This RenderObject has no descendants.

Also, below is the code which I am using to draw the chart.

FlChart(
  chart: BarChart(
    BarChartData(
      barGroups: barChartGroupsData,
      titlesData: FlTitlesData(
        bottomTitles: SideTitles(
          showTitles: false,
        ),
        leftTitles: SideTitles(
          margin: 0.0,
          showTitles: false,
          getTitles: (tileIndex) {
            return tileIndex.toInt().toString();
          }
        )
      ),
      alignment: BarChartAlignment.spaceEvenly,
      backgroundColor: AppColors.white,
      borderData: FlBorderData(
        show: false
      ),
      gridData: FlGridData(
        drawHorizontalGrid: true,
      ),
      barTouchData: BarTouchData(
        enabled: false,
        touchTooltipData: TouchTooltipData(),
        allowTouchBarBackDraw: false,
      )
    ),
  ),
),

Any idea as to why this might be occuring? Thanks in advance for your help.
Also, many thanks for creating this awesome package!

Adding RangeAnnotation

Hi
I would like to add Range Annotation, probably a line that shows a max or min threshold,

Show custom data on Tooltip from both axis

Hello, Can we pass custom data to Tooltip?
For example i want to show 5 Jul: β‚Ή200 on tooltip instead of 200.0
Like i also want to grab some data from horizontal axis to show date and also the price from vertical axis.

To achieve this i think i have to pass all of my hotizontal axis values and then onLongPress i have to get data from it.
If i add all of my Date data to horizontal axis, it gets overlapped.
Like this:
Demo
Can you please add option to set how many values developer wants to show on chart, so that remaining values remain hidden instead of overlapping? Same thing on vertical axis will be a PlusPlus.

Axis dimensions titles

Hi, thanks for this great package.
Would be good if you could add axis titles options (i.e: "power" on y and "date" on x axis)

file:///Users/mac/flutter_prj/fl_chart-master/lib/fl_chart.dart:60:56: Error: The getter 'localPosition' isn't defined for the class 'LongPressStartDetails'. - 'LongPressStartDetails' is from 'package:flutter/src/gestures/long_press.dart' ('file:///Users/mac/flutter/packages/flutter/lib/src/gestures/long_press.dart'). Try correcting the name to the name of an existing getter, or defining a getter or field named 'localPosition'. _touchInputNotifier.value = FlLongPressStart(d.localPosition); ^^^^^^^^^^^^^

θΏθ‘ŒδΈδΊ†,

Option to align title

today its hardcoded in "void drawTitles"
in this line
final TextPainter tp = TextPainter(text: span, textAlign: TextAlign.center, textDirection: TextDirection.ltr);

Try correcting the name to the name of an existing getter, or defining a getter or field named 'localPosition'.

image
image

return new FlChart( chart: new LineChart( LineChartData( lineTouchData: const LineTouchData(enabled: false), lineBarsData: [ LineChartBarData( spots: [ FlSpot(0, 1), FlSpot(1, 2), FlSpot(2, 1.5), FlSpot(3, 3), FlSpot(4, 3.5), ], barWidth: 2, isCurved: false, colors: [Colors.blue], belowBarData: BelowBarData( // εŒΊεŸŸι’œθ‰² show: true, colors: [Color.fromRGBO(3, 102, 214, 0.1)] ), dotData: FlDotData( // θ½¬ζŠ˜η‚Ή show: false, ), ) ], minY: 0, titlesData:FlTitlesData( leftTitles: const SideTitles(showTitles: true,), bottomTitles: SideTitles( showTitles: true, getTitles: (val) { switch (val.toInt()) { case 0: return '12:00:00'; break; case 1: return '12:00:05'; break; case 2: return '12:00:10'; break; case 3: return '12:00:15'; break; case 4: return '12:00:20'; break; } } ) ), gridData: FlGridData(show: true), borderData:FlBorderData( show: true, border: new Border.all(width: 1.0, color: Colors.grey[350]) ), ) ), );

Chart is not redrawn on data update

I am using a pie chart which gets data fed from a StreamProvider and whenever I receive the updated data the chart is not redrawn. I have tried debugging it and I can see that the updated values are set to the PieChartSectionData's, but the chart doesn't redraw itself automatically.

Codemagic build breaks when using FlChart

Tried to build my app on Codemagic, it breaks when I try to use this FlChart library. If i remove the chart widget, everything works fine.

== Building for Android ==

== /usr/local/bin/flutter build apk --debug ==
Initializing gradle...                                              2.8s
Resolving dependencies...                                          51.1s
Running Gradle task 'assembleDebug'...                          

Compiler message:

lib/src/components/charts/EmployeesChart.dart:93:25: Error: No named parameter with the name 'getVerticalTitles'.

                        getVerticalTitles: (value) {

                        ^^^^^^^^^^^^^^^^^

file:///Users/builder/programs/flutter/.pub-cache/hosted/pub.dartlang.org/fl_chart-0.1.4/lib/src/chart/base/base_chart/base_chart_data.dart:79:9: Context: Found this candidate, but the arguments don't match.

  const FlTitlesData({

        ^

Compiler failed on lib/main.dart

FAILURE: Build failed with an exception.

* Where:

Script '/Users/builder/programs/flutter/packages/flutter_tools/gradle/flutter.gradle' line: 665



* What went wrong:

Execution failed for task ':app:compileflutterBuildDebugArm'.
...

BUILD FAILED in 22s
Running Gradle task 'assembleDebug'...                             23.7s
Gradle task assembleDebug failed with exit code 1

Double Axis

Hey!

An important improvement for this component, in my opinion would be the possibility to have two axis, left and right of the chart. Also a scrolling option.

Great work!
Guilherme

Prevent line curvature overshooting

Thanks for this plugin. It's really fantastic and you're really killing it!

I love the curved lines, but they cause data confusion due to "overshooting" their data point. Changing curvature smoothness doesn't seem to fix this specific issue.

Flat:

image

Curved:

image

Becomes especially problematic if you see the actual data points:

image

Can we do something like this crummy Photoshop job?

image

Basically, keep curvature, but prevent overshooting?

issue when data Y =0

Hello i tried to add minY: 0.0, but I have always a screen freeze when a dataY passed to 0... I just use bar_chart_sample2.dart and change this like that makeGroupData(0, 0, 12),

Ability to show gaps in data?

Again, thanks for this plugin. You're doing an awesome job!

Is it possible to show gaps or null data? I've played around and haven't found how one might do that.

Visually, something along these lines:

image

Implementation wise, this might look like:

                    FlSpot(1, 2),
                    FlSpot(2, 3),
                    FlSpot(3, 3),
                    FlSpot(4, null),
                    FlSpot(5, null),
                    FlSpot(6, 2),
                    FlSpot(7, 4),

Thanks again!

Where can I set the touch popup's Text style?

Hey there,
I am trying to located where I go about settings the touch popup data's text style? Because I use go-flutter on desktop often times I have to manually provide the text style data for font and color otherwise nothing shows up. I was able to set it for this package for the bottom and left axis, but since I can't find it for the touch popup data it is always just blank.

Thanks,
-MH

How to turn off TouchTooltipData when touching a chart

How can I avoid the popup data to show when I touch the LineChart ? I tried putting the object touchTooltipData: in LineTouchData at null but then my state is not updated correctly to my other widgets.

Another related question: how can I let the chart listen to normalPress and not only longPress? Each time I try to interact with the chart I have to "longpress" it

Scrollable chart

I'd love to be able to have a chart where you can horizontally (or vertically) scroll to show more data. Probably to keep the interactability there would have to be a scrollbar you'd drag. I guess currently you could do something similar but the axis labels would disappear.

Whelp looks like this has already been said. Oops...

Custom zero line width

Is it possible to add a custom zero line width parameter to the FlGridData wich would render the zero line a bit more prominent.

I currently stack my chart and draw a thicker divider using positioned widget to simulate that. But it is not very handy for dynamic charts.

Edit: oh and, is there a built in way to set a custom background color for the chart? Currently i use the stack approach described above.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.