Graphic Documentation

repository·main·Indexed 23 days ago

https://github.com/entronad/graphic

A declarative data visualization library for Flutter based on the grammar of graphics. It allows users to compose complex charts through data processing and mark shapes, supporting advanced interactivity, animations, and high-density data performance. The library features a decoupled architecture separating the Engine, Component, and Renderer, and provides a flexible system for defining Geoms, Scales, and Attributes.

Tokens
49.6K
Snippets
100
Records
256
Agent score
83%

What's inside Graphic

  1. Overview of Graphic

    main

    Graphic is a Flutter charting library based on a grammar of data visualization derived from Leland Wilkinson's The Grammar of Graphics. It allows for flexible, declarative specifications where data processing steps and mark shapes can be composed freely.

    Key features include:

    • Flexible declarative grammar: Compose data processing and mark shapes without being limited to specific chart types. Custom shape draw methods are supported.
    • Interaction: High interactivity via event and selection definitions, enabling features like item highlighting, tooltips, and coordinate scaling.
    • Animation: Supports mark transition animations during chart construction or updates, including various entrance animation forms.
  2. Identify customization entry points in Graphic

    main

    Graphic allows customization across several layers of the visualization. Use the following mapping to determine how to implement specific changes:

    What to CustomizeHowKey Classes
    Chart geometryCreate custom ShapeExtend IntervalShape, LineShape, AreaShape, PointShape, or PolygonShape
    Visual encodingCustom encoder functionsColorEncode(encoder: ...), SizeEncode(encoder: ...), etc.
    TooltipsCustom tooltip rendererTooltipGuide(renderer: ...)
    AnnotationsCustom annotation rendererCustomAnnotation(renderer: ...)
    Data processingCustom transformsMapTrans(mapper: ...), Filter(predicate: ...)
    Collision handlingCustom modifierExtend Modifier
  3. Differentiate between Transform and Statistics (Stat)

    main

    In the Graphic pipeline, data processing is split into two main concepts located between the raw data and the geometric marks:

    1. Transform (trans): Does not change the number of data rows or their order. It creates additional mapping-based one-dimensional variables (e.g., calculating a new field based on existing ones).
    2. Statistics (stat): Can sort, filter, augment, or bin data. It can change the number of rows (e.g., creating bins) and generate multi-dimensional data. Statistics are positioned after the scale and before the geom in the pipeline.

    Key Rule: Certain geometries like polygon or edge must be associated with a stat (such as bin).

  4. Compare Cross and Nest faceting

    main

    Both cross and nest are used for faceting (creating 'frames of frames'), but they serve different semantic purposes:

    • Cross: Represents different aspects of the same dimension. For the same dimension, cross-facets are considered identical in context.
    • Nest: Represents different meanings for different categories. It is used when a categorical variable divides the graph into distinct sub-groups (e.g., nesting by 'gender' and 'marital status').

    Note: nest is applied to categorical variables and inherently partitions the graph, whereas cross is an aspect of a frame.

  5. Use Varset Algebra operators

    main

    Graphic uses algebraic operators to map variables to visual dimensions. The order and type of operator determine how data is positioned.

    Cross (*) — Assign to different dimensions

    Maps variables to different position dimensions (e.g., x and y). The first variable maps to the first dimension, the second to the second. Varset('date') * Varset('value') results in date $\rightarrow$ x-axis and value $\rightarrow$ y-axis.

    Blend (+) — Combine on same dimension

    Combines multiple variables on the same dimension. This is used for range-based marks like candlesticks. Varset('open') + Varset('close') maps both variables to the same dimension.

    Nest (/) — Group by variable

    Groups data by a variable's values to create separate series. Nesting does not create a new dimension; it creates groups within existing dimensions and is always applied last in the expression. Varset('date') * Varset('value') / Varset('series') results in date $\rightarrow$ x, value $\rightarrow$ y, grouped by series.

    // Cross
    Varset('date') * Varset('value')
    
    // Blend
    Varset('open') + Varset('close')
    
    // Nest
    Varset('date') * Varset('value') / Varset('series')
  6. Understand the Dataflow Lifecycle and Rebuild Rules

    main

    The project uses a directed acyclic graph (DAG) for dataflow. The lifecycle is triggered by three main events:

    1. Spec Change (Initialization): Rebuild the entire dataflow.
    2. Data Change: Recalculate the main link starting from the data source.
    3. Signal Change: Recalculate downstream components starting from the signal.

    Key Data Characteristics:

    • Data is treated as both param and value within the DAG.
    • Data flows through four stages: original $\rightarrow$ scaled $\rightarrow$ raw aes $\rightarrow$ aes.
    • Every data update is a full update, with stages linked by index.
  7. How DataSets and Variables work

    main

    Data is managed through DataSet classes. A DataSet contains variables and transforms.

    • Namespace: All DataSets share a single namespace for variables.
    • Transforms: When a transform generates a variable, adding the as keyword creates a new variable; omitting as performs the operation on the existing variable.
    • Scales: Generated variables are automatically configured with scales. For example, a Proportion variable automatically defaults to a scale of 0-1.
    • Data Sources: In the specification, data sources are referred to using the keys source or from (inspired by G2 and ECharts).
  8. Component Lifecycle: Props and State

    main

    The project adopts a React-like model for managing component data and updates:

    • Props: Immutable configuration passed during construction or via setters. They serve as the input for the component.
    • State: Mutable, internal data that is persisted and used for rendering. State is derived from or updated by Props.
      • Standard for State: Must be externally settable/accessible, persistent, and not purely derivable from other states.
    • Updates: To trigger a re-render, use setState or specific add methods.
    • Destruction: Components use a remove mechanism to detach from parent elements and clear references to props to prevent memory leaks.
  9. Understand the Tuple and Data Representation

    main

    Data within the system is encapsulated in Tuples.

    • Construction: Use the ingest method (acting as the constructor) to create Tuples.
    • Data Types: Fields within a Tuple are restricted to num, String, and DateTime.
    • Immutability/Transformation: The system uses a functional approach. Instead of direct field modification, transformations are handled via operators.
    • Generics: It is assumed that all Tuples within a single dataflow share a consistent generic type D.
  10. Understand the Hierarchy: Element, Shape, and Container

    main

    The library organizes visual components in a hierarchical structure:

    1. Element: The base unit. It has no context other than the canvas. The destroy method resets its cfg to null.
    2. Shape (extends Element): A visual primitive.
      • type is represented as a String for extensibility.
      • Custom shapes can be defined by passing a path.
      • Shapes may require additional state like isClip or endState.
    3. Text (extends Shape): Supports both rich text (using textSpan) and plain text (using text and textStyle). Rich text takes precedence.
    4. Container (extends Element): A grouping mechanism.
      • addShape adds a shape for use.
      • setClip includes protection against null configurations.
    5. Renderer (extends Container): The component responsible for the actual rendering process, distinct from the underlying canvas.
  11. Handle Null and Invalid Values in Data

    main

    The library provides specific rules for handling null and invalid (e.g., NaN) values to ensure visual stability:

    • Positioning: null values in position attributes are treated as NaN (since Offset cannot be null). In adjust operations, null is treated as being at the origin.
    • Attribute Handling: For non-position attributes, null values are generally treated as 0.
    • Geom Behavior:
      • In line and area geoms, null values trigger a 'break' (discontinuity) in the line.
      • For other geoms, the specific element is simply not drawn.
    • Scales: If a scale input is null, the scale returns null.
    • Invalid Fixes: The system uses an invalidFix enumeration to manage how null and isFinit (NaN) cases are resolved during the adjust and shape phases.
  12. Understand the Data Visualization Grammar pipeline

    main

    The project follows a 'Grammar of Data Visualization' approach. Data flows through a specific pipeline of stages to be transformed into visual figures. Understanding this sequence is key to customizing how data is mapped to aesthetics:

    Data $\rightarrow$ Tuples $\rightarrow$ Scaled Tuples $\rightarrow$ Aesthetic Attributes $\rightarrow$ Figures

    1. Variable: The raw input data.
    2. Scale: Transforming data values into a coordinate or visual space.
    3. Aesthetic: Mapping scaled values to visual properties (e.g., color, size, shape).
    4. Group: Organizing data into logical sets (using nester and cross operations).