Data visualization is a common but important part of application development. A good visualization library always makes it easier to build data visualization charts. But unfortunately, there is not yet a perfect visualization library in the Flutter community. The current candidates all have some unsatisfactoriness, such as:
To build complex visualization charts, we developed flutter_echarts, Witch imports Echarts (A powerful Web visualization library) into Flutter Apps by Webview. It did help to satisfy some complex demands, but Webview has some weaknesses in performance and compatibility. For fluency and stability, we still need a native Flutter data visualization library.
In recent years, data visualization in front-end development has progressed a lot. The Grammar of Graphics theory has been applied to web visualization libraries. this theory is proposed by Leland Wilkinson in the book The Grammar of Graphics. It tries to describe grammar rules for all statistic graphics.
Thanks to this theory, the visualization library will no longer be limited to the traditional charts categories like line/bar/pie.
Data visualization is abstracted to a combination of geometry marks, coordinates, and scales, which highly increased flexibility and extensibility. Frontend visualization libraries based on Grammar of Graphics are vega, AntV of Alipay, and chart-part of Microsoft.
So, there comes Graphic: a Flutter data visualization library based on Grammar of Graphics.
A basic example of Graphic:
graphic.Chart(
data: [
{ 'genre': 'Sports', 'sold': 275 },
{ 'genre': 'Strategy', 'sold': 115 },
{ 'genre': 'Action', 'sold': 120 },
{ 'genre': 'Shooter', 'sold': 350 },
{ 'genre': 'Other', 'sold': 150 },
],
scales: {
'genre': graphic.CatScale(
accessor: (map) => map['genre'] as String,
),
'sold': graphic.NumScale(
accessor: (map) => map['sold'] as num,
nice: true,
)
},
geoms: [graphic.IntervalGeom(
position: graphic.PositionAttr(field: 'genre*sold'),
shape: graphic.ShapeAttr(values: [
graphic.Shapes.rrectInterval(radius: Radius.circular(5))
]),
)],
axes: {
'genre': graphic.Defaults.horizontalAxis,
'sold': graphic.Defaults.verticalAxis,
},
)
More examples please see in this Example App :
Grammar of Graphics
Data visualization can be roughly summarized to: Mapping data to visual channel attribute (color, shape, size, position...) values by a certain rule, and then render shapes with these attributes.
In Grammar of Graphics, this progress can be concrete to:
In Graphic, the design of APIs and class names are mainly refered to AntV. The core concepts are:
These concepts are familiar for those who has already known about Grammar of Graphics. If you have never met them, please refer to the book. We think that Grammar of Graphics is an important part of data visualization, so whether you will use related libraries or not, it worth learning.
Declarative Chart
Most visualization libraries in Web is imperative, and plot charts by calling a series of functions. AntV is not an exception. But in Flutter, declarative and reactive views are advocated. The constructor of view is configured by the tree returned in build function. It's worth mentioning that this is also an important deference between Web Canvas and Flutter CustomPaint Widget.
So Graphic APIs is designed declarative. All information is configured by props of graphic. Chart Widget. The chart will rerender when the widget tree updates. By the way, we will optimize the rerender performance in the future.
Why there can be all kinds of various charts? The key is the diversity of shape attribute. So it is the most complex one in all visual channel attributes. The customizability of shape attribute determines the extensibility of visualization libraries.
In Graphic, the shape attribute is defined to functions or high order functions. It receives values of visual channel attributes of geometry marks, and returns the composed render shapes for the render engine. Users can custom their own shape functions:
List<graphic.RenderShape> triangleInterval(
List<graphic.AttrValueRecord> attrValueRecords,
graphic.CoordComponent coord,
Offset origin,
) {
// Implementation of attrValueRecords => renderShapes
}
Graphic has now mainly finished static charts. We will add features such as interactions, animations, and components like tooltip, legend in the future.
The features and APIs may be unstable for now. So you are welcome for trial, but be cautious to use it in production environment.
In this article we introduced a Flutter data visualization library based on Grammar of Graphics: Graphic
Previously published behind a paywall: https://medium.com/@entronad/graphic-a-flutter-data-visualization-library-base-on-grammar-of-graphics-75ca751f5cae