This GitLab instance is undergoing maintenance and is operating in read-only mode.

You are on a read-only GitLab instance.
readme.md 24.9 KB
Newer Older
David Anderson's avatar
David Anderson committed
1
2
# Gist Charts
## Overview
3
4
The Gist chart is a canvas charting library built around the idea that charts should be modular, fast, reusable, interactive, and defined by their data.

5
## new ChartCanvas( htmlContainer to be filled with chart )
6
calling new ChartCanvas() defines a new chart container for you. The constructor takes an html element that will be filled with your chart. Your chart will be set to the same width and height of your provided element.
7

8
* <strong>addChart</strong>( configs: BaseChartConfig<DataPoint> | BaseChartConfig<DataPoint>[] ): void
David Anderson's avatar
David Anderson committed
9
10
  * Adds the given charts to this canvas. By Default, charts will be drawn in the order they are added. This can be changed by setting the zIndex value on charts though.

11
* <strong>removeChart</strong>( configs: BaseChartConfig<DataPoint> | BaseChartConfig<DataPoint>[] ): void
David Anderson's avatar
David Anderson committed
12
13
  * Removes one or many charts from this canvas.

14
* <strong>addAxis</strong>( configs: BaseChartConfig<DataPoint> | BaseChartConfig<DataPoint>[] ): void
David Anderson's avatar
David Anderson committed
15
16
  * Adds the given axis to this canvas. The axis itself will still need to register its charts, however this lets the axis know how much room it has when providing the range for the charts to draw with. By Default axis that are added will be drawn, but this can be prevented by setting the shouldRenderValues to false on the axis

17
* <strong>removeAxis</strong>( configs: BaseChartConfig<DataPoint> | BaseChartConfig<DataPoint>[] ): void
David Anderson's avatar
David Anderson committed
18
19
  * Removes the given axis from this chart. If the beginRender has been called on the chartcanvas, than it will need to be called again for this to have affect.

20
* <strong>beginRender</strong>(): void
David Anderson's avatar
David Anderson committed
21
22
  * All charts for this canvas will begin watching there datalist, and rendering all data given. Data can be added before or after beginRender as rendering is an asynchronous process. When all charts have drawn all of their given data, they will all be copied over to this canvas. Until then, they are each displayed over this canvas, so the user will be able to see their progress. All charts have a onRenderStateChange that can be overridden to know when they start or stop drawing.

23
* <strong>stopRender</strong>(): void
David Anderson's avatar
David Anderson committed
24
25
  * Tells all charts to stop watching there datalist.

26
* <strong>addBehavior</strong>( behavior: GistBehavior | GistBehavior[] ): void
David Anderson's avatar
David Anderson committed
27
28
  * Add the given behaviors to this canvas. By default, the canvas is a static element, but through behaviors you can allow the user to zoom, pan and drawn data interactivity with the user. See the section on behaviors for more data.

29
* <strong>removeBehavior</strong>( behavior: GistBehavior | GistBehavior[] ): void
David Anderson's avatar
David Anderson committed
30
31
  * Remove the given behaviors from this canvas. Behaviors that are removed, will no longer fire. They can always be restored by calling addBehavior again.

32
* <strong>cancelBehaviorActivation</strong>(): void
David Anderson's avatar
David Anderson committed
33
34
35
  * For performance reasons by default behaviors throttle or debounce their events. In the event that you wish to stop a delayed even from firing, you may call this method.
  * Note: This is called whenever the user mouses away from this canvas.

36
* <strong>zoom</strong>( zoomLevel: number ): void
David Anderson's avatar
David Anderson committed
37
38
  * Set the given zoom level for this canvas. Values between 0 and 1 will zoom out. Values greater than 1 will zoom in.

39
* <strong>pan</strong>( x: number, y: number ): void
David Anderson's avatar
David Anderson committed
40
41
  * Pan the canvas by x,y pixels

42
* <strong>getDataUrl</strong>( type?: string ): string
David Anderson's avatar
David Anderson committed
43
44
45
  * Calls toDataUrl on this canvas displayed html canvas element.
  * Note. If charts are currently rendering they may not be reflected by the return value of this. To ensure they are included, call this after renderstate change has been called.

46
* <strong>getImageData</strong>(x: number?, y: number?, width: number?, height: number? ): ImageData
David Anderson's avatar
David Anderson committed
47
48
49
  * Calls getImageData on the canvas's html canvas element's context. X, Y default to 0, and width and height default to the width and height of the canvas element.
  * Note. If charts are currently rendering they may not be reflected by the return value of this. To ensure they are included, call this after renderstate change has been called.

50
* <strong>background</strong>: string | undefined ( undefined by default )
David Anderson's avatar
David Anderson committed
51
52
53
  * By default your canvas will be transparent, you can set a background color for the canvas by setting this.
  * Note: This must be set before beginRender is called to have affect.

54
* <strong>layout</strong>: GistChartLayout
David Anderson's avatar
David Anderson committed
55
56
57
  * By default the chart canvas will take up the space in its parent element, then allocate space for the axis ( in the margins ), and leave the remaining space for the charts to be rendered in. This can be changed by editing these properties.
    * minMargin: TBLR\<number\> The minimal amount of space supplied for the axis to draw, and for the chart to overflow ( used to allow charts to draw values on the edge and display the overflow )
    * maxMargin: TBLR\<number\> The maximum amount of space supplied for the axis to draw, and for the chart to overflow ( used to allow charts to draw values on the edge and display the overflow )
David Anderson's avatar
David Anderson committed
58
59
60
61
62
---
## New DataPoint<T>( data?: T)
All Charts contain a data list that is made up of data points.

* <strong> data: T | Undefined</strong>
David Anderson's avatar
typos    
David Anderson committed
63
  * This is the data that is associated with this point. Anytime you need to do something with this specific point, store what you need here. This can be set either when the point as a constructor parameter or set directly later.
David Anderson's avatar
David Anderson committed
64
65
66
67

*<strong> getExtent( chart: BaseChart ): Extent
  * Return the extent x and y bounds of the shape that the given chart drew for this point.
  * Note: This will fail if the point is not drawn yet.
68

69
70
---
## Base Chart<T extends DataPoint = DataPoint>
David Anderson's avatar
David Anderson committed
71
All charts will have the following properties unless otherwise specified
72

73
* <strong>datalist</strong>( val?: Array<T> | T ) {
74
75
  * When given an array, This chart will wipe out drawn data it has already done, and then start watching the instance of the array given, and start drawing this array. That instance can have new points added, and this chart will draw them. However, points removed or changed after being drawn will not be detected.

76
* <strong>getStyle</strong>( dp: DataPoint | undefined ): CanvasStyle
77
78
  * This method should be overwritten. The method will take a DataPoint and return a style that determines how it will be drawn. See this method under each chart to see its defaults or any point of the canvas style that is ignored.

79
* <strong>drawCountPerRender</strong>: number
80
  * How many data points should be rendered per animation frame. Increasing this will cause the chart to draw faster, but may cause dips in browser performance.
81

82
* <strong>margin</strong>: number ( 0 by default )
83
84
  * The amount of space outside of the alloted chart that the chart can overflow onto. This is useful if you want a chart to draw on the explicit mins, or max and not be cut off.

85
* <strong>background</strong> : string | undefined ( undefined by default )
86
87
  * Charts are transparent by default ( easier to stack ) however, you can give a chart a background that will cover charts below this one.

88
* <strong>alpha</strong>: number ( 1 by default )
89
90
  * Decreasing the alpha will make this chart more transparent. Setting the value to 0 will make this chart completely invisible.

91
* <strong>zIndex</strong>: number | undefined ( undefined by default )
92
93
  * By defaults charts are drawn in the order they are given. The order can be changed by setting the zIndex.

94
* <strong>isActive</strong>: boolean ( true by default )
95
96
  * Active charts are drawn, inactive charts are not drawn.

97
* <strong>shouldCenterBandX</strong>: boolean ( false by default )
98
99
  * When this is set to true, if valueToWidth is overwritten, values will be offset by half of the returned value. This is useful if you want to align continuous axis and categorical axis. This is useful if you want to align a continuous axis with a categorical axis.

100
* <strong>shouldCenterBandY</strong>: boolean ( false by default )
101
  * When this is set to true, if valueToWidth is overwritten, values will be offset by half of the returned value. This is useful if you want to align continuous axis and categorical axis. This is useful if you want to align a continuous axis with a categorical axis.
David Anderson's avatar
David Anderson committed
102

103
104
105
106
107
108
109
110
111
### LineChart <small>extends BaseChart<LineChartData></small>
Each LineChartData will be drawn as a single line on the chart. The entire line, will be treated as a single entity, meaning that it is styled the same throughout and supported mouse events will trigger if anywhere on the line is clicked. If you want to have separate styles through the lines, you will need to create multiple LineChartData objects. If you want to have events trigger on the vertices, you can pass the DataPoints of the LineChartData to a scatter chart.
```
  class LineChartData<T = any> extends DataPoint<T> {
    points: DataPoint<any>[] = [];
  }
```

### ScatterChart <small>extends BaseChart</small>
112
* getStyle( dp: DataPoint ): ScatterStyle
113
114

### BarChart <small>extends BaseChart</small>
115
* <strong>getX2</strong>: undefined | ( ( dp: DataPoint ) => any );
116
  * Bars are anchored by the corner defined by the axis getValues. The second x coordinate is defined by getX2 if it is defined, if not, it is defined by valueToWidth.
117
* <strong>getY2</strong>: undefined | ( ( dp: DataPoint ) => any );
118
  * Bars are anchored by the corner defined by the axis getValues. The second y coordinate is defined by getY2 if it is defined, if not, it is defined by valueToWidth.
David Anderson's avatar
David Anderson committed
119

120
### AreaChart <small>extends BaseChart</small>
121
* <strong>fillAxis</strong>: BaseAxis ( the charts x axis by default )
David Anderson's avatar
David Anderson committed
122
  * When shouldFillToOrigin is true ( it is by default ), this axis will be used to fill the area with.
123
* <strong>shouldFillToOrigin</strong> : boolean ( true by default )
David Anderson's avatar
David Anderson committed
124
125
  * If true, the data lines will connect the areas bounding line to the origin and then fill it.
  * If false, the end of the lines will be connected and filled.
126
* <strong>axisOrigin</strong>: any ( should be the same type used for values of the fill axis )
127
128
  * This is the value that areas will be filled to.

129
### BoxPlot <small>extends BaseChart</small>
130
* <strong>primaryAxis</strong>: BaseAxis ( has to be set or will not drawn )
David Anderson's avatar
David Anderson committed
131
  * The whiskers of the boxplot will stretch out from the core box along this axis.
132
* <strong>secondaryAxis</strong>: BaseAxis ( has to be set or will not drawn )
David Anderson's avatar
David Anderson committed
133
  * The box plot items will use this axis to determine the width of each item drawn.
134
135
* <strong>getBandThickness</strong>:  ( datapoint?: BoxPlotData ) => number
    * How wide should the box plots be drawn? by default this is determined by the axis. Categorical axis will give the width of the corresponding category. While continuous axis will return the size of the stroke. You can overwrite this behavior by redefining this function.
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

### RadialChart <small>extends BaseChart</small>
Note: radial chart close enough property only works on the inner and outer radius. It will not consider the point if is not between the start and stop angles.
* <strong>isClockwise</strong>: boolean = false;
  * By default unit circles are not clockwise. flip this to true if you want them
* <strong>labelPixelOffset</strong>: number = 15;
  * set the number of pixels to offset labels by
* <strong>centerXValue</strong>: number = 0;
  * This is the value that will be given to the axis to determine the center of the chart
* <strong>centerYValue</strong>: number = 0;
  * This is the value that will be given to the axis to determine the center of the chart
* <strong>radialAxis</strong>: BaseAxis | undefined;
  * Axis to use when scaling the radius. By default will be the x axis
* <strong>getStartAngle</strong>: ( dp: DataPoint )=>number = shouldImplement.bind( this, 'getStartAngle') as any;
  * How to extract the start angle from the data point
* <strong>getStopAngle</strong>: ( dp: DataPoint )=>number = shouldImplement.bind( this, 'getStopAngle') as any;
  * How to extract the end angle from the data point
* <strong>getInnerRadius</strong>: ( dp: DataPoint )=>number = shouldImplement.bind( this, 'getInnerRadius') as any;
  * Given the data point get what you need to give to the axis getValue( x: any )=> number method
* <strong>getOuterRadius</strong>: ( dp: DataPoint )=>number = shouldImplement.bind( this, 'getOuterRadius') as any;
  * Given the data point get what you need to give to the axis getValue( x:any )=> number method
* <strong>getLabel</strong>:( dp: DataPoint )=>string|undefined = shouldImplement.bind(this, 'getLabel') as any;
  * Given the data point get the label for that curve
159
160
161
---
### Base Axis\<T\>
All Axis will have these properties and configs unless otherwise specified.
David Anderson's avatar
David Anderson committed
162

163
164
165
166
167
168
* <strong>getValue</strong>( dp: DataPoint ): T
  * This method must be provided by the coder. It converts a datapoint to the value that this axis is built off of.

* <strong>valueToString</strong>( value: T, tickIndex?: number, tickArray?: T[] ): string
  This method determines how axis values are displayed on the tick marks. By default, what ever the value, is will just have toString() called on it. However if you are using something like a date, or floating numbers, you will want to overwrite this method to provide your own formatting. The value is the current value getting formatted. The tick index is the index of the tick mark in its array. tickArray, is an array of all the tick values that will be displayed.

David Anderson's avatar
David Anderson committed
169
170
171
172
* <strong>valueToImage</strong>( value:T )=> GistCanvas | undefined
  * Set this method to draw the given GistCanvas behind or in place of any text given by valueToString.
  * We use GistCanvas because it automatically applies the pixel ratio logic to prevent blurs.

173
* <strong>label</strong>: string | undefined;
174
 * The string that displayed on the side of this axis.
175

176
* <strong>lineHeight</strong>: number = 20;
177
178
  * How tall the canvas should consider the text to be to ensure that it has enough room to display

179
* <strong>font</strong>: string = 'bold 14px Roboto,"Helvetica Neue",sans-serif';
180
181
  * What font the canvas should use to draw with this axis

182
* <strong>tickAngle</strong>: number = 0 ( radians );
183
184
  * By default, tick labels will be drawn horizontally, You can give an an angle in radians to rotate the text. Note, this will
  throw off the alignment for the labels, so we advise setting that.
185
186

* <strong>tickTextAlign</strong>: undefined | 'center' | 'right' | 'left' = undefined;
187
188
  * How the tick labels should be aligned with respect to their ticks. When undefined, Top and bottom axis will center their
  text, and the left and right text will align the text to line up against the tick mark.
189
190

* <strong>axisLineThickness</strong>: number = 1;
191
192
  * How thick are the tick marks/ axis border

193
* <strong>color</strong>: string = '#000';
194
195
  * The color that will be used to draw the axis border, ticks, tick labels and axis label.

196
* <strong>tickLength</strong>: number = 5;
197
198
  * How long in pixels to make the tick marks

199
* <strong>tickLabelPad</strong>: number = 3;
200
201
  * How much space around between tick marks and tick labels, and the tick labels and axis label.

202
* <strong>shouldRenderTicks</strong>: boolean = true;
203
204
  * Set this to false to not draw tick marks or their labels

205
* <strong>shouldRenderBorder</strong>: boolean = true;
206
207
  * Set this to false to not draw the border against the edge of the chart

208
* <strong>shouldExtendTicksAcrossChart</strong>: boolean = false;
209
210
211
  * Set this to true to extend tick makes across the chart. These will be drawn behind each chart.


212
213
214
215
* <strong>registerChart</strong>( charts: BaseChart<DataPoint> | BaseChart<DataPoint>[] ): BaseAxis
  * Tells each provided chart to use this axis as its x or y axis ( determined by this axis orientation )

* <strong>resetZoom</strong>(): void
216
217
  * Reset the zoom level to 1.

218
* <strong>zoom</strong>( zoom: number = 1.14, offset: number = 0 ): void
219
  * Set the zoom level for this axis. Values between 0 and 1, zoom out from the default view. Values greater than 1 zoom in.
220

221
### CategoricalAxis\<T\> <small>extends BaseAxis</small>
David Anderson's avatar
typos    
David Anderson committed
222
CategoricalAxis are axis non continuous domains. They require explicitCategories to be set. And any value datapoint that cannot find a category will throw an error, so they should be filtered out before given to a list. By default, the size of each category will be the same such that when combined, they will fill the chart.
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242

* <strong>explicitCategories</strong>( value: T ):
  * An array of the categories that make up this axis domain. In order for changes in this to be detected, chartCanvas.beginRender() must be called.

* <strong>getCategorySize</strong>( value: T ): number
  * If you want a category to be a certain size, you can set this method. It will overwrite minCategorySize and maxCategorySize.

* <strong>minCategorySize</strong>: number | undefined = undefined
      * Ensure that categories will be no smaller than this. If there is not enough room on the axis, points will be drawn off canvas and not be seen.
  * Note: this will be overwritten by getCategorySize

* <strong>maxCategorySize</strong>: number | undefined = undefined
    * Ensure that categories will be no larger than this. This may cause the chart to not fill the given canvas.
    * Note: this will be overwritten by getCategorySize

* <strong>innerPadding</strong>: number = 0.1
  * Once the width for the category is determined,what percentage of that belongs to the space between categories. This value only   determines the space in between categories. To set the space between the first and last category and the edge of the chart, set outerPadding

* <strong>outerPadding</strong>: number = 0.1
  * Once the width for the category is determined,what percentage of that belongs to the space between the first and last category and the   edge of the chart canvas. To set the space between the categories, set innerPadding
243

244
245
246
247
248
* <strong>tickLabelPosition</strong>: 'center' | 'stop' | 'start' = 'center'
  * Tells the axis where to draw its label for the category.
     * 'center' ( default ) is in the middle of the category.
     * 'start' will draw it where the band begins.
     * 'stop' will draw it where the band ends.
249

250
### ContinuousAxis\<T\> <small>extends BaseAxis</small>
251
Continuous axis. Where the value to pixel is determined using a linear scale mapped from the chart extents to the explicit bounds.
252

253
254
255
* <strong>explicitBounds</strong>: T[]
  * Explicit min and max values for this axis. Order does not matter, the chart will flow with the first value being on the left, to second value being on the right.
* <strong>explicitTickValues</strong>: T[] | undefined
256

257
258
* <strong>valueToWidth</strong>( value: T )
  * This method will determine how wide a category on the axis will be given. By default, a ContinuousAxis will give all values the value of Axis.axisLineThickness.
259

260
 ### LogAxis<T> <small>extends ContinuousAxis</small>
261
262
263
 Log axis is an extension of the continuous scale. Instead of a linear scale, a log scale will be used.
 * <strong>base</strong>: number = 10
   * The base for this logarithmic to use.
264

265
 ### TemporalAxis<T> <small>extends ContinuousAxis</small>
266
 TemporalAxis is an extension of the continuous axis. The value of the dates are used to generate ticks. Using a temporal axis instead of a continuous axis will result in much better tick marks.
267

268
---
269
## Behaviors
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
ChartCanvas will not be interactive by default. You can change this by calling addBehavior, and then passing in a new behavior object.

```
    let getData = new GetDataAtMouseEvent(
            'click',
            {
                chart: charts,
                onEvent: ( reports ) => {
                    let pointsAtEvent: DataPoint[] = [];
                    reports.forEach( r => pointsAtEvent.push( ...r.dpl ) );

                    if ( !pointsAtEvent.length ) {
                        selectedData = [];
                    }
                    selectedData.push( ...pointsAtEvent );
                    selectionUpdate();
                }
            },
288
            3
289
290
291
292
293
294
295
296
297
        );
        let zoom = new ZoomBehavior();
        zoom.limitZoom( axis, 0.5, 1.5 );

        let pan = new PanBehavior('wheel'); // use wheel because we want to click on the data
        pan.limitPan( bottomAxis, pointCount * -0.25, pointCount * 1.25 );

        me.chart.addBehavior( [ getData, zoom, pan ] );
```
298

299
### PanBehavior
300
301
302
303
304
305
306
PanBehavior will allow the user to pan the various charts by the x and y axis. By default, it works by holding the mouse button down on the chart, dragging to pan, and then releasing to stop. Be warned that this does trigger redraws on every chart and this can be costly in performance.
* <strong> new PanBehavior</strong>(eventNames: 'mousedrag' | 'wheel', throttleTime: number )
  * eventNames: 'wheel' allows the user to pan by scrolling the mouse. 'mousedrag' works by clicking down and dragging.
  * throttleTime: How often in milliseconds this event can fire. defaults to 15
* <strong>limitPan</strong>( axis: BaseAxis, minValue: T, maxValue: T ) where T is the type that the axis uses for values
  * The given axis will not allow the min or max value to be moved out of the chart view.
  * Beta feature. It is known that this can lock up sometimes, especially when used with ZoomBehavior.limitZoom
307

308
### ZoomBehavior
309
310
311
312
313
314
315
316
317
318
ZoomBehavior allow the user to zoom in on the data while not changing the size of the chart element and still keep the same resolution.

* <strong> new ZoomBehavior</strong>(zoomConstant: number ,zoomMethod: 'multiplication' | 'addition' , throttleTime: number  )
  * zoomConstant: controls how strong the zoom step is. Defaults to 1.15
  * zoomMethod: multiplication zoom steps are based on the current zoom level resulting in a smoother movement. addition will jump by steps. defaults to 'multiplication'
  * throttleTime:  how long in milliseconds to throttle the event. defaults to 50.

* <strong>limitZoom</strong>( targets: BaseAxis | Array<BaseAxis>, minZoomLevel: number, maxZoomLevel: number )
  * The given axis will not be able to zoom past the minZoomLevel and maxZoomLevel
  * Beta feature. It is known that this can lock up sometimes, especially when used with PanBehavior.limitPan
319

320
### GetDataAtEvent
321
322
This behavior will get all drawn data points at the given event, and make a callback with each of the given charts, and the data at that point for the chart. Note, only points that are drawn will be returned.

323
* <strong>new GetDataAtMouseEvent </strong>( eventNames: supportedEventType | supportedEventType[], eventHandlers: EventHandler | EventHandler[], closeEnough: number = 0  throttleTime: number = 250, limiter: LimiterType = 'throttle' )
324
325
  * supportedEventType: 'dblclick' | 'click' | 'mousedown' | 'mousemove' | 'mouseout' | 'mouseover' | 'mouseup'
  * EventHandler is an interface object you need to pass to tell what charts to listen for this event on, and how to handle the event. When the onEvent method you pass is called, it will be called with a list of reports EventReports. Each report has a chart, and the list of drawn datapoints at this event.
326
327
  * closeEnough: number( 0 by default ) The number of pixels that a mouse can be away from a drawn value and still register as being over it.

328
329
330
331
332
333
334
335
336
337
338
339
340
341

```
interface EventHandler {
  chart: BaseChart | Array<BaseChart> | undefined;
  onEvent: (
      reportList: Array<EventReport>,
      mouseEvent: MouseEvent | undefined
  ) => void;
}

interface EventReport {
    dpl: DataPoint[],
    chart: BaseChart
}
David Anderson's avatar
David Anderson committed
342
```
343
---
344
## Debugging ( debugLogger.enabled=true )
David Anderson's avatar
typos    
David Anderson committed
345
ChartCanvas, Charts, and Axis objects all have an object property called debugLogger. If you set its enabled flag, to true, it will print out various debug information.This is very very verbose. To help with the amount of information, You can set the logPrefix to prefix each message an object prints with the prefix. By default, it will use window.console.error to log debug information, bt you can overwrite its log method to anything you like. The object is defined as.
346
```
347
348
349
350
class DebugLogger{
    logPrefix: string = '' // string to prefix any message from this logger.
    logMethod: = console.error // method to be called when debug information is provided.
    isEnabled: boolean = false // whether or not to provide debug information.
351
  }
352
  ```
353

354
---
355
356
357
358
359
## Helper Functions
### makeHiDPICanvas( width: number, height: number, canvas?: HTMLCanvasElement )
Will scale a canvas to device resolution. See https://www.html5rocks.com/en/tutorials/canvas/hidpi/ for an explanation for why this is needed.

### drawSourceCanvas( source: HTMLCanvasElement, destination: HTMLCanvasElement, left: number, top: number )
David Anderson's avatar
David Anderson committed
360
361
362
Will draw the source canvas onto the destination canvas. This is essentially context.drawImage, except that this will do the HiDPI scaling for you.


363
### Utility Classes / Interfaces
364
365
366
367
368
369
370
371
372
373
374
```
 class TBLR<T>{
  public top:T
  public bottom:T
  public left:T
  public right:T
  constructor ( defaultValue: T | TBLR<T> )
  isEqual( tblr: TBLR<T> // returns true if all values of both instances are the same
  setValue( value: T  ) // Returns true if top, bottom left and right all equal value.
  setValue( TBLR<T> ) // Returns if top, bottom, left, and right all equal their corresponding values
 }
David Anderson's avatar
David Anderson committed
375

376
377
378
379
380
 class DebugLogger{
    logPrefix: string = ''
    logMethod: = console.error
    isEnabled: boolean = false
  }
381

382
  ```
David Anderson's avatar
David Anderson committed
383

David Anderson's avatar
1.1.0    
David Anderson committed
384
385
386
387
388
### Change Log

* 1.1.0:
  * Feature: ValueToImage on axis
  * Bug Fix: OnRenderStateChange will trigger when rendering begins and finishes on the same cycle
David Anderson's avatar
David Anderson committed
389
390
* 1.1.001
  * Bug Fix: Chart margins will now be cleared