skills/syncfusion-flutter-circular-charts/references/accessibility-and-export.md

229 lines
6.0 KiB
Markdown

# Accessibility and Export
## Table of Contents
- [Accessibility](#accessibility)
- [RTL Support](#rtl-support)
- [Export as PNG Image](#export-as-png-image)
- [Export as PDF](#export-as-pdf)
---
## Accessibility
`SfCircularChart` is built with accessibility in mind and supports:
### Sufficient Contrast
Customize colors for all chart elements to meet WCAG contrast requirements:
- Chart title text color via `ChartTitle.textStyle`
- Series palette via `SfCircularChart.palette`
- Per-point colors via `pointColorMapper`
- Data label text via `DataLabelSettings.textStyle`
- Legend text via `Legend.textStyle`
- Tooltip background via `TooltipBehavior.color`
- Selected segment color via `SelectionBehavior.selectedColor`
### Large Fonts
All text elements scale automatically with the device's `MediaQueryData.textScaler` (system font size). You can also explicitly set font sizes on:
- `ChartTitle.textStyle.fontSize`
- `DataLabelSettings.textStyle.fontSize`
- `Legend.textStyle.fontSize`
- `TooltipBehavior` text
### Tappable Targets
The chart provides callback support to respond to user taps on key elements:
- **Data points** — `onPointTap` callback on `SfCircularChart`
- **Data labels** — `onDataLabelTapped` callback on `SfCircularChart`
- **Legend items** — `onLegendTapped` callback on `SfCircularChart`
Example:
```dart
SfCircularChart(
onPointTap: (ChartPointDetails details) {
print('Tapped point index: ${details.pointIndex}');
print('Series index: ${details.seriesIndex}');
},
series: <CircularSeries>[...],
)
```
---
## RTL Support
Wrap the chart in a `Directionality` widget to enable right-to-left layout:
```dart
Directionality(
textDirection: TextDirection.rtl,
child: SfCircularChart(
series: <CircularSeries>[
PieSeries<ChartData, String>(
dataSource: chartData,
xValueMapper: (d, _) => d.x,
yValueMapper: (d, _) => d.y,
),
],
),
)
```
---
## Export as PNG Image
Use a `GlobalKey<SfCircularChartState>` to capture the chart as a PNG image:
```dart
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
class ExportChartPage extends StatefulWidget {
@override
_ExportChartPageState createState() => _ExportChartPageState();
}
class _ExportChartPageState extends State<ExportChartPage> {
final GlobalKey<SfCircularChartState> _chartKey = GlobalKey();
final List<ChartData> _data = [
ChartData('Jan', 35),
ChartData('Feb', 28),
ChartData('Mar', 34),
];
Future<void> _exportImage() async {
final ui.Image? image = await _chartKey.currentState!.toImage(pixelRatio: 3.0);
final ByteData? bytes = await image!.toByteData(
format: ui.ImageByteFormat.png,
);
final Uint8List imageBytes = bytes!.buffer.asUint8List(
bytes.offsetInBytes,
bytes.lengthInBytes,
);
await Navigator.push(
context,
MaterialPageRoute(
builder: (_) => Scaffold(body: Image.memory(imageBytes)),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
SfCircularChart(
key: _chartKey,
series: <CircularSeries>[
PieSeries<ChartData, String>(
dataSource: _data,
xValueMapper: (d, _) => d.x,
yValueMapper: (d, _) => d.y,
),
],
),
ElevatedButton(
onPressed: _exportImage,
child: const Text('Export as PNG'),
),
],
),
);
}
}
class ChartData {
ChartData(this.x, this.y);
final String x;
final double y;
}
```
> `pixelRatio: 3.0` produces a high-resolution image. Adjust as needed.
---
## Export as PDF
Requires additional packages. Run the following to add them (always resolves latest compatible versions):
```bash
flutter pub add syncfusion_flutter_pdf path_provider open_file
```
```dart
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:path_provider/path_provider.dart';
import 'package:open_file/open_file.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:syncfusion_flutter_pdf/pdf.dart';
class _ExportPageState extends State<ExportChartToPdf> {
final GlobalKey<SfCircularChartState> _chartKey = GlobalKey();
Future<void> _exportPDF() async {
final ui.Image image = await _chartKey.currentState!.toImage(pixelRatio: 3.0);
final ByteData? byteData = await image.toByteData(
format: ui.ImageByteFormat.png,
);
final List<int> imageBytes = byteData!.buffer.asUint8List(
byteData.offsetInBytes,
byteData.lengthInBytes,
);
final PdfBitmap bitmap = PdfBitmap(imageBytes);
final PdfDocument document = PdfDocument();
document.pageSettings.size = Size(
bitmap.width.toDouble(),
bitmap.height.toDouble(),
);
final PdfPage page = document.pages.add();
final Size pageSize = page.getClientSize();
page.graphics.drawImage(
bitmap,
Rect.fromLTWH(0, 0, pageSize.width, pageSize.height),
);
final List<int> pdfBytes = document.saveSync();
document.dispose();
final Directory dir = await getApplicationSupportDirectory();
final File file = File('${dir.path}/chart_export.pdf');
await file.writeAsBytes(pdfBytes, flush: true);
OpenFile.open(file.path);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SfCircularChart(
key: _chartKey,
series: <CircularSeries>[
PieSeries<ChartData, String>(
dataSource: chartData,
xValueMapper: (d, _) => d.x,
yValueMapper: (d, _) => d.y,
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: _exportPDF,
child: const Icon(Icons.picture_as_pdf),
),
);
}
}
```
> The pattern is the same for both PNG and PDF: capture via `toImage`, convert to bytes, then use those bytes however you need (display, save, share, embed in PDF).