src/PlotBar.ts

   1/**

   2 * ## PlotBar 

   3 * Plots data as vertical bars by configuring the series' `type` 

   4 * as {@link Series.Series.plot 'bar'}. The `cols` name array starts with 

   5 * the x-value column, or `undefined` to use the row index as x-values.

   6 * 

   7 * #### Mode 1 - Classic Bars

   8 * Specify a single name for y-values to generate bars that reach up from the

   9 * x-axis to the value in each data row. Negative heights are allowed.

  10 * Example: `y:'volume'`

  11 * 

  12 * #### Mode 2 - High-Low Bars

  13 * Specify names for y and yBase values to create high-low bars that reach from the 

  14 * y-value to the yBase-value for each data row. Negative heights are allowed.

  15 * Example: `y:'open', yBase:'close'`

  16 * 

  17 * #### Example

  18 * 

  19 * script.js'>

  20 * let series = {

  21 *    colNames:['time', 'volume', 'open', 'close'],

  22 *    rows:[

  23 *      [5, 0.2, 0.3, 0.5],

  24 *      [10, 0.7, 0.1, 0.2],

  25 *      [15, 0.4, 0.5, 0.6],

  26 *      [20, 0.1, 0.4, 0.6],

  27 *      [25,0.5, 0.3, 0.55],

  28 *      [30, 0.3, 0.4, 0.5]

  29 * ]};

  30 * 

  31 * m.mount(root, { 

  32 *      view:() => m(hsgraph.Graph, {cfgFn: cfg => {

  33 *          cfg.chart.title.text = 'Bar Chart';

  34 *          cfg.series.data   = [series];

  35 *          cfg.series.series = [

  36 *              { y:'volume', type: 'bar'},

  37 *              { y:'open', yBase:'close', type: 'bar'}

  38 *          ];

  39 *          cfg.series.series[0].style.bar.width = 80;

  40 *          cfg.series.series[1].style.bar.offset = 0;

  41 *          cfg.series.series[1].style.bar.width = 10;

  42 *      }})

  43 * });

  44 *

  45 * 

  46 * 

  47 */

  48

  49/** */

  50export const m = require("mithril");

  51export type Vnode = typeof m.Vnode;

  52import { Data }         from 'hsdatab';

  53import { NumDomain }    from 'hsdatab';

  54import { XYScale }      from './AxesTypes';

  55import { Plot }         from './Plot';

  56import { SeriesDef,

  57         SeriesStyle }  from './Series';

  58

  59export class PlotBar extends Plot {

  60    drawBar(clipID:string, data:Data, x:number, y:number, y0:number, scales:XYScale, sStyle:SeriesStyle, s:number) {

  61        const style = `fill: ${sStyle.bar.color};`;

  62        const index = (x === undefined);

  63        const domain = scales.x.domain();

  64        const offset = s*sStyle.bar.offset * (domain[1] - domain[0])/ (100 * data.getData().length);

  65        const width  = sStyle.bar.width    * (domain[1] - domain[0])/ (100 * data.getData().length);

  66        return m('svg', {class:'hs-graph-series-bars'}, data.getData().map(

  67            (p:number[], i:number) => {

  68                const rx0 = scales.x.convert((index? i : p[x]) + offset - width/2);

  69                const rx1 = scales.x.convert((index? i : p[x]) + offset + width/2);

  70                const ry0 = scales.y.convert(y0===undefined? 0 : p[y0]);

  71                const ry = scales.y.convert(p[y]);

  72                return this.rect({x:rx0, y:ry0}, {h:ry-ry0, w:rx1-rx0}, style);

  73            })

  74        );

  75    }

  76

  77    setDefaults(data:Data, series:SeriesDef, scales:XYScale) {

  78        super.setDefaults(data, series, scales);

  79        let  dom = scales.y.domain();

  80        if (dom[0] > 0) { 

  81            dom[0] = 0; 

  82            scales.y.domain(dom);

  83        }

  84        if (series.x === undefined) {

  85            scales.x.domain([-0.5, data.getData().length-0.5]);

  86        }

  87    }

  88

  89    plot(data:Data, series:SeriesDef, scales:XYScale, i:number, clipID:string): Vnode[] {

  90        const x = data.colNumber(series.x);

  91        const y = data.colNumber(series.y);

  92        const yBase = series.yBase? data.colNumber(series.yBase) : undefined;

  93        if (y===undefined) { return m('.error',''); }

  94        return [

  95            this.drawBar(clipID, data, x, y, yBase, scales, series.style, i),

  96        ];

  97    }

  98}

  99