Chart.js platform abstraction (proposal)

Chart.js is currently moderately bound to the DOM API (node, attributes, style, events, etc.) but should only require a context2d instance implementing the W3C Canvas 2D Context API standard and a strict (and potentially restricted) JavaScript environment. In that conditions, the library should make no assumption on the targeting platform/language and thus should be able to run on none DOM environments. On way to achieve that goal would be to introduce a new core.platform class implementing platform specific features.

Context acquisition

core.platform implementations must provide a compatible context2d instance from a (platform specific) root item. It should also maintain the context2d rendering size coherent with the associated item size without altering in any way the root item state.

Event management

Since events are platform specific, Chart.js should abstract them:

  • core.event (object)
    • type
      • mouseenter (includes touchstart)
      • mousemove (includes touchmove)
      • mouseout (includes touchend)
      • click (includes touchend)
      • resize
    • native (the native event)
    • height (the canvas height)
    • width (the canvas width)
    • x (relative to the canvas)
    • y (relative to the canvas)

Note: currently, native events are passed to the onClick handlers. Since this handler can be used in plugins, it should now accepts the Chart.js abstracted event. If the user wants to implement behaviors based on the native event, it should use: event.native.

The responsive config (deprecation)

This config should be deprecated for the following reasons:

  • the library should not alter the user given root item state
  • responsiveness of a DOM element is the user responsibility (js/css)
  • context2d rasterization size should be maintained by the platform implementation

In case a users don't want a rasterization size equal to the item size, a new adaptative platform config can be introduced, in which case, platforms can skip resizing management:

config: {
    platform: {
        adaptative: true/false
    }
}

Interface (Chart.platform [static])

  • acquireContext(root, options) -> context2d
  • releaseContext(context) -> boolean
  • repaintContext(context)
  • requestAnimationFrame(context, root) -> boolean
  • cancelAnimationFrame(context, root) -> boolean
  • addEventListener(item, type, listener)
  • removeEventListener(item, type, listener)

Default implementation

Chart.js should be shipped with the DOM platform implementation which can initially live in the core.platform.js file.

DOM container (the new way)

Starting 2.4.x, we should provide a way to instantiate a Chart using a DOM container (i.e. accepting children) allowing full control on injected DOM elements (e.g. the hidden iframe used as resize event detector). The current implementation injects this iframe as a sibling of the canvas, meaning that the library doesn't control the state of the container, which in some cases, doesn't play well with this method (e.g. if the container is absolutely positioned). Also, since the canvas bellows to the user assets, we should not alter its style (width, height, etc.).

Rasterizing size management would be done via an hidden iframe (or object), or directly using the onresize event on compatible brwoser (e.g. IE).

Note: investigate the use of a DOM object instead of an "iframe", it might be lighter and faster.

For example:

    <div id="chart"></div>
    [...]
    var chart = new Chart(document.getElementById("chart"), { ... });

core.platform.acquireCanvas() would generate the following elements and start monitoring the iframe to maintain the canvas rasterization size.

    <div id="chart">
      <div style="position: relative; .... make it fill its parent ...">
        <canvas style="position: relative; .... make it fill its parent ...">
        <iframe style="position: absolute; .... make it fill its parent ...">
      </div>
    </div>

Examples:

  • Static chart with natural size, width: 256px, height: width * aspect ratio:

    // old: { config: { responsive: false } }
    <canvas id="chart" width="256px"></canvas>
    // new: no config
    <div id="chart"></div>
    
  • Static chart, fixed width, height: width * aspect ratio:

    // old: { config: { responsive: false } }
    <canvas id="chart" width="320"></canvas>
    // new: no config
    <div id="chart" style="width: 320px"></div>
    

    Note: currently confusing because doesn't work if the canvas size is set by style!

  • Responsive chart, height: width * aspect ratio

    // old: { config: { responsive: true, maintainAspectRatio: true } }
    <div style="width: 25%"><canvas id="chart"></canvas></div>
    // new: no config
    <div id="chart" style="width: 25%"></div>
    
  • Responsive chart, fixed height, doesn't maintain aspect ratio

    // old: { config: { responsive: true, maintainAspectRatio: false } }
    <div style="width: 25%, height: 128px"><canvas id="chart"></canvas></div>
    // new: no config
    <div id="chart" style="width: 25%; height: 128px"></div>
    
  • Fully responsive chart, doesn't maintain aspect ratio

    // old: { config: { responsive: true, maintainAspectRatio: false } }
    <div style="width: 25vh, height: 25vh"><canvas id="chart"></canvas></div>
    // new: no config
    <div id="chart" style="width: 25vw; height: 25vh">
    

DOM canvas

deprecated in 2.4.x / removal in 3.x The library should not inject elements outside the root item, so the rasterizing size management should not rely on an iframe. If a user choose that method, a deprecation message will be displayed with a link to that document (or documentation). For example:

It appears you passed a canvas element directly to chartjs, this is
being deprecated in favor of using a standard container element. See
http://link_to_the_doc_explaining_why_and_benefits for details.

context2d

deprecated in 2.4.x / removal in 3.x Fallback to DOM canvas (context2d.canvas)

Other changes

  • helpers.retinaScale should be implementation by platforms (removed from helpers)
  • removals in 3.x: (move to platform from 2.4.x)
    • helpers.getRelativePosition
    • helpers.isConstrainedValue
    • helpers.getConstraintDimension
    • helpers.getConstraintWidth
    • helpers.getConstraintHeight
    • helpers.getMaximumWidth
    • helpers.getMaximumHeight
    • helpers.getStyle
    • helpers.parseMaxStyle

Platform implementations

  • DOM (default)
  • Node.js
  • QML (Qt)
  • etc.

Might fix the following issues

Milestones

  • 2.5.0: acquire/release from a root item
  • 2.6.0: new animation frame management
  • 2.7.0: new event management

results matching ""

    No results matching ""