Skip to content

Commit

Permalink
Added partial support for having custom colors per data item for line…
Browse files Browse the repository at this point in the history
… series

Fixes #195 (the second part)
  • Loading branch information
timocov committed Nov 5, 2021
1 parent dff7efd commit 59d727f
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 12 deletions.
1 change: 1 addition & 0 deletions docs/line-series.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Each item of the line series should be a [whitespace](./whitespace-data.md) item

- `time` ([Time](./time.md)) - a time of the item
- `value` (`number`) - a value of the item
- `color` (`string`) - an optional color of the item

## Customization

Expand Down
33 changes: 29 additions & 4 deletions src/api/data-consumer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,37 @@ export interface LineData {
value: number;
}

/**
* A base interface for a data point of single-value series.
*/
export interface SingleValueData {
/**
* The time of the data.
*/
time: Time;

/**
* Price value of the data.
*/
value: number;
}

/**
* Structure describing a single item of data for line series
*/
export interface LineData extends SingleValueData {
/**
* Optional color value for certain data item. If missed, color from options is used
*/
color?: string;
}

/**
* Structure describing a single item of data for histogram series
*/
export interface HistogramData extends LineData {
export interface HistogramData extends SingleValueData {
/**
* Optional color value for certain data item. If missed, color from HistogramSeriesOptions is used
* Optional color value for certain data item. If missed, color from options is used
*/
color?: string;
}
Expand Down Expand Up @@ -153,11 +178,11 @@ export interface SeriesDataItemTypeMap {
/**
* The types of area series data.
*/
Area: LineData | WhitespaceData;
Area: SingleValueData | WhitespaceData;
/**
* The types of baseline series data.
*/
Baseline: LineData | WhitespaceData;
Baseline: SingleValueData | WhitespaceData;
/**
* The types of line series data.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/api/get-series-plot-row-creator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { BarData, CandlestickData, HistogramData, isWhitespaceData, LineData, Se
function getLineBasedSeriesPlotRow(time: TimePoint, index: TimePointIndex, item: LineData | HistogramData): Mutable<SeriesPlotRow<'Line' | 'Histogram' | 'Area' | 'Baseline'>> {
const val = item.value;

const res: Mutable<SeriesPlotRow<'Histogram'>> = { index, time, value: [val, val, val, val] };
const res: Mutable<SeriesPlotRow<'Histogram' | 'Line'>> = { index, time, value: [val, val, val, val] };

// 'color' here is public property (from API) so we can use `in` here safely
// eslint-disable-next-line no-restricted-syntax
Expand Down
8 changes: 5 additions & 3 deletions src/model/series-bar-colorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class SeriesBarColorer {
const seriesOptions = this._series.options();
switch (targetType) {
case 'Line':
return this._lineStyle(seriesOptions as LineStyleOptions);
return this._lineStyle(seriesOptions as LineStyleOptions, barIndex, precomputedBars);

case 'Area':
return this._areaStyle(seriesOptions as AreaStyleOptions);
Expand Down Expand Up @@ -126,10 +126,12 @@ export class SeriesBarColorer {
};
}

private _lineStyle(lineStyle: LineStyleOptions): BarColorerStyle {
private _lineStyle(lineStyle: LineStyleOptions, barIndex: TimePointIndex, precomputedBars?: PrecomputedBars): BarColorerStyle {
const currentBar = ensureNotNull(this._findBar(barIndex, precomputedBars)) as SeriesPlotRow<'Line'>;

return {
...emptyResult,
barColor: lineStyle.color,
barColor: currentBar.color ?? lineStyle.color,
};
}

Expand Down
6 changes: 5 additions & 1 deletion src/model/series-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { PlotRow } from './plot-data';
import { PlotList } from './plot-list';
import { SeriesType } from './series-options';

export interface LinePlotRow extends PlotRow {
readonly color?: string;
}

export interface HistogramPlotRow extends PlotRow {
readonly color?: string;
}
Expand All @@ -21,7 +25,7 @@ export interface SeriesPlotRowTypeAtTypeMap {
Candlestick: CandlestickPlotRow;
Area: PlotRow;
Baseline: PlotRow;
Line: PlotRow;
Line: LinePlotRow;
Histogram: HistogramPlotRow;
}

Expand Down
9 changes: 8 additions & 1 deletion src/renderers/line-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { LinePoint, LineStyle, LineType, LineWidth, setLineStyle } from './draw-
import { ScaledRenderer } from './scaled-renderer';
import { walkLine } from './walk-line';

export type LineItem = TimedValue & PricedValue & LinePoint;
export type LineItem = TimedValue & PricedValue & LinePoint & { color?: string };

export interface PaneRendererLineDataBase {
lineType: LineType;
Expand Down Expand Up @@ -41,10 +41,17 @@ export abstract class PaneRendererLineBase<TData extends PaneRendererLineDataBas
ctx.lineJoin = 'round';

ctx.beginPath();

// TODO: implement drawing a colored line, see https://github.com/tradingview/lightweight-charts/issues/195#issuecomment-961850692

if (this._data.items.length === 1) {
const point = this._data.items[0];
ctx.moveTo(point.x - this._data.barWidth / 2, point.y);
ctx.lineTo(point.x + this._data.barWidth / 2, point.y);

if (point.color !== undefined) {
ctx.strokeStyle = point.color;
}
} else {
walkLine(ctx, this._data.items, this._data.lineType, this._data.visibleRange);
}
Expand Down
7 changes: 5 additions & 2 deletions src/views/pane/line-pane-view.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BarPrice } from '../../model/bar';
import { ChartModel } from '../../model/chart-model';
import { Series } from '../../model/series';
import { SeriesBarColorer } from '../../model/series-bar-colorer';
import { TimePointIndex } from '../../model/time-data';
import { IPaneRenderer } from '../../renderers/ipane-renderer';
import { LineItem, PaneRendererLine, PaneRendererLineData } from '../../renderers/line-renderer';
Expand Down Expand Up @@ -38,7 +39,9 @@ export class SeriesLinePaneView extends LinePaneViewBase<'Line', LineItem> {
return this._lineRenderer;
}

protected _createRawItem(time: TimePointIndex, price: BarPrice): LineItem {
return this._createRawItemBase(time, price);
protected _createRawItem(time: TimePointIndex, price: BarPrice, colorer: SeriesBarColorer): LineItem {
const item = this._createRawItemBase(time, price) as LineItem;
item.color = colorer.barStyle(time).barColor;
return item;
}
}

0 comments on commit 59d727f

Please sign in to comment.