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
- https://github.com/chartjs/Chart.js/issues/882
- https://github.com/chartjs/Chart.js/issues/2210#issuecomment-211290157
- https://github.com/chartjs/Chart.js/issues/2127
- https://github.com/chartjs/Chart.js/issues/2181
- https://github.com/chartjs/Chart.js/issues/2527
- https://github.com/chartjs/Chart.js/issues/2958
- https://github.com/chartjs/Chart.js/issues/3105
- https://github.com/chartjs/Chart.js/issues/3170
- https://github.com/chartjs/Chart.js/issues/3180
Related issues
Milestones
- 2.5.0: acquire/release from a root item
- 2.6.0: new animation frame management
- 2.7.0: new event management