Skip to content

Latest commit

 

History

History
288 lines (272 loc) · 11.7 KB

DEVELOPER-GUIDE.md

File metadata and controls

288 lines (272 loc) · 11.7 KB

Taucharts Developer Guide

Welcome to the Taucharts Developer Guide.

This guide will walk you through Taucharts-specific terms and show you how the library works to give you an idea on how to improve it.

Many terms and ideas are covered in The Grammar of Graphics book by Leland Wilkinson.

What happens when you create a chart instance?

const chart = new Taucharts.Chart({
    type: 'line',
    x: 'Date',
    y: 'Effort',
    data: [...],
    guide: { x: { tickPeriod: 'month' } },
    settings: { asyncRendering: true }
});
  • Simple chart config is auto-transformed into a more complex specification, containing information about detected dimensions' types and hierarchical structure of elements (though it can be specified manually).
  • Then GPL config is created (Graphics Programming Language). It contains information about data sources and scales configurations.
  • Plugins are initialized. Each plugin can add content into chart layout, subscribe to chart events and modify the configuration at different steps of processing, register new Grammar Elements etc.
  • Same steps are run after calling chart.updateConfig( config ).
        .--------------.
        |    CONFIG    |
        |--------------|
        | {            |
        |   type,      |
        |   x, y,      |
        |   data,      |
        |   guide,     |
        |   settings,  |
        |   ...        |
        | }            |
        '-------|------'
                |
                |__________
                           |
                           |
.==========================|========================================.
|                          |                   src/charts/tau.chart |
|  new Taucharts.Chart( config )                                    |
:                 |                                                 :
.                 |___________  - - - subscribe to window 'resize'  .
                              |
                              |___________
                                          |
                                          |
    DataProcessor.autoDetectDimTypes( spec.data )
      DataProcessor.autoAssignScales( dimensions )
                              |
                              |
  chartTypesRegistry.get( spec.type )
                              |__________ ChartArea     src/api/...
                              |__________ ChartLine
                              |__________ ...
                              |
            transformConfig( config )
                              |
                  .-----------|------------------.
                  |            SPEC              |
                  |------------------------------|
                  | config.spec = {              |
                  |   dimensions,                |
                  |   unit: {                    |
                  |     type: 'COORDS.RECT',     |
                  |     x: [...],                |
                  |     y: [...],                |
                  |     unit: [ { x, y, ... } ], |
                  |     ...                      |
                  |   }                          |
                  | }                            |
                  '-----------|------------------'
                              |
                              |____________
                                           |
                                           |
 .=========================================|==========================.
 |                                         |      src/charts/tau.plot |
 |  new Taucharts.Plot( { spec, x, y, data, guide, settings, ... } )  |
 :                  |                                                 :
 .                  |_____________________                            .
                                          |
                                          |
                    Plot.setupSettings( config )
                  this.createGPLConfig( config )
                                          |
                                          | - - - this.setupPlugins()
                                          |
                  .=======================|=================.
                  |                       |          src/spec-converter
                  |  new SpecConverter( config ).convert()  |
                  :                                 |       :
                  .                  _______________|       .
                                    |
                      .-------------|---------------------.
                      |            GPL CONFIG             |
                      |-----------------------------------|
                      | {                                 |
                      |   sources: {                      |
                      |     '?': { dims: {}, data: [] },  |
                      |     '/': { dims: {}, data: [] }   |
                      |   },                              |
                      |   scales: {                       |
                      |     x_null: { type, source: '?' },|
                      |     y_null: { type, source: '?' },|
                      |     ...                           |
                      |   }                               |
                      | }                                 |
                      '-----------------------------------'

Let's render the chart

chart.renderTo(domElement);
  • Chart layout is inserted into DOM element. Chart size is determined by container's size (if not specified).
  • Live Spec (detailed GPL config) is created from GPL config by using Spec Transformers. Default transformers are ApplyRatio (removes empty values from facets and resizes facets proportionally) and AutoLayout (configures layout parameters depending on chart size).
  • Units structure gets unfolded, data is passed from parents to their children and processed by applying expressions (filters etc.).
  • Another Spec Transformers are applied: ExtractAxes removes repeated X and Y axes from facets, CalcSize calculates required chart size and hides ticks or labels when there is not enough space. There are some strategies for calculating required size and optimizing a chart, the most common are normal (default one, displays scrollbars when optimal chart size is too large to prevent large density of facets, categorical ticks, bars etc.) and entire-view (fits the whole chart into specified size without displaying scrollbars).
  • Task Runner is initialized. It runs tasks asynchronously by small synchronous chunks to prevent browser from freeze.
  • Tasks for creating draw scenario are scheduled. Grammar Elements are created, their screen models (mapping from data row to coordinates, colors etc.) are initialized and modified by Grammar Rules, that are toggled by guides.
  • Tasks for rendering DOM nodes are scheduled. The draw method of each Grammar Element is called and chart DOM nodes are created or updated one by one.
  • Task runner executes scheduled tasks.
  • Same steps are repeated when chart.refresh() or chart.updateConfig( config ) is called. The best practice is to reuse existing DOM nodes and slightly animate their transition.
  .=========================================================.
  | Plot                               src/charts/tau.plot  |
  |                 this.disablePointerEvents()             |
  :                 this._insertLayout()                    :
  .                 this._createLiveSpec()                  .
                            |
                     .------|-----.
                     | GPL CONFIG |
                     |------------|
                     | {          |
                     |   sources, |
                     |   scales,  |
                     | }          |
                     '------|-----'
                            |___________
                                        |
            SpecTransformApplyRatio( liveSpec )
            SpecTransformAutoLayout( liveSpec )
                            |
                            | - - - - `specready`
                      .-----|-----.
                      | LIVE SPEC |
                      |-----------|
                      | {         |
                      |   sources,|
                      |   scales, |
                      | }         |
                      '-----|-----'
                            |
                            |__________
                                       |
                                       |
                   this._createGPL( liveSpec )
                            |
            .===============|===================.
            |               |        src/charts/tau.gpl
            |   new GPL( liveSpec )             |
            :       .unfoldStructure()          :
            .              |                    .
                           |
                     .-----|-----.
                     | LIVE SPEC |
                     | (expanded)|
                     |-----------|
                     | {         |
                     |   sources,|
                     |   scales, |
                     | }         |
                     '-----|-----'
                           |
                           |_____________
                                         |
                                         |
            SpecTransformExtractAxes( liveSpec )
             SpecTransformCalcSize( liveSpec )
                           |
                           | - - - - `unitsstructureexpanded`
                     .-----|-----.
                     | LIVE SPEC |
                     |  (final)  |
                     |-----------|
                     | {         |
                     |   sources,|
                     |   scales, |
                     | }         |
                     '-----|-----'
                           |
                           |___________
                                       |
                                       |
        this._scheduleDrawScenario( liveSpec ) - - - (async via TaskRunner)
                           |
                           |
               gpl.getDrawScenarioQueue()
                           |
                           |
                 .---------|--------.
                 | GRAMMAR ELEMENTS |
                 |------------------|
                 | [                |
                 |   {screenModel}, |
                 |   {screenModel}  |
                 |   ...            |
                 | ]                |
                 '---------|--------'
                           |
                           |
              this._scheduleDrawing() - - - (async via TaskRunner)
                           |
                           | - - - `beforerender`
                           |
                    grammarElement.draw() - - - `unitdraw`
                    grammarElement.draw() - - - `unitdraw`
                          ...
                           |
                           | - - - `render`

                TaskRunner.run()
                            |
                       _____|
                      |
                      |
            |              __
         20 |     __/\  __/
            |  __/    \/
          0 |__________________
              Jan   May   Sep

Publishing the library

  • Assign a version number using Semantic Versioning rules. If API or some features are not stable, use -beta.0 prefix.
  • Run npm test, ensure that all tests have passed successfully.
  • Run npm run build.
  • Publish a beta version by executing npm publish --tag beta.
  • Publish a stable version by executing npm publish.

Misc

  • Use Squash Commits when merging a Pull Request to keep the repository history clean for being able to highlight the release notes.