Wondering what’s next for npm?Check out our public roadmap! »

    @sis-cc/dotstatsuite-d3-charts

    6.5.2 • Public • Published

    rcw-charts

    oecd test lint

    Set of configurable charts based on d3.

    Setup

    npm install rcw-charts
    

    Usage

    import { BarChart } from 'rcw-charts';
    
    const chart = new BarChart(el, options, data);
    chart.update(el, otherOptions, otherData);
    chart.destroy(el);

    Available charts

    • bar
    • row
    • scatter
    • line
    • vertical symbol
    • horizontal symbol
    • timeline

    API (out of the box usage)

    methods

    constructor(el, options, data)

    Setup DOM elements and call update.

    update(el, options, data)

    Draw the chart using the lifecycle of d3 (join, enter, update, exit).

    destroy(el)

    Destroy all d3 related elements (selections, events) from el including el.

    props

    el

    any valid DOM element (JSDOM elements are valid, React's virtual DOM elements are not)

    const el = document.getElementById('root');

    options

    const axisOptions = {
      step: 1,
      format: { proc: null, pattern: '.0f', isTime: false },
      color: 'black',
      thickness: 1
    };
    
    const options = {
      base: {
        width: 920,
        height: 455,
        margin: 0,
      },
      axis: {
        x: axisOptions,
        y: {
          ...axisOptions,
          step: 2
        }
      }
    };
    name default type/domain description
    base - {} base options
    base.width 920 <Integer> width of the chart
    base.height 455 <Integer> height of the chart
    base.margin 0 <Integer> margins (top, right, bottom, left) of the chart (#1)
    base.isAnnotated false <Boolean> serie annotations
    base.padding {top: 0, right: 0, bottom: 0, left: 0} {} padding around base
    base.innerPadding {top: 0, right: 0, bottom: 0, left: 0} {} padding around series
    axis - {} axis options
    axis.{x|y} - {} x or y axis options
    axis.{x|y}.color black CSS color of the axis (line only)
    axis.{x|y}.thickness 1 <Integer> thickness of the axis (line only)
    axis.{x|y}.orient left `[top right
    axis.{y\}.padding 0 <Integer> padding of the axis (#4)
    axis.{x|y}.tick - {} tick options
    axis.{x|y}.tick.size 6 <Integer> length (width for y, height for x) of a tick
    axis.{x|y}.tick.minorSize 0 <Integer> length (width for y, height for x) of a minor tick
    axis.{x|y}.tick.color black CSS color of a tick
    axis.{x|y}.tick.thickness 1 <Integer> thickness of a tick
    axis.{x|y}.tick.minorThickness 1 <Integer> thickness of a minor tick
    axis.{x|y}.font - - font options
    axis.{x|y}.font.family sans-serif CSS font family
    axis.{x|y}.font.size 10 <Integer> font size
    axis.{x|y}.font.color black CSS font color
    axis.{x|y}.font.weight normal CSS font weight
    axis.{x|y}.font.rotation -45 <Integer> font rotation (#3)
    axis.{x|y}.format - - format options
    axis.{x|y}.format.proc null <function> proc to manually compute a format (#2)
    axis.{x|y}.format.pattern .0f D3 pattern injected in d3.format
    axis.{x|y}.format.isTime false <Boolean> use d3.time.format
    axis.{x|y}.format.maxWidth null <Integer> value to set a maximum to the width of the text (in pixels)
    axis.{x|y}.ordinal.gap .3 [0 -> 1] ratio for band gap
    axis.{x|y}.ordinal.padding .3 [0 -> 1] space ratio around bands
    axis.{x|y}.ordinal.minDisplaySize 300 <Integer> minimal number of pixels required to display the axis (width for horizontal, height for vertical)
    axis.{x|y}.linear.min 0 <Integer> min value (#7)
    axis.{x|y}.linear.minDisplaySize 100 <Integer> minimal number of pixels required to display the axis (width for horizontal, height for vertical)
    axis.{x|y}.linear.minTickSizeFactor 2 <Integer> minimal ratio of a tick label offset (width for horizontal, height for vertical) for step size
    axis.{x|y}.linear.minTickSizeFactor 5 <Integer> maximal ratio of a tick label offset (width for horizontal, height for vertical) for step size
    axis.{x|y}.linear.max 0 <Integer> max value (#7)
    axis.{x|y}.linear.step 0 <Integer> step that defines tick count (#8)
    axis.{x|y}.linear.frequency year `[year month
    axis.{x|y}.linear.pivot - {} pivot options
    axis.{x|y}.linear.pivot.value null <Integer> pivot value, if null computed from min, max or data
    axis.{x|y}.linear.pivot.color black CSS color of pivot line
    axis.{x|y}.linear.pivot.thickness 2 <Integer> width of pivot line
    axis.{x|y}.grid.color black CSS color of a line
    axis.{x|y}.grid.thickness 1 <Integer> thickness of a line
    axis.{x|y}.grid.baselines [] Array of <Integer> grid lines considered as pivot line (#9)
    serie - {} serie options
    serie.colors ['gray'] [CSS] colors of a serie
    serie.overColors ['green'] [CSS] colors of a hovered serie
    serie.highlightColors ['blue'] [CSS] colors of highlighted series
    serie.baselineColors ['#263238'] [CSS] colors of baseline series
    serie.annotation - {} annotation options
    serie.annotation.font.family sans-serif CSS font family
    serie.annotation.font.size 10 <Integer> font size
    serie.annotation.font.weight normal CSS font weight
    serie.annotation.margin 2 <Integer> margin around annotation
    serie.annotation.format - {} annotation format (cf axis.format)
    serie.annotation.display focus `[never always
    serie.scatter - {} scatter options
    serie.scatter.markerRadius 7 <Integer> radius of a marker
    serie.scatter.areaIndex .1 [0 -> 1] ratio that control annotation position on edges
    serie.line.shadow 10 <Integer> shadow line for hovering more easily
    serie.line.thickness 1 <Integer> thickness of a line
    serie.line.marker - {} marker options for a line
    serie.line.marker.shadow 2 <Integer> shadow border of a marker
    serie.line.marker.shape circle `[circle cross
    serie.line.focused - {} focused line options
    serie.line.focused.thickness 2 <Integer> thickness of a focused line
    serie.line.densityRatio 32 <Integer> ratio for visibility of markers and annotations
    serie.tooltip - {} scatter options
    serie.tooltip.display over `[never over]`
    serie.tooltip.layout <proc> <function> proc that render an html string (#5)
    • (#1) compliant with the d3 standard
    • (#2) proc(datum) => datum.x%2 === 0 ? datum.x : 'odd values are odd...'
    • (#3) only used for x if labels are too long
    • (#4) correlated to orient (left, right), only for y
    • (#5) proc(serie, datum, color) => `<div style="${style}">X: ${datum.x}<br />Y: ${datum.y}</div>`
    • (#6) focus is the aggregation of all focus modes (highlight, baseline)
    • (#7) min and max values are overriden by data to avoid clamping and misleading charts
    • (#8) if min is 0 and max is 100 with 20 step, ticks will be [0,20,40,60,80,100], a 0 step (default) is considered invalid and will be overriden by data
    • (#9) pivot has an impact on all the computations, baselines have no impact. They are declarative, if they are drawn they have the same style as a pivot line.
    • (#10) a time axis has the same behavior as a linear axis except that ticks are handle by the combination of a frequency and a step (ie every quarter is month and 3)

    data

    {
      label: 'my serie',
      datapoints: [
        {x, y, z, highlightIndex, baselineIndex, label},
      ]
    }

    x, y, z can be <Integer> or <String>

    API (advanced usage)

    Advanced usage should be used when options are not enough to fit the needs.

    The Scatterplot into Bubble usecase

    The difference between the scatterplot and the bubble is the data used to compute the size of the plots.

    Here is the source of the bubble:

    function plotSizeAccessor(target) {
      target.accessors = {
        ...target.accessors,
        plotSize: (options, datum) => target.accessors.z(datum) > 0 ? target.accessors.z(datum) : 0
      };
    }
    
    @plotSizeAccessor
    export default class Bubble extends ScatterPlot {}

    The scatterplot engine is used to draw a bubble with a slight difference, the plotSize accessor has been changed:

    // in Scatterplot
    function plotSizeAccessor(target) {
      target.accessors = {
        ...target.accessors,
        plotSize: (options, datum) => options.plotSize
      };
    }

    note: bubble needs a little bit more like displaying smaller bubbles on top but to keep the usecase simple for the documentation, only the size aspect has been kept.

    This usecase is very simple but shows that:

    • tweaking a chart is not as complex as creating a chart
    • tweaking is not risky and has no side-effect on the inherited chart
    • tweaking is handy, the context is provided ((options, datum) => options.plotSize):
      • datum is not used in scatterplot
      • datum is required for bubble
      • datum represents a plot data ({x,y,z})
      • the accessor is executed somewhere in the flow engine where the datum is injected
      • plotSizes are computed on the fly by the engine (data-driven approach)

    Available hooks (decorators)

    name description
    selectors define css classes associated with charts DOM elements
    accessors define how the engine access data or options (x dimension, annotation label, ...)
    computors define computations used in the chart engine flow (ranges, scales, offsets, ...)
    eauors stands for 'enter and update -ors', define how to draw elements (with d3)

    Each chart defines decorators and a flow engine.
    Decorators are inherited and can overriden anywhere in the inheritance chain:

    1. Base defines how to compute the x axis
    2. Base::Scatterplot do nothing (ie reuse the x axis computation inherited from Base)
    3. Scatterplot::Bubble can redefine how to compute the x axis
    // default axis computation
    export default function computors(target) {
      target.computors = {
        ...target.computors,
        xAxis: (scale, options) => computeAxis(scale, options)
      }
    }
    
    // bar needs an ordinal axis
    export default function computors(target) {
      target.computors = {
        ...target.computors,
        xAxis: (scale, options) => computeOrdinalAxis(scale, options)
      }
    }

    Thoughts

    Hooks are a way for tweaking charts and handle usecases that options do not cover.
    Some hooks may be permanent, others can introduce features that may become native (ie accessible throught options).

    Tooltips

    Tooltip is a transversal concept that is be generic except the UI element on which it is attached and the event that trigger it.
    That is why tooltip handlers need to be declared for each charts since a chart is the only one to know its structure.

    Handlers:

    • showTooltip(_selector, accessors, options, scales, datum): show the tooltip
    • hideTooltip(_selector, partial): hide the tooltip

    These handlers manage the visibility of the tooltip and its placement.
    They also use the layout (provided in options) to display the tooltip as expected.

    // in eauors
    d3.select(/*<selector>*/)
      .on('mousemove', _.curry(showTooltip)(selectors.tooltip, accessors, options, scales))
      .on('mouseleave', _.curry(hideTooltip)(selectors.tooltip));

    It is not necessary to understand currying here, choose the UI part on which tooltip should appear and copy/paste the handler partial executions.
    Recommended events are mousemove and mouseleave but others can be used.

    Layout sample:

    function layout(datum, color) {
      const style = `
        font-size: 10px;
        font-family: sans-serif;
        color: ${color};
        padding: 5px;
        border: 1px solid ${color};
        background: white;
        opacity: .8;
      `;
      return `<div style="${style}">X: ${datum.x}<br />Y: ${datum.y}</div>`;
    }

    Inline style is accepted and allow a good customization.
    datum holds all the data relative to the point, bar, etc and color is the color used for highlighting.

    Keywords

    none

    Install

    npm i @sis-cc/dotstatsuite-d3-charts

    DownloadsWeekly Downloads

    22

    Version

    6.5.2

    License

    MIT

    Unpacked Size

    1.64 MB

    Total Files

    205

    Last publish

    Collaborators

    • avatar
    • avatar
    • avatar
    • avatar