fl_echarts 0.1.0 copy "fl_echarts: ^0.1.0" to clipboard
fl_echarts: ^0.1.0 copied to clipboard

ECharts visualization library for Flutter, supporting Android, iOS, macOS, and Windows via an embedded WebView.

example/lib/main.dart

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:fl_echarts/fl_echarts.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'fl_echarts Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
        useMaterial3: true,
      ),
      home: const DemoPage(),
    );
  }
}

// ─── Demo page ───────────────────────────────────────────────────────────────

class DemoPage extends StatefulWidget {
  const DemoPage({super.key});

  @override
  State<DemoPage> createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage> {
  bool _darkMode = false;

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 4,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('fl_echarts Demo'),
          actions: [
            const Text('Dark'),
            Switch(
              value: _darkMode,
              onChanged: (v) => setState(() => _darkMode = v),
            ),
            const SizedBox(width: 8),
          ],
          bottom: const TabBar(
            tabs: [
              Tab(text: 'Bar'),
              Tab(text: 'Line'),
              Tab(text: 'Pie'),
              Tab(text: 'Live'),
            ],
          ),
        ),
        body: TabBarView(
          children: [
            _ChartTab(
              darkMode: _darkMode,
              title: 'Bar Chart — Monthly Sales',
              option: _barOption,
            ),
            _ChartTab(
              darkMode: _darkMode,
              title: 'Line Chart — Temperature',
              option: _lineOption,
            ),
            _ChartTab(
              darkMode: _darkMode,
              title: 'Pie Chart — Browser Usage',
              option: _pieOption,
            ),
            _LiveTab(darkMode: _darkMode),
          ],
        ),
      ),
    );
  }
}

// ─── Static chart tab ────────────────────────────────────────────────────────

class _ChartTab extends StatelessWidget {
  final bool darkMode;
  final String title;
  final Map<String, dynamic> option;

  const _ChartTab({
    required this.darkMode,
    required this.title,
    required this.option,
  });

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(title,
              style: Theme.of(context)
                  .textTheme
                  .titleMedium
                  ?.copyWith(fontWeight: FontWeight.bold)),
          const SizedBox(height: 12),
          ECharts(
            height: 320,
            darkMode: darkMode,
            option: option,
            onChartReady: () => debugPrint('$title ready'),
          ),
        ],
      ),
    );
  }
}

// ─── Live update tab ─────────────────────────────────────────────────────────

class _LiveTab extends StatefulWidget {
  final bool darkMode;
  const _LiveTab({required this.darkMode});

  @override
  State<_LiveTab> createState() => _LiveTabState();
}

class _LiveTabState extends State<_LiveTab> {
  final _controller = EChartsController();
  final _rng = Random();
  bool _ready = false;
  bool _loading = false;

  Map<String, dynamic> get _randomOption => {
        'title': {'text': 'Random Data', 'left': 'center'},
        'tooltip': {},
        'xAxis': {
          'type': 'category',
          'data': ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
        },
        'yAxis': {'type': 'value'},
        'series': [
          {
            'type': 'bar',
            'data': List.generate(7, (_) => _rng.nextInt(200) + 20),
            'itemStyle': {
              'color': {
                'type': 'linear',
                'x': 0,
                'y': 0,
                'x2': 0,
                'y2': 1,
                'colorStops': [
                  {'offset': 0, 'color': '#6366f1'},
                  {'offset': 1, 'color': '#a5b4fc'},
                ],
              },
            },
          },
        ],
      };

  Map<String, dynamic> _currentOption = {};

  @override
  void initState() {
    super.initState();
    _currentOption = _randomOption;
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  Future<void> _refresh() async {
    setState(() => _loading = true);
    _controller.showLoading(text: 'Refreshing…');
    await Future.delayed(const Duration(milliseconds: 600));
    final next = _randomOption;
    await _controller.updateChart(next);
    _controller.hideLoading();
    setState(() {
      _currentOption = next;
      _loading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('Live Updates via EChartsController',
              style: Theme.of(context)
                  .textTheme
                  .titleMedium
                  ?.copyWith(fontWeight: FontWeight.bold)),
          const SizedBox(height: 12),
          ECharts(
            height: 320,
            darkMode: widget.darkMode,
            option: _currentOption,
            controller: _controller,
            onChartReady: () => setState(() => _ready = true),
          ),
          const SizedBox(height: 16),
          Row(
            children: [
              FilledButton.icon(
                onPressed: _ready && !_loading ? _refresh : null,
                icon: const Icon(Icons.refresh),
                label: const Text('Randomize Data'),
              ),
              const SizedBox(width: 12),
              FilledButton.tonal(
                onPressed: _ready
                    ? () => _controller.executeJavaScript('echart.clear();')
                    : null,
                child: const Text('Clear'),
              ),
            ],
          ),
          const SizedBox(height: 12),
          Text(
            _ready ? '✓ Chart is ready' : '⏳ Waiting for chart…',
            style: TextStyle(
              color: _ready ? Colors.green : Colors.orange,
              fontSize: 13,
            ),
          ),
        ],
      ),
    );
  }
}

// ─── Chart options ────────────────────────────────────────────────────────────

final _barOption = {
  'tooltip': {'trigger': 'axis'},
  'legend': {
    'data': ['2023', '2024']
  },
  'xAxis': {
    'type': 'category',
    'data': [
      'Jan',
      'Feb',
      'Mar',
      'Apr',
      'May',
      'Jun',
      'Jul',
      'Aug',
      'Sep',
      'Oct',
      'Nov',
      'Dec'
    ],
  },
  'yAxis': {'type': 'value'},
  'series': [
    {
      'name': '2023',
      'type': 'bar',
      'data': [32, 51, 41, 64, 75, 82, 91, 87, 73, 68, 54, 45],
    },
    {
      'name': '2024',
      'type': 'bar',
      'data': [42, 58, 55, 70, 88, 95, 101, 96, 85, 78, 65, 60],
    },
  ],
};

final _lineOption = {
  'tooltip': {'trigger': 'axis'},
  'legend': {
    'data': ['Min', 'Max']
  },
  'xAxis': {
    'type': 'category',
    'data': [
      'Jan',
      'Feb',
      'Mar',
      'Apr',
      'May',
      'Jun',
      'Jul',
      'Aug',
      'Sep',
      'Oct',
      'Nov',
      'Dec'
    ],
  },
  'yAxis': {'type': 'value', 'name': '°C'},
  'series': [
    {
      'name': 'Min',
      'type': 'line',
      'smooth': true,
      'data': [-2, 0, 4, 9, 14, 18, 20, 19, 15, 10, 5, 1],
      'areaStyle': {'opacity': 0.2},
    },
    {
      'name': 'Max',
      'type': 'line',
      'smooth': true,
      'data': [6, 9, 14, 19, 25, 30, 33, 32, 27, 21, 13, 8],
      'areaStyle': {'opacity': 0.2},
    },
  ],
};

final _pieOption = {
  'tooltip': {'trigger': 'item'},
  'legend': {'orient': 'vertical', 'left': 'left'},
  'series': [
    {
      'name': 'Browser',
      'type': 'pie',
      'radius': ['40%', '70%'],
      'avoidLabelOverlap': false,
      'label': {'show': false},
      'emphasis': {
        'label': {'show': true, 'fontSize': 18, 'fontWeight': 'bold'},
      },
      'data': [
        {'value': 63, 'name': 'Chrome'},
        {'value': 18, 'name': 'Safari'},
        {'value': 6, 'name': 'Edge'},
        {'value': 4, 'name': 'Firefox'},
        {'value': 9, 'name': 'Other'},
      ],
    },
  ],
};
0
likes
0
points
165
downloads

Publisher

unverified uploader

Weekly Downloads

ECharts visualization library for Flutter, supporting Android, iOS, macOS, and Windows via an embedded WebView.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, webview_flutter, webview_windows

More

Packages that depend on fl_echarts