Skip to content

[WIP] render, renderTo, RenderController, and RenderPolicy docs

Xiaohan Zhang edited this page Jan 19, 2017 · 4 revisions

Anatomy of a Plottable Render

Rendering a Component has several phases:

  1. Anchoring, in which a Component is associated with a particular SVG element in the DOM. A Component must first be anchored before it renders. Anchoring modifies the DOM element by attaching styles and children.
  2. Layout, in which a Component computes its own width/height and prepares other internal state for rendering at the given width/height. Plottable Components are built to be rendered on a variety of widths and heights.
  3. Add to global render queue, in which a Component adds itself (and any children needing redraw) to Plottable's RenderController.
  4. Render, in which Components that have been added to the queue draw elements to the DOM.

So, to render a Plottable Component, the set of steps might look like:

const component = ...

// step 1
component.anchor(document.getElementById("mySvg"));

// step 2
component.computeLayout();

// step 3. Calling .render() will schedule the RenderController
// to perform step 4 in a requestAnimationFrame.
component.render();

// alternatively, you may force step 4 which will use the previously
// set layout and anchor. Watch out - this method is a no-op for Table
// and Group.
component.renderImmediately();

To simplify this, we added the .renderTo() method:

const component = ...

// all four steps at once. 
component.renderTo(document.getElementById("mySvg"));

You should rarely need to call .computeLayout(), .render(), or .renderImmediately() on your own; these are automatically handled by Plottable.

You may call Component.detach() and then Component.anchor(newElement) to manually uproot and re-anchor a Component from one part of the DOM to another - this can help re-use charts for better perf.

asynchronous .render() vs. synchronous .renderTo()

An important takeaway is that .render() only schedules the component to be asynchronously rendered in the next animation frame. This allows batching multiple property changes together without causing intermediate renders:

// here we change multiple properties across multiple components.
// all of these changes will be rendered once asynchronously.
xAxis.formatter(newFormatter).innerTickLength(newTickLength);
yAxis.domain([0, 25]);

You don't have to call .render() manually; changes to component properties will automatically call .render().

In contrast to .render(), .renderTo() will immediately cause the Component to draw to the DOM. This is to allow DOM manipulation of Plottable's drawn components.

RenderController

Plottable's RenderController (accessible at Plottable.RenderController) is a singleton object responsible for scheduling and flushing Components to be rendered. You usually shouldn't need to touch this as the above described behavior covers the majority of cases. But for advanced cases, you can use the methods in RenderController to have more control. In particular you can set the RenderPolicy, which defines whether .render() is synchronous or asynchronous. By default we use Plottable.RenderController.Policy.ANIMATION_FRAME, but you can change this:

Plottable.RenderController.renderPolicy(
    Plottable.RenderController.Policy.IMMEDIATE
)

This will cause all .render() calls to commit to the DOM immediately. This is not recommended and can cause significant perf problems, but it is useful for debugging.