Skip to content

Coming from Plotly ​

Holochart reads the same figure as plotly.js: data, layout, config and frames, with Plotly's attribute names, hovertemplate syntax and templates. Its functional API has Plotly's function names and argument order. For most charts, moving over is a change of import and of a few lines around the chart; this page lists those lines.

Attribute names are Plotly's, letter for letter (showticklabels, paper_bgcolor), and Holochart has no camelCase spellings of them. What Holochart adds is named in camelCase (styleRules, sharedRenderer), except its 3D material and lighting attributes; see Attribute names.

It describes plotly.js 4. The compatibility table has the attribute by attribute detail.

The same chart, side by side ​

js
import Plotly from 'plotly.js-dist-min';

const gd = document.getElementById('chart');

await Plotly.newPlot(
  gd,
  [{ type: 'scatter', mode: 'lines+markers', x: [1, 2, 3], y: [2, 1, 3] }],
  { title: { text: 'Hello' } },
  { responsive: true },
);

gd.on('plotly_click', (event) => console.log(event.points[0].x));

await Plotly.restyle(gd, { 'marker.color': 'crimson' }, [0]);
await Plotly.relayout(gd, { 'xaxis.range': [0, 4] });
Plotly.purge(gd);
ts
import * as Holochart from '@mk7s/holochart';

const el = document.getElementById('chart')!;

const chart = await Holochart.newPlot(
  el,
  [{ type: 'scatter', mode: 'lines+markers', x: [1, 2, 3], y: [2, 1, 3] }],
  { title: { text: 'Hello' } },
  { responsive: true },
);

chart.on('plotly_click', (event) => console.log(event.points[0]?.x));

await Holochart.restyle(el, { 'marker.color': 'crimson' }, [0]);
await Holochart.relayout(el, { 'xaxis.range': [0, 4] });
Holochart.purge(el);

With a script tag, window.Holochart takes the place of window.Plotly; see Installation.

Three things changed:

  • The element is an element. Plotly also accepts the element's id as a string. Holochart takes the HTMLElement only.
  • The promise resolves to a chart. newPlot and the other functions resolve to a Chart object, not to the element. Nothing is attached to the element: there is no gd.data, gd.layout or gd.on. Use the chart, which getChart(el) returns at any time.
  • Events are on the chart. chart.on('plotly_click', …) replaces gd.on('plotly_click', …).

Functions ​

These work as in Plotly, with the element as the first argument:

newPlot, react, restyle, relayout, update, addTraces, deleteTraces, moveTraces, extendTraces, prependTraces, addFrames, deleteFrames, animate, purge, toImage, downloadImage, Fx.hover and Fx.unhover.

plotly.jsHolochart
Plotly.newPlot('chart', data)newPlot(document.getElementById('chart'), data)
gd.data, gd.layoutchart.data, chart.layout
gd._fullData, gd._fullLayoutchart.fullData, chart.fullLayout
gd.on('plotly_click', fn)chart.on('plotly_click', fn) or chart.on('click', fn)
gd.removeAllListeners('plotly_click')chart.off('click')
Plotly.Plots.resize(gd)chart.resize()
Plotly.toImage(gd, { format: 'svg' })Not available: PNG, JPEG and WebP only

Every function also exists as a method of the chart (chart.restyle(…), chart.react(figure), chart.toImage(…)), and createChart(el, figure) creates a chart without the promise. The rest of these docs use that form; both are the same chart. See Core concepts.

Events ​

Every Holochart event answers to its Plotly name: plotly_click, plotly_hover, plotly_relayout, plotly_selected, plotly_legendclick, plotly_sunburstclick and the rest subscribe to click, hover, relayout and so on. The payloads have Plotly's fields (points[] with curveNumber, pointNumber, x, y, customdata, data, fullData). The event reference lists them all.

Differences:

  • unhover carries an empty points list. Plotly sends the points that were hovered.
  • Plotly emits these and Holochart does not: plotly_autosize (listen to resize), plotly_react, plotly_update, plotly_beforeexport, plotly_afterexport, plotly_exportfail and plotly_framework.
  • Holochart adds resize, destroy, webglcontextrestored, beforerender and afterrender.
  • A click listener that returns false cancels a sunburst, treemap or icicle drill-down, as the sunburstclick listener does.

What to change in the figure ​

  • scattergl and scatterpolargl: rename them to scatter and scatterpolar. Every Holochart trace is drawn on the GPU, so there is no separate WebGL trace type. A trace with an unknown type is hidden, with a warning in the console that names the nearest type.
  • Date objects: Holochart shows a Date at its UTC time; Plotly shows it at the browser's local time. Date strings without a UTC offset are read the same way in both, without a time zone; Holochart converts a string with an offset (Z, +01:00) to UTC. If your data are Date objects and you want local times on the axis, pass date strings instead.
  • Fonts: text is drawn from font files, not from the fonts installed on the computer. A font.family that isn't registered is drawn with the built-in font. See Web fonts.

An attribute or value that Holochart doesn't have is ignored with a console warning, and the chart still draws. Set config.strict: true while migrating to turn those warnings into errors.

Maps ​

scattergeo, choropleth and layout.geo work as in Plotly, with every projection, but the full bundle does not include them: maps are a package of their own, so that pages without a map do not download map code. Add one import next to the bundle's (or register tracesGeo in a partial bundle):

ts
import * as Holochart from '@mk7s/holochart';
import '@mk7s/holochart/geo';

Without it a map trace is hidden, and the console warning names this import. Two more things differ from Plotly:

  • The base map is bundled (Natural Earth) and nothing is fetched: config.topojsonURL is empty by default, where Plotly's default is its CDN. Coastlines and borders therefore differ slightly from Plotly's, and maps work offline.
  • geo.fitbounds defaults to 'locations', as in plotly.js 4: the view is fitted to the data unless the figure sets the view or fitbounds: false.

Maps lists the rest, and the chart pages of scattergeo and choropleth what differs per trace.

What is missing ​

Not available in Holochart:

  • Tile maps: scattermap, choroplethmap, densitymap and the layout.map subplot. Projected maps are available: see Maps above.
  • Ternary, Smith and carpet plots: scatterternary, scattersmith, carpet, scattercarpet, contourcarpet.
  • quiver traces.
  • Vector export: toImage makes PNG, JPEG and WebP images, not SVG.
  • LaTeX ($…$) in text, and non-Gregorian calendars (xcalendar, layout.calendar).
  • Element ids as the first argument, and data on the element (gd.data).

The compatibility table lists every trace type, attribute, layout key and config option, and the known deviations where Holochart draws or behaves differently on purpose.

Default look ​

Holochart has its own default look, so a plotly.js figure without layout.template renders differently: dark (#0a0a0f) instead of white, 9 px Helvetica Neue text instead of 12 px Open Sans, tighter margins, a horizontal legend above the plot instead of a vertical one on the right, thinner lines, smaller markers, and bright-on-dark automatic colorscales. The colorway has 8 colors instead of category10's 10, so trace colors differ from the third trace on. Values your figure sets explicitly are kept.

To match plotly.js, use the plotly-classic template, either for every chart or per figure:

ts
import { setDefaultTemplate } from '@mk7s/holochart'; // or '@mk7s/holochart-runtime'

setDefaultTemplate('plotly-classic'); // once, before creating charts

// or per figure
createChart(el, { data, layout: { ...layout, template: 'plotly-classic' } });

plotly-classic renders the same as template: 'none' or null: Plotly's own defaults. Your figure JSON is unaffected either way: chartToJSON exports the figure you gave, not the template. A figure that names a template ('plotly_white', …) gets that template instead of the default, as in Plotly. See The default look for its values.

Saved figures ​

A figure saved from Plotly as JSON loads as it is. fromJSON(el, json) creates the chart, and decodes the base64 typed arrays ({ dtype, bdata }) that plotly.py writes:

ts
import { fromJSON } from '@mk7s/holochart';

const chart = fromJSON(el, await (await fetch('/figures/sales.json')).text());
await chart.ready;

What Holochart adds ​

Plotly ignores these, so a figure that uses them still loads there, without them:

Released under the MIT License.