From 1c5bcb72189ada2348b64b279658891eb63ad272 Mon Sep 17 00:00:00 2001 From: Kirill Chetverikov Date: Mon, 24 Apr 2023 14:57:18 +0300 Subject: [PATCH 01/14] Implemented line-based series' point markers support --- src/api/options/series-options-defaults.ts | 3 + src/model/series-options.ts | 51 +++++++++++-- src/renderers/area-renderer-base.ts | 25 +++--- src/renderers/area-renderer.ts | 8 +- src/renderers/baseline-renderer-area.ts | 10 +-- src/renderers/baseline-renderer-line.ts | 8 +- src/renderers/draw-line.ts | 2 +- src/renderers/line-renderer-base.ts | 21 +++-- src/renderers/walk-line.ts | 76 ++++++++++++++----- src/views/pane/baseline-pane-view.ts | 17 +++-- src/views/pane/line-pane-view.ts | 9 ++- .../series/area-with-point-markers.js | 21 +++++ .../series/baseline-with-point-markers.js | 57 ++++++++++++++ .../series/line-with-point-markers.js | 25 ++++++ 14 files changed, 263 insertions(+), 70 deletions(-) create mode 100644 tests/e2e/graphics/test-cases/series/area-with-point-markers.js create mode 100644 tests/e2e/graphics/test-cases/series/baseline-with-point-markers.js create mode 100644 tests/e2e/graphics/test-cases/series/line-with-point-markers.js diff --git a/src/api/options/series-options-defaults.ts b/src/api/options/series-options-defaults.ts index 5cee840180..ea8779b7b2 100644 --- a/src/api/options/series-options-defaults.ts +++ b/src/api/options/series-options-defaults.ts @@ -42,6 +42,7 @@ export const lineStyleDefaults: LineStyleOptions = { crosshairMarkerBorderWidth: 2, crosshairMarkerBackgroundColor: '', lastPriceAnimation: LastPriceAnimationMode.Disabled, + pointMarkersVisible: false, }; export const areaStyleDefaults: AreaStyleOptions = { @@ -58,6 +59,7 @@ export const areaStyleDefaults: AreaStyleOptions = { crosshairMarkerBorderWidth: 2, crosshairMarkerBackgroundColor: '', lastPriceAnimation: LastPriceAnimationMode.Disabled, + pointMarkersVisible: false, }; export const baselineStyleDefaults: BaselineStyleOptions = { @@ -85,6 +87,7 @@ export const baselineStyleDefaults: BaselineStyleOptions = { crosshairMarkerBackgroundColor: '', lastPriceAnimation: LastPriceAnimationMode.Disabled, + pointMarkersVisible: false, }; export const histogramStyleDefaults: HistogramStyleOptions = { diff --git a/src/model/series-options.ts b/src/model/series-options.ts index 2dc340a93e..0ef7357061 100644 --- a/src/model/series-options.ts +++ b/src/model/series-options.ts @@ -174,6 +174,19 @@ export interface LineStyleOptions { */ lineType: LineType; + /** + * Show circle markers on each point. + * + * @defaultValue `false` + */ + pointMarkersVisible: boolean; + /** + * Circle markers radius in pixels. + * + * @defaultValue `undefined` + */ + pointMarkersRadius?: number; + /** * Show the crosshair marker. * @@ -187,13 +200,13 @@ export interface LineStyleOptions { */ crosshairMarkerRadius: number; /** - * Crosshair marker border color. An empty string falls back to the the color of the series under the crosshair. + * Crosshair marker border color. An empty string falls back to the color of the series under the crosshair. * * @defaultValue `''` */ crosshairMarkerBorderColor: string; /** - * The crosshair marker background color. An empty string falls back to the the color of the series under the crosshair. + * The crosshair marker background color. An empty string falls back to the color of the series under the crosshair. * * @defaultValue `''` */ @@ -266,6 +279,19 @@ export interface AreaStyleOptions { */ lineType: LineType; + /** + * Show circle markers on each point. + * + * @defaultValue `false` + */ + pointMarkersVisible: boolean; + /** + * Circle markers radius in pixels. + * + * @defaultValue `undefined` + */ + pointMarkersRadius?: number; + /** * Show the crosshair marker. * @@ -279,13 +305,13 @@ export interface AreaStyleOptions { */ crosshairMarkerRadius: number; /** - * Crosshair marker border color. An empty string falls back to the the color of the series under the crosshair. + * Crosshair marker border color. An empty string falls back to the color of the series under the crosshair. * * @defaultValue `''` */ crosshairMarkerBorderColor: string; /** - * The crosshair marker background color. An empty string falls back to the the color of the series under the crosshair. + * The crosshair marker background color. An empty string falls back to the color of the series under the crosshair. * * @defaultValue `''` */ @@ -393,6 +419,19 @@ export interface BaselineStyleOptions { */ lineType: LineType; + /** + * Show circle markers on each point. + * + * @defaultValue `false` + */ + pointMarkersVisible: boolean; + /** + * Circle markers radius in pixels. + * + * @defaultValue `undefined` + */ + pointMarkersRadius?: number; + /** * Show the crosshair marker. * @@ -406,13 +445,13 @@ export interface BaselineStyleOptions { */ crosshairMarkerRadius: number; /** - * Crosshair marker border color. An empty string falls back to the the color of the series under the crosshair. + * Crosshair marker border color. An empty string falls back to the color of the series under the crosshair. * * @defaultValue `''` */ crosshairMarkerBorderColor: string; /** - * The crosshair marker background color. An empty string falls back to the the color of the series under the crosshair. + * The crosshair marker background color. An empty string falls back to the color of the series under the crosshair. * * @defaultValue `''` */ diff --git a/src/renderers/area-renderer-base.ts b/src/renderers/area-renderer-base.ts index 4c85768540..af6f1f1c92 100644 --- a/src/renderers/area-renderer-base.ts +++ b/src/renderers/area-renderer-base.ts @@ -1,11 +1,11 @@ -import { MediaCoordinatesRenderingScope } from 'fancy-canvas'; +import { BitmapCoordinatesRenderingScope } from 'fancy-canvas'; import { Coordinate } from '../model/coordinate'; import { PricedValue } from '../model/price-scale'; import { SeriesItemsIndexesRange, TimedValue } from '../model/time-data'; +import { BitmapCoordinatesPaneRenderer } from './bitmap-coordinates-pane-renderer'; import { LinePoint, LineStyle, LineType, LineWidth, setLineStyle } from './draw-line'; -import { MediaCoordinatesPaneRenderer } from './media-coordinates-pane-renderer'; import { walkLine } from './walk-line'; export type AreaFillItemBase = TimedValue & PricedValue & LinePoint; @@ -25,26 +25,27 @@ export interface PaneRendererAreaDataBase extends MediaCoordinatesPaneRenderer { +export abstract class PaneRendererAreaBase extends BitmapCoordinatesPaneRenderer { protected _data: TData | null = null; public setData(data: TData): void { this._data = data; } - protected _drawImpl(renderingScope: MediaCoordinatesRenderingScope): void { + protected _drawImpl(renderingScope: BitmapCoordinatesRenderingScope): void { if (this._data === null) { return; } @@ -68,8 +69,8 @@ export abstract class PaneRendererAreaBase { export class PaneRendererArea extends PaneRendererAreaBase { private _fillCache: AreaFillCache | null = null; - protected override _fillStyle(renderingScope: MediaCoordinatesRenderingScope, item: AreaFillItem): CanvasRenderingContext2D['fillStyle'] { - const { context: ctx, mediaSize } = renderingScope; + protected override _fillStyle(renderingScope: BitmapCoordinatesRenderingScope, item: AreaFillItem): CanvasRenderingContext2D['fillStyle'] { + const { context: ctx, bitmapSize } = renderingScope; const { topColor, bottomColor } = item; - const bottom = mediaSize.height as Coordinate; + const bottom = bitmapSize.height as Coordinate; if ( this._fillCache !== null && diff --git a/src/renderers/baseline-renderer-area.ts b/src/renderers/baseline-renderer-area.ts index a22c24e401..fd304330be 100644 --- a/src/renderers/baseline-renderer-area.ts +++ b/src/renderers/baseline-renderer-area.ts @@ -1,4 +1,4 @@ -import { MediaCoordinatesRenderingScope } from 'fancy-canvas'; +import { BitmapCoordinatesRenderingScope } from 'fancy-canvas'; import { clamp } from '../helpers/mathex'; @@ -19,14 +19,14 @@ interface BaselineFillCache extends Record { private _fillCache: BaselineFillCache | null = null; - protected override _fillStyle(renderingScope: MediaCoordinatesRenderingScope, item: BaselineFillItem): CanvasRenderingContext2D['fillStyle'] { - const { context: ctx, mediaSize } = renderingScope; + protected override _fillStyle(renderingScope: BitmapCoordinatesRenderingScope, item: BaselineFillItem): CanvasRenderingContext2D['fillStyle'] { + const { context: ctx, bitmapSize } = renderingScope; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const data = this._data!; const { topFillColor1, topFillColor2, bottomFillColor1, bottomFillColor2 } = item; - const baseLevelCoordinate = data.baseLevelCoordinate ?? mediaSize.height as Coordinate; - const bottom = mediaSize.height as Coordinate; + const baseLevelCoordinate = data.baseLevelCoordinate ?? bitmapSize.height as Coordinate; + const bottom = bitmapSize.height as Coordinate; if ( this._fillCache !== null && diff --git a/src/renderers/baseline-renderer-line.ts b/src/renderers/baseline-renderer-line.ts index 6772ce9051..af828d2875 100644 --- a/src/renderers/baseline-renderer-line.ts +++ b/src/renderers/baseline-renderer-line.ts @@ -1,4 +1,4 @@ -import { MediaCoordinatesRenderingScope } from 'fancy-canvas'; +import { BitmapCoordinatesRenderingScope } from 'fancy-canvas'; import { clamp } from '../helpers/mathex'; @@ -21,14 +21,14 @@ interface BaselineStrokeCache extends Record { private _strokeCache: BaselineStrokeCache | null = null; - protected override _strokeStyle(renderingScope: MediaCoordinatesRenderingScope, item: BaselineStrokeItem): CanvasRenderingContext2D['strokeStyle'] { - const { context: ctx, mediaSize } = renderingScope; + protected override _strokeStyle(renderingScope: BitmapCoordinatesRenderingScope, item: BaselineStrokeItem): CanvasRenderingContext2D['strokeStyle'] { + const { context: ctx, bitmapSize } = renderingScope; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const data = this._data!; const { topLineColor, bottomLineColor } = item; const { baseLevelCoordinate } = data; - const bottom = mediaSize.height as Coordinate; + const bottom = bitmapSize.height as Coordinate; if ( this._strokeCache !== null && diff --git a/src/renderers/draw-line.ts b/src/renderers/draw-line.ts index 8be951893e..655d887ac9 100644 --- a/src/renderers/draw-line.ts +++ b/src/renderers/draw-line.ts @@ -58,7 +58,7 @@ export const enum LineStyle { */ LargeDashed = 3, /** - * A dottled line with more space between dots. + * A dotted line with more space between dots. */ SparseDotted = 4, } diff --git a/src/renderers/line-renderer-base.ts b/src/renderers/line-renderer-base.ts index 7fc07cfbda..b38fb36f48 100644 --- a/src/renderers/line-renderer-base.ts +++ b/src/renderers/line-renderer-base.ts @@ -1,10 +1,10 @@ -import { MediaCoordinatesRenderingScope } from 'fancy-canvas'; +import { BitmapCoordinatesRenderingScope } from 'fancy-canvas'; import { PricedValue } from '../model/price-scale'; import { SeriesItemsIndexesRange, TimedValue } from '../model/time-data'; +import { BitmapCoordinatesPaneRenderer } from './bitmap-coordinates-pane-renderer'; import { LinePoint, LineStyle, LineType, LineWidth, setLineStyle } from './draw-line'; -import { MediaCoordinatesPaneRenderer } from './media-coordinates-pane-renderer'; import { walkLine } from './walk-line'; export type LineItemBase = TimedValue & PricedValue & LinePoint; @@ -20,26 +20,29 @@ export interface PaneRendererLineDataBase extends MediaCoordinatesPaneRenderer { +export abstract class PaneRendererLineBase extends BitmapCoordinatesPaneRenderer { protected _data: TData | null = null; public setData(data: TData): void { this._data = data; } - protected _drawImpl(renderingScope: MediaCoordinatesRenderingScope): void { + protected _drawImpl(renderingScope: BitmapCoordinatesRenderingScope): void { if (this._data === null) { return; } - const { items, visibleRange, barWidth, lineType, lineWidth, lineStyle } = this._data; + const { items, visibleRange, barWidth, lineType, lineWidth, lineStyle, pointMarkersRadius } = this._data; if (visibleRange === null) { return; @@ -54,8 +57,10 @@ export abstract class PaneRendererLineBase( - renderingScope: MediaCoordinatesRenderingScope, +export function walkLine( + renderingScope: BitmapCoordinatesRenderingScope, items: readonly TItem[], lineType: LineType, + pointMarkersRadius: number | undefined, visibleRange: SeriesItemsIndexesRange, barWidth: number, // the values returned by styleGetter are compared using the operator !==, // so if styleGetter returns objects, then styleGetter should return the same object for equal styles - styleGetter: (renderingScope: MediaCoordinatesRenderingScope, item: TItem) => TStyle, - finishStyledArea: (ctx: CanvasRenderingContext2D, style: TStyle, areaFirstItem: LinePoint, newAreaFirstItem: LinePoint) => void + styleGetter: (renderingScope: BitmapCoordinatesRenderingScope, item: TItem) => TStyle, + finishStyledArea: (renderingScope: BitmapCoordinatesRenderingScope, style: TStyle, areaFirstItem: LinePoint, newAreaFirstItem: LinePoint) => void ): void { if (items.length === 0 || visibleRange.from >= items.length || visibleRange.to <= 0) { return; } - const ctx = renderingScope.context; + const { context: ctx, horizontalPixelRatio, verticalPixelRatio } = renderingScope; const firstItem = items[visibleRange.from]; let currentStyle = styleGetter(renderingScope, firstItem); @@ -35,16 +36,16 @@ export function walkLine( const item1: LinePoint = { x: firstItem.x - halfBarWidth as Coordinate, y: firstItem.y }; const item2: LinePoint = { x: firstItem.x + halfBarWidth as Coordinate, y: firstItem.y }; - ctx.moveTo(item1.x, item1.y); - ctx.lineTo(item2.x, item2.y); + ctx.moveTo(item1.x * horizontalPixelRatio, item1.y * verticalPixelRatio); + ctx.lineTo(item2.x * horizontalPixelRatio, item2.y * verticalPixelRatio); - finishStyledArea(ctx, currentStyle, item1, item2); + finishStyledArea(renderingScope, currentStyle, item1, item2); return; } const changeStyle = (newStyle: TStyle, currentItem: TItem) => { - finishStyledArea(ctx, currentStyle, currentStyleFirstItem, currentItem); + finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); ctx.beginPath(); currentStyle = newStyle; @@ -54,7 +55,7 @@ export function walkLine( let currentItem = currentStyleFirstItem; ctx.beginPath(); - ctx.moveTo(firstItem.x, firstItem.y); + ctx.moveTo(firstItem.x * horizontalPixelRatio, firstItem.y * verticalPixelRatio); for (let i = visibleRange.from + 1; i < visibleRange.to; ++i) { currentItem = items[i]; @@ -62,33 +63,72 @@ export function walkLine( switch (lineType) { case LineType.Simple: - ctx.lineTo(currentItem.x, currentItem.y); + ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); break; case LineType.WithSteps: - ctx.lineTo(currentItem.x, items[i - 1].y); + ctx.lineTo(currentItem.x * horizontalPixelRatio, items[i - 1].y * verticalPixelRatio); if (itemStyle !== currentStyle) { changeStyle(itemStyle, currentItem); - ctx.lineTo(currentItem.x, items[i - 1].y); + ctx.lineTo(currentItem.x * horizontalPixelRatio, items[i - 1].y * verticalPixelRatio); } - ctx.lineTo(currentItem.x, currentItem.y); + ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); break; case LineType.Curved: { const [cp1, cp2] = getControlPoints(items, i - 1, i); - ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, currentItem.x, currentItem.y); + ctx.bezierCurveTo( + cp1.x * horizontalPixelRatio, + cp1.y * verticalPixelRatio, + cp2.x * horizontalPixelRatio, + cp2.y * verticalPixelRatio, + currentItem.x * horizontalPixelRatio, + currentItem.y * verticalPixelRatio + ); break; } } if (lineType !== LineType.WithSteps && itemStyle !== currentStyle) { changeStyle(itemStyle, currentItem); - ctx.moveTo(currentItem.x, currentItem.y); + ctx.moveTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); } } if (currentStyleFirstItem !== currentItem || currentStyleFirstItem === currentItem && lineType === LineType.WithSteps) { - finishStyledArea(ctx, currentStyle, currentStyleFirstItem, currentItem); + finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); + } + + let prevStyle: TStyle | null = null; + + if (pointMarkersRadius) { + const tickWidth = Math.max(1, Math.floor(horizontalPixelRatio)); + const correction = (tickWidth % 2) / 2; + + const radius = pointMarkersRadius * verticalPixelRatio + correction; + for (let i = visibleRange.to - 1; i >= visibleRange.from; --i) { + const point = items[i]; + if (point) { + const style = styleGetter(renderingScope, point); + if (style !== prevStyle) { + ctx.beginPath(); + if (prevStyle !== null) { + ctx.fill(); + } + + ctx.fillStyle = style; + prevStyle = style; + } + + const centerX = Math.round(point.x * horizontalPixelRatio) + correction; // correct x coordinate only + const centerY = point.y * verticalPixelRatio; + + ctx.moveTo(centerX, centerY); + ctx.arc(centerX, centerY, radius, 0, Math.PI * 2); + } + } + + ctx.fill(); } } diff --git a/src/views/pane/baseline-pane-view.ts b/src/views/pane/baseline-pane-view.ts index f14fb7d16f..c3a7fe19f7 100644 --- a/src/views/pane/baseline-pane-view.ts +++ b/src/views/pane/baseline-pane-view.ts @@ -32,17 +32,17 @@ export class SeriesBaselinePaneView extends LinePaneViewBase<'Baseline', Baselin return; } - const baselineProps = this._series.options(); + const options = this._series.options(); - const baseLevelCoordinate = this._series.priceScale().priceToCoordinate(baselineProps.baseValue.price, firstValue.value); + const baseLevelCoordinate = this._series.priceScale().priceToCoordinate(options.baseValue.price, firstValue.value); const barWidth = this._model.timeScale().barSpacing(); this._baselineAreaRenderer.setData({ items: this._items, - lineWidth: baselineProps.lineWidth, - lineStyle: baselineProps.lineStyle, - lineType: baselineProps.lineType, + lineWidth: options.lineWidth, + lineStyle: options.lineStyle, + lineType: options.lineType, baseLevelCoordinate, invertFilledArea: false, @@ -54,9 +54,10 @@ export class SeriesBaselinePaneView extends LinePaneViewBase<'Baseline', Baselin this._baselineLineRenderer.setData({ items: this._items, - lineWidth: baselineProps.lineWidth, - lineStyle: baselineProps.lineStyle, - lineType: baselineProps.lineType, + lineWidth: options.lineWidth, + lineStyle: options.lineStyle, + lineType: options.lineType, + pointMarkersRadius: options.pointMarkersVisible ? (options.pointMarkersRadius || options.lineWidth / 2 + 2) : undefined, baseLevelCoordinate, diff --git a/src/views/pane/line-pane-view.ts b/src/views/pane/line-pane-view.ts index 6a1d730025..265e2211e9 100644 --- a/src/views/pane/line-pane-view.ts +++ b/src/views/pane/line-pane-view.ts @@ -16,13 +16,14 @@ export class SeriesLinePaneView extends LinePaneViewBase<'Line', LineStrokeItem, } protected _prepareRendererData(): void { - const lineStyleProps = this._series.options(); + const options = this._series.options(); const data: PaneRendererLineData = { items: this._items, - lineStyle: lineStyleProps.lineStyle, - lineType: lineStyleProps.lineType, - lineWidth: lineStyleProps.lineWidth, + lineStyle: options.lineStyle, + lineType: options.lineType, + lineWidth: options.lineWidth, + pointMarkersRadius: options.pointMarkersVisible ? (options.pointMarkersRadius || options.lineWidth / 2 + 2) : undefined, visibleRange: this._itemsVisibleRange, barWidth: this._model.timeScale().barSpacing(), }; diff --git a/tests/e2e/graphics/test-cases/series/area-with-point-markers.js b/tests/e2e/graphics/test-cases/series/area-with-point-markers.js new file mode 100644 index 0000000000..9bb317f3cc --- /dev/null +++ b/tests/e2e/graphics/test-cases/series/area-with-point-markers.js @@ -0,0 +1,21 @@ +function generateData() { + const res = []; + const time = new Date(Date.UTC(2018, 0, 1, 0, 0, 0, 0)); + for (let i = 0; i < 500; ++i) { + res.push({ + time: time.getTime() / 1000, + value: i, + }); + + time.setUTCDate(time.getUTCDate() + 1); + } + return res; +} + +function runTestCase(container) { + const chart = window.chart = LightweightCharts.createChart(container); + + const mainSeries = chart.addAreaSeries({ pointMarkersVisible: true }); + + mainSeries.setData(generateData()); +} diff --git a/tests/e2e/graphics/test-cases/series/baseline-with-point-markers.js b/tests/e2e/graphics/test-cases/series/baseline-with-point-markers.js new file mode 100644 index 0000000000..48a99540c8 --- /dev/null +++ b/tests/e2e/graphics/test-cases/series/baseline-with-point-markers.js @@ -0,0 +1,57 @@ +function generateData() { + const res = []; + const time = new Date(Date.UTC(2018, 0, 1, 0, 0, 0, 0)); + for (let i = 0; i < 50; ++i) { + res.push({ + time: time.getTime() / 1000, + value: i * (-1), + }); + + time.setUTCDate(time.getUTCDate() + 1); + } + + for (let i = 0; i < 100; ++i) { + res.push({ + time: time.getTime() / 1000, + value: -50 + i, + }); + + time.setUTCDate(time.getUTCDate() + 1); + } + + for (let i = 0; i < 100; ++i) { + res.push({ + time: time.getTime() / 1000, + value: 50 - i, + }); + + time.setUTCDate(time.getUTCDate() + 1); + } + + for (let i = 0; i < 100; ++i) { + res.push({ + time: time.getTime() / 1000, + value: -50 + i, + }); + + time.setUTCDate(time.getUTCDate() + 1); + } + return res; +} + +function runTestCase(container) { + const chart = window.chart = LightweightCharts.createChart(container); + + const mainSeries = chart.addBaselineSeries({ + lineWidth: 1, + baseValue: { + type: 'price', + price: 0, + }, + pointMarkersVisible: true, + }); + + chart.timeScale().fitContent(); + + mainSeries.setData(generateData()); +} diff --git a/tests/e2e/graphics/test-cases/series/line-with-point-markers.js b/tests/e2e/graphics/test-cases/series/line-with-point-markers.js new file mode 100644 index 0000000000..4886cc0691 --- /dev/null +++ b/tests/e2e/graphics/test-cases/series/line-with-point-markers.js @@ -0,0 +1,25 @@ +function generateData() { + const res = []; + const time = new Date(Date.UTC(2018, 0, 1, 0, 0, 0, 0)); + for (let i = 0; i < 500; ++i) { + res.push({ + time: time.getTime() / 1000, + value: i, + }); + + time.setUTCDate(time.getUTCDate() + 1); + } + return res; +} + +function runTestCase(container) { + const chart = window.chart = LightweightCharts.createChart(container); + + const mainSeries = chart.addLineSeries({ + lineWidth: 1, + color: '#ff0000', + pointMarkersVisible: true, + }); + + mainSeries.setData(generateData()); +} From 7d25d5dfe05852e72a6e6451c4a22496e6940f03 Mon Sep 17 00:00:00 2001 From: Kirill Chetverikov Date: Mon, 24 Apr 2023 15:22:01 +0300 Subject: [PATCH 02/14] Fixed point markers on area series --- src/views/pane/area-pane-view.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/views/pane/area-pane-view.ts b/src/views/pane/area-pane-view.ts index 6593abb213..e6cc1f0bec 100644 --- a/src/views/pane/area-pane-view.ts +++ b/src/views/pane/area-pane-view.ts @@ -27,26 +27,27 @@ export class SeriesAreaPaneView extends LinePaneViewBase<'Area', AreaFillItem & } protected _prepareRendererData(): void { - const areaStyleProperties = this._series.options(); + const options = this._series.options(); this._areaRenderer.setData({ - lineType: areaStyleProperties.lineType, + lineType: options.lineType, items: this._items, - lineStyle: areaStyleProperties.lineStyle, - lineWidth: areaStyleProperties.lineWidth, + lineStyle: options.lineStyle, + lineWidth: options.lineWidth, baseLevelCoordinate: null, - invertFilledArea: areaStyleProperties.invertFilledArea, + invertFilledArea: options.invertFilledArea, visibleRange: this._itemsVisibleRange, barWidth: this._model.timeScale().barSpacing(), }); this._lineRenderer.setData({ - lineType: areaStyleProperties.lineType, + lineType: options.lineType, items: this._items, - lineStyle: areaStyleProperties.lineStyle, - lineWidth: areaStyleProperties.lineWidth, + lineStyle: options.lineStyle, + lineWidth: options.lineWidth, visibleRange: this._itemsVisibleRange, barWidth: this._model.timeScale().barSpacing(), + pointMarkersRadius: options.pointMarkersVisible ? (options.pointMarkersRadius || options.lineWidth / 2 + 2) : undefined, }); } } From cb259a434e80000ba7a8e4e912b3de946f5b5d7e Mon Sep 17 00:00:00 2001 From: Kirill Chetverikov Date: Mon, 24 Apr 2023 15:38:04 +0300 Subject: [PATCH 03/14] Added possibility to hide line-based series line --- src/api/options/series-options-defaults.ts | 3 + src/model/series-options.ts | 21 ++++ src/renderers/line-renderer-base.ts | 2 +- src/renderers/walk-line.ts | 112 +++++++++--------- src/views/pane/area-pane-view.ts | 2 +- src/views/pane/baseline-pane-view.ts | 2 +- src/views/pane/line-pane-view.ts | 2 +- ...ries-with-point-markers-and-hidden-line.js | 26 ++++ 8 files changed, 111 insertions(+), 59 deletions(-) create mode 100644 tests/e2e/graphics/test-cases/series/line-series-with-point-markers-and-hidden-line.js diff --git a/src/api/options/series-options-defaults.ts b/src/api/options/series-options-defaults.ts index ea8779b7b2..36bfec967e 100644 --- a/src/api/options/series-options-defaults.ts +++ b/src/api/options/series-options-defaults.ts @@ -36,6 +36,7 @@ export const lineStyleDefaults: LineStyleOptions = { lineStyle: LineStyle.Solid, lineWidth: 3, lineType: LineType.Simple, + lineVisible: true, crosshairMarkerVisible: true, crosshairMarkerRadius: 4, crosshairMarkerBorderColor: '', @@ -53,6 +54,7 @@ export const areaStyleDefaults: AreaStyleOptions = { lineStyle: LineStyle.Solid, lineWidth: 3, lineType: LineType.Simple, + lineVisible: true, crosshairMarkerVisible: true, crosshairMarkerRadius: 4, crosshairMarkerBorderColor: '', @@ -79,6 +81,7 @@ export const baselineStyleDefaults: BaselineStyleOptions = { lineWidth: 3, lineStyle: LineStyle.Solid, lineType: LineType.Simple, + lineVisible: true, crosshairMarkerVisible: true, crosshairMarkerRadius: 4, diff --git a/src/model/series-options.ts b/src/model/series-options.ts index 0ef7357061..1f54e6ddcb 100644 --- a/src/model/series-options.ts +++ b/src/model/series-options.ts @@ -174,6 +174,13 @@ export interface LineStyleOptions { */ lineType: LineType; + /** + * Show series line. + * + * @defaultValue `true` + */ + lineVisible: boolean; + /** * Show circle markers on each point. * @@ -279,6 +286,13 @@ export interface AreaStyleOptions { */ lineType: LineType; + /** + * Show series line. + * + * @defaultValue `true` + */ + lineVisible: boolean; + /** * Show circle markers on each point. * @@ -419,6 +433,13 @@ export interface BaselineStyleOptions { */ lineType: LineType; + /** + * Show series line. + * + * @defaultValue `true` + */ + lineVisible: boolean; + /** * Show circle markers on each point. * diff --git a/src/renderers/line-renderer-base.ts b/src/renderers/line-renderer-base.ts index b38fb36f48..23e46d19ca 100644 --- a/src/renderers/line-renderer-base.ts +++ b/src/renderers/line-renderer-base.ts @@ -10,7 +10,7 @@ import { walkLine } from './walk-line'; export type LineItemBase = TimedValue & PricedValue & LinePoint; export interface PaneRendererLineDataBase { - lineType: LineType; + lineType?: LineType; items: TItem[]; diff --git a/src/renderers/walk-line.ts b/src/renderers/walk-line.ts index 34b34c2ea8..85cff415ff 100644 --- a/src/renderers/walk-line.ts +++ b/src/renderers/walk-line.ts @@ -9,7 +9,7 @@ import { LinePoint, LineType } from './draw-line'; export function walkLine( renderingScope: BitmapCoordinatesRenderingScope, items: readonly TItem[], - lineType: LineType, + lineType: LineType | undefined, pointMarkersRadius: number | undefined, visibleRange: SeriesItemsIndexesRange, barWidth: number, @@ -24,81 +24,83 @@ export function walkLine { - finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); + return; + } - ctx.beginPath(); - currentStyle = newStyle; - currentStyleFirstItem = currentItem; - }; + const changeStyle = (newStyle: TStyle, currentItem: TItem) => { + finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); - let currentItem = currentStyleFirstItem; + ctx.beginPath(); + currentStyle = newStyle; + currentStyleFirstItem = currentItem; + }; - ctx.beginPath(); - ctx.moveTo(firstItem.x * horizontalPixelRatio, firstItem.y * verticalPixelRatio); + let currentItem = currentStyleFirstItem; - for (let i = visibleRange.from + 1; i < visibleRange.to; ++i) { - currentItem = items[i]; - const itemStyle = styleGetter(renderingScope, currentItem); + ctx.beginPath(); + ctx.moveTo(firstItem.x * horizontalPixelRatio, firstItem.y * verticalPixelRatio); - switch (lineType) { - case LineType.Simple: - ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); - break; - case LineType.WithSteps: - ctx.lineTo(currentItem.x * horizontalPixelRatio, items[i - 1].y * verticalPixelRatio); + for (let i = visibleRange.from + 1; i < visibleRange.to; ++i) { + currentItem = items[i]; + const itemStyle = styleGetter(renderingScope, currentItem); - if (itemStyle !== currentStyle) { - changeStyle(itemStyle, currentItem); + switch (lineType) { + case LineType.Simple: + ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); + break; + case LineType.WithSteps: ctx.lineTo(currentItem.x * horizontalPixelRatio, items[i - 1].y * verticalPixelRatio); + + if (itemStyle !== currentStyle) { + changeStyle(itemStyle, currentItem); + ctx.lineTo(currentItem.x * horizontalPixelRatio, items[i - 1].y * verticalPixelRatio); + } + + ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); + break; + case LineType.Curved: { + const [cp1, cp2] = getControlPoints(items, i - 1, i); + ctx.bezierCurveTo( + cp1.x * horizontalPixelRatio, + cp1.y * verticalPixelRatio, + cp2.x * horizontalPixelRatio, + cp2.y * verticalPixelRatio, + currentItem.x * horizontalPixelRatio, + currentItem.y * verticalPixelRatio + ); + break; } + } - ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); - break; - case LineType.Curved: { - const [cp1, cp2] = getControlPoints(items, i - 1, i); - ctx.bezierCurveTo( - cp1.x * horizontalPixelRatio, - cp1.y * verticalPixelRatio, - cp2.x * horizontalPixelRatio, - cp2.y * verticalPixelRatio, - currentItem.x * horizontalPixelRatio, - currentItem.y * verticalPixelRatio - ); - break; + if (lineType !== LineType.WithSteps && itemStyle !== currentStyle) { + changeStyle(itemStyle, currentItem); + ctx.moveTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); } } - if (lineType !== LineType.WithSteps && itemStyle !== currentStyle) { - changeStyle(itemStyle, currentItem); - ctx.moveTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); + if (currentStyleFirstItem !== currentItem || currentStyleFirstItem === currentItem && lineType === LineType.WithSteps) { + finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); } } - if (currentStyleFirstItem !== currentItem || currentStyleFirstItem === currentItem && lineType === LineType.WithSteps) { - finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); - } - let prevStyle: TStyle | null = null; if (pointMarkersRadius) { diff --git a/src/views/pane/area-pane-view.ts b/src/views/pane/area-pane-view.ts index e6cc1f0bec..27daba1b38 100644 --- a/src/views/pane/area-pane-view.ts +++ b/src/views/pane/area-pane-view.ts @@ -41,7 +41,7 @@ export class SeriesAreaPaneView extends LinePaneViewBase<'Area', AreaFillItem & }); this._lineRenderer.setData({ - lineType: options.lineType, + lineType: options.lineVisible ? options.lineType : undefined, items: this._items, lineStyle: options.lineStyle, lineWidth: options.lineWidth, diff --git a/src/views/pane/baseline-pane-view.ts b/src/views/pane/baseline-pane-view.ts index c3a7fe19f7..d86499c49f 100644 --- a/src/views/pane/baseline-pane-view.ts +++ b/src/views/pane/baseline-pane-view.ts @@ -56,7 +56,7 @@ export class SeriesBaselinePaneView extends LinePaneViewBase<'Baseline', Baselin lineWidth: options.lineWidth, lineStyle: options.lineStyle, - lineType: options.lineType, + lineType: options.lineVisible ? options.lineType : undefined, pointMarkersRadius: options.pointMarkersVisible ? (options.pointMarkersRadius || options.lineWidth / 2 + 2) : undefined, baseLevelCoordinate, diff --git a/src/views/pane/line-pane-view.ts b/src/views/pane/line-pane-view.ts index 265e2211e9..2c72f14f65 100644 --- a/src/views/pane/line-pane-view.ts +++ b/src/views/pane/line-pane-view.ts @@ -21,7 +21,7 @@ export class SeriesLinePaneView extends LinePaneViewBase<'Line', LineStrokeItem, const data: PaneRendererLineData = { items: this._items, lineStyle: options.lineStyle, - lineType: options.lineType, + lineType: options.lineVisible ? options.lineType : undefined, lineWidth: options.lineWidth, pointMarkersRadius: options.pointMarkersVisible ? (options.pointMarkersRadius || options.lineWidth / 2 + 2) : undefined, visibleRange: this._itemsVisibleRange, diff --git a/tests/e2e/graphics/test-cases/series/line-series-with-point-markers-and-hidden-line.js b/tests/e2e/graphics/test-cases/series/line-series-with-point-markers-and-hidden-line.js new file mode 100644 index 0000000000..9697dfa3c5 --- /dev/null +++ b/tests/e2e/graphics/test-cases/series/line-series-with-point-markers-and-hidden-line.js @@ -0,0 +1,26 @@ +function generateData() { + const res = []; + const time = new Date(Date.UTC(2018, 0, 1, 0, 0, 0, 0)); + for (let i = 0; i < 500; ++i) { + res.push({ + time: time.getTime() / 1000, + value: i, + }); + + time.setUTCDate(time.getUTCDate() + 1); + } + return res; +} + +function runTestCase(container) { + const chart = window.chart = LightweightCharts.createChart(container); + + const mainSeries = chart.addLineSeries({ + lineWidth: 1, + color: '#ff0000', + pointMarkersVisible: true, + lineVisible: false, + }); + + mainSeries.setData(generateData()); +} From b3822857a5a22014386fc1fa8b3dba9c7e16b3d2 Mon Sep 17 00:00:00 2001 From: Kirill Chetverikov Date: Mon, 24 Apr 2023 18:54:32 +0300 Subject: [PATCH 04/14] Fixed graphics tests --- src/renderers/baseline-renderer-area.ts | 4 ++-- src/renderers/baseline-renderer-line.ts | 4 ++-- src/renderers/line-renderer-base.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/renderers/baseline-renderer-area.ts b/src/renderers/baseline-renderer-area.ts index fd304330be..32e3e7bffd 100644 --- a/src/renderers/baseline-renderer-area.ts +++ b/src/renderers/baseline-renderer-area.ts @@ -20,7 +20,7 @@ export class PaneRendererBaselineArea extends PaneRendererAreaBase Date: Mon, 24 Apr 2023 19:36:51 +0300 Subject: [PATCH 05/14] Increased size limits --- .size-limit.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.size-limit.js b/.size-limit.js index cc8406295f..357560871d 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -4,21 +4,21 @@ module.exports = [ { name: 'CJS', path: 'dist/lightweight-charts.production.cjs', - limit: '44.46 KB', + limit: '44.7 KB', }, { name: 'ESM', path: 'dist/lightweight-charts.production.mjs', - limit: '44.38 KB', + limit: '44.65 KB', }, { name: 'Standalone-ESM', path: 'dist/lightweight-charts.standalone.production.mjs', - limit: '46.08 KB', + limit: '46.35 KB', }, { name: 'Standalone', path: 'dist/lightweight-charts.standalone.production.js', - limit: '46.13 KB', + limit: '46.4 KB', }, ]; From 23b1646d0db275ca39f1ed647677ad53220b8d6d Mon Sep 17 00:00:00 2001 From: Kirill Chetverikov Date: Mon, 24 Apr 2023 20:32:31 +0300 Subject: [PATCH 06/14] Increased size limits one more time Co-authored-by: Mark Silverwood --- .size-limit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.size-limit.js b/.size-limit.js index 357560871d..ebf8733624 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -4,7 +4,7 @@ module.exports = [ { name: 'CJS', path: 'dist/lightweight-charts.production.cjs', - limit: '44.7 KB', + limit: '44.75 KB', }, { name: 'ESM', From 986537b3d7062f875ea622e5f2a1a9c92f59c778 Mon Sep 17 00:00:00 2001 From: Kirill Chetverikov Date: Tue, 25 Apr 2023 19:05:29 +0300 Subject: [PATCH 07/14] Fixed painting markers on series with one visible point --- src/renderers/walk-line.ts | 86 +++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/src/renderers/walk-line.ts b/src/renderers/walk-line.ts index 85cff415ff..692f6ad29f 100644 --- a/src/renderers/walk-line.ts +++ b/src/renderers/walk-line.ts @@ -41,64 +41,62 @@ export function walkLine { + finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); - return; - } + ctx.beginPath(); + currentStyle = newStyle; + currentStyleFirstItem = currentItem; + }; - const changeStyle = (newStyle: TStyle, currentItem: TItem) => { - finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); + let currentItem = currentStyleFirstItem; ctx.beginPath(); - currentStyle = newStyle; - currentStyleFirstItem = currentItem; - }; - - let currentItem = currentStyleFirstItem; - - ctx.beginPath(); - ctx.moveTo(firstItem.x * horizontalPixelRatio, firstItem.y * verticalPixelRatio); - - for (let i = visibleRange.from + 1; i < visibleRange.to; ++i) { - currentItem = items[i]; - const itemStyle = styleGetter(renderingScope, currentItem); + ctx.moveTo(firstItem.x * horizontalPixelRatio, firstItem.y * verticalPixelRatio); - switch (lineType) { - case LineType.Simple: - ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); - break; - case LineType.WithSteps: - ctx.lineTo(currentItem.x * horizontalPixelRatio, items[i - 1].y * verticalPixelRatio); + for (let i = visibleRange.from + 1; i < visibleRange.to; ++i) { + currentItem = items[i]; + const itemStyle = styleGetter(renderingScope, currentItem); - if (itemStyle !== currentStyle) { - changeStyle(itemStyle, currentItem); + switch (lineType) { + case LineType.Simple: + ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); + break; + case LineType.WithSteps: ctx.lineTo(currentItem.x * horizontalPixelRatio, items[i - 1].y * verticalPixelRatio); + + if (itemStyle !== currentStyle) { + changeStyle(itemStyle, currentItem); + ctx.lineTo(currentItem.x * horizontalPixelRatio, items[i - 1].y * verticalPixelRatio); + } + + ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); + break; + case LineType.Curved: { + const [cp1, cp2] = getControlPoints(items, i - 1, i); + ctx.bezierCurveTo( + cp1.x * horizontalPixelRatio, + cp1.y * verticalPixelRatio, + cp2.x * horizontalPixelRatio, + cp2.y * verticalPixelRatio, + currentItem.x * horizontalPixelRatio, + currentItem.y * verticalPixelRatio + ); + break; } + } - ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); - break; - case LineType.Curved: { - const [cp1, cp2] = getControlPoints(items, i - 1, i); - ctx.bezierCurveTo( - cp1.x * horizontalPixelRatio, - cp1.y * verticalPixelRatio, - cp2.x * horizontalPixelRatio, - cp2.y * verticalPixelRatio, - currentItem.x * horizontalPixelRatio, - currentItem.y * verticalPixelRatio - ); - break; + if (lineType !== LineType.WithSteps && itemStyle !== currentStyle) { + changeStyle(itemStyle, currentItem); + ctx.moveTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); } } - if (lineType !== LineType.WithSteps && itemStyle !== currentStyle) { - changeStyle(itemStyle, currentItem); - ctx.moveTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); + if (currentStyleFirstItem !== currentItem || currentStyleFirstItem === currentItem && lineType === LineType.WithSteps) { + finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); } } - - if (currentStyleFirstItem !== currentItem || currentStyleFirstItem === currentItem && lineType === LineType.WithSteps) { - finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); - } } let prevStyle: TStyle | null = null; From 68282cd904a90653184dbd9afc7e94bde337cad1 Mon Sep 17 00:00:00 2001 From: Kirill Chetverikov Date: Tue, 25 Apr 2023 20:57:19 +0300 Subject: [PATCH 08/14] Area renderers refactoring --- src/renderers/area-renderer.ts | 39 +++++------------ src/renderers/baseline-renderer-area.ts | 58 ++++++------------------- src/renderers/baseline-renderer-line.ts | 54 ++++++----------------- src/renderers/gradient-style-cache.ts | 48 ++++++++++++++++++++ 4 files changed, 86 insertions(+), 113 deletions(-) create mode 100644 src/renderers/gradient-style-cache.ts diff --git a/src/renderers/area-renderer.ts b/src/renderers/area-renderer.ts index 66ab386c86..62f82eeda4 100644 --- a/src/renderers/area-renderer.ts +++ b/src/renderers/area-renderer.ts @@ -4,40 +4,25 @@ import { Coordinate } from '../model/coordinate'; import { AreaFillColorerStyle } from '../model/series-bar-colorer'; import { AreaFillItemBase, PaneRendererAreaBase, PaneRendererAreaDataBase } from './area-renderer-base'; +import { GradientStyleCache } from './gradient-style-cache'; export type AreaFillItem = AreaFillItemBase & AreaFillColorerStyle; export interface PaneRendererAreaData extends PaneRendererAreaDataBase { } -interface AreaFillCache extends Record { - fillStyle: CanvasRenderingContext2D['fillStyle']; - bottom: Coordinate; -} - export class PaneRendererArea extends PaneRendererAreaBase { - private _fillCache: AreaFillCache | null = null; + private readonly _fillCache: GradientStyleCache = new GradientStyleCache(); protected override _fillStyle(renderingScope: BitmapCoordinatesRenderingScope, item: AreaFillItem): CanvasRenderingContext2D['fillStyle'] { - const { context: ctx, bitmapSize } = renderingScope; - - const { topColor, bottomColor } = item; - const bottom = bitmapSize.height as Coordinate; - - if ( - this._fillCache !== null && - this._fillCache.topColor === topColor && - this._fillCache.bottomColor === bottomColor && - this._fillCache.bottom === bottom - ) { - return this._fillCache.fillStyle; - } - - const fillStyle = ctx.createLinearGradient(0, 0, 0, bottom); - fillStyle.addColorStop(0, topColor); - fillStyle.addColorStop(1, bottomColor); - - this._fillCache = { topColor, bottomColor, fillStyle, bottom }; - - return fillStyle; + return this._fillCache.get( + renderingScope, + { + topColor1: item.topColor, + topColor2: '', + bottomColor1: '', + bottomColor2: item.bottomColor, + bottom: renderingScope.bitmapSize.height as Coordinate, + } + ); } } diff --git a/src/renderers/baseline-renderer-area.ts b/src/renderers/baseline-renderer-area.ts index 32e3e7bffd..369bbc8ca0 100644 --- a/src/renderers/baseline-renderer-area.ts +++ b/src/renderers/baseline-renderer-area.ts @@ -1,63 +1,31 @@ import { BitmapCoordinatesRenderingScope } from 'fancy-canvas'; -import { clamp } from '../helpers/mathex'; - import { Coordinate } from '../model/coordinate'; import { BaselineFillColorerStyle } from '../model/series-bar-colorer'; import { AreaFillItemBase, PaneRendererAreaBase, PaneRendererAreaDataBase } from './area-renderer-base'; +import { GradientStyleCache } from './gradient-style-cache'; export type BaselineFillItem = AreaFillItemBase & BaselineFillColorerStyle; export interface PaneRendererBaselineData extends PaneRendererAreaDataBase { } - -interface BaselineFillCache extends Record { - fillStyle: CanvasRenderingContext2D['fillStyle']; - baseLevelCoordinate: Coordinate; - bottom: Coordinate; -} export class PaneRendererBaselineArea extends PaneRendererAreaBase { - private _fillCache: BaselineFillCache | null = null; + private readonly _fillCache: GradientStyleCache = new GradientStyleCache(); protected override _fillStyle(renderingScope: BitmapCoordinatesRenderingScope, item: BaselineFillItem): CanvasRenderingContext2D['fillStyle'] { - const { context: ctx, bitmapSize, verticalPixelRatio } = renderingScope; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const data = this._data!; - const { topFillColor1, topFillColor2, bottomFillColor1, bottomFillColor2 } = item; - const baseLevelCoordinate = data.baseLevelCoordinate ?? bitmapSize.height as Coordinate; - const bottom = bitmapSize.height as Coordinate; - - if ( - this._fillCache !== null && - this._fillCache.topFillColor1 === topFillColor1 && - this._fillCache.topFillColor2 === topFillColor2 && - this._fillCache.bottomFillColor1 === bottomFillColor1 && - this._fillCache.bottomFillColor2 === bottomFillColor2 && - this._fillCache.baseLevelCoordinate === baseLevelCoordinate && - this._fillCache.bottom === bottom - ) { - return this._fillCache.fillStyle; - } - - const fillStyle = ctx.createLinearGradient(0, 0, 0, bottom); - const baselinePercent = clamp(baseLevelCoordinate * verticalPixelRatio / bottom, 0, 1); - - fillStyle.addColorStop(0, topFillColor1); - fillStyle.addColorStop(baselinePercent, topFillColor2); - fillStyle.addColorStop(baselinePercent, bottomFillColor1); - fillStyle.addColorStop(1, bottomFillColor2); - - this._fillCache = { - topFillColor1, - topFillColor2, - bottomFillColor1, - bottomFillColor2, - fillStyle, - baseLevelCoordinate, - bottom, - }; - - return fillStyle; + return this._fillCache.get( + renderingScope, + { + topColor1: item.topFillColor1, + topColor2: item.topFillColor2, + bottomColor1: item.bottomFillColor1, + bottomColor2: item.bottomFillColor2, + bottom: renderingScope.bitmapSize.height as Coordinate, + baseLevelCoordinate: data.baseLevelCoordinate, + } + ); } } diff --git a/src/renderers/baseline-renderer-line.ts b/src/renderers/baseline-renderer-line.ts index 8948099b61..2625846df8 100644 --- a/src/renderers/baseline-renderer-line.ts +++ b/src/renderers/baseline-renderer-line.ts @@ -1,61 +1,33 @@ import { BitmapCoordinatesRenderingScope } from 'fancy-canvas'; -import { clamp } from '../helpers/mathex'; - import { Coordinate } from '../model/coordinate'; import { BaselineStrokeColorerStyle } from '../model/series-bar-colorer'; import { LineItemBase as LineStrokeItemBase, PaneRendererLineBase, PaneRendererLineDataBase } from './line-renderer-base'; +import { GradientStyleCache } from './gradient-style-cache'; export type BaselineStrokeItem = LineStrokeItemBase & BaselineStrokeColorerStyle; export interface PaneRendererBaselineLineData extends PaneRendererLineDataBase { baseLevelCoordinate: Coordinate; } -interface BaselineStrokeCache extends Record { - strokeStyle: CanvasRenderingContext2D['strokeStyle']; - baseLevelCoordinate: Coordinate; - bottom: Coordinate; -} - export class PaneRendererBaselineLine extends PaneRendererLineBase { - private _strokeCache: BaselineStrokeCache | null = null; + private readonly _strokeCache: GradientStyleCache = new GradientStyleCache(); protected override _strokeStyle(renderingScope: BitmapCoordinatesRenderingScope, item: BaselineStrokeItem): CanvasRenderingContext2D['strokeStyle'] { - const { context: ctx, bitmapSize, verticalPixelRatio } = renderingScope; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const data = this._data!; - const { topLineColor, bottomLineColor } = item; - const { baseLevelCoordinate } = data; - const bottom = bitmapSize.height as Coordinate; - - if ( - this._strokeCache !== null && - this._strokeCache.topLineColor === topLineColor && - this._strokeCache.bottomLineColor === bottomLineColor && - this._strokeCache.baseLevelCoordinate === baseLevelCoordinate && - this._strokeCache.bottom === bottom - ) { - return this._strokeCache.strokeStyle; - } - - const strokeStyle = ctx.createLinearGradient(0, 0, 0, bottom); - const baselinePercent = clamp(baseLevelCoordinate * verticalPixelRatio / bottom, 0, 1); - - strokeStyle.addColorStop(0, topLineColor); - strokeStyle.addColorStop(baselinePercent, topLineColor); - strokeStyle.addColorStop(baselinePercent, bottomLineColor); - strokeStyle.addColorStop(1, bottomLineColor); - - this._strokeCache = { - topLineColor, - bottomLineColor, - strokeStyle, - baseLevelCoordinate, - bottom, - }; - - return strokeStyle; + return this._strokeCache.get( + renderingScope, + { + topColor1: item.topLineColor, + topColor2: item.topLineColor, + bottomColor1: item.bottomLineColor, + bottomColor2: item.bottomLineColor, + bottom: renderingScope.bitmapSize.height as Coordinate, + baseLevelCoordinate: data.baseLevelCoordinate, + } + ); } } diff --git a/src/renderers/gradient-style-cache.ts b/src/renderers/gradient-style-cache.ts new file mode 100644 index 0000000000..2bbbbd97d8 --- /dev/null +++ b/src/renderers/gradient-style-cache.ts @@ -0,0 +1,48 @@ +import { BitmapCoordinatesRenderingScope } from "fancy-canvas"; +import { Coordinate } from "../model/coordinate"; +import { clamp } from "../helpers/mathex"; + +export interface GradientCacheParams { + topColor1: string + topColor2: string; + bottomColor1: string; + bottomColor2: string; + baseLevelCoordinate?: Coordinate | null; + bottom: Coordinate; +} + +export class GradientStyleCache { + private _params?: GradientCacheParams; + private _cachedValue?: CanvasGradient; + + public get(scope: BitmapCoordinatesRenderingScope, params:GradientCacheParams ): CanvasGradient { + const cachedParams = this._params; + if ( + this._cachedValue === undefined || + cachedParams === undefined || + cachedParams.topColor1 !== params.topColor1 || + cachedParams.topColor2 !== params.topColor2 || + cachedParams.bottomColor1 !== params.bottomColor1 || + cachedParams.bottomColor2 !== params.bottomColor2 || + cachedParams.baseLevelCoordinate !== params.baseLevelCoordinate || + cachedParams.bottom !== params.bottom + ) { + const gradient = scope.context.createLinearGradient(0, 0, 0, params.bottom); + + gradient.addColorStop(0, params.topColor1); + + if (params.baseLevelCoordinate != null) { + const baselinePercent = clamp(params.baseLevelCoordinate * scope.verticalPixelRatio / params.bottom, 0, 1); + gradient.addColorStop(baselinePercent, params.topColor2); + gradient.addColorStop(baselinePercent, params.bottomColor1); + } + + gradient.addColorStop(1, params.bottomColor2); + + this._cachedValue = gradient; + this._params = params; + } + + return this._cachedValue; + } +} From af9b729f1f7430c903c93906c67803f0342b60be Mon Sep 17 00:00:00 2001 From: Kirill Chetverikov Date: Tue, 25 Apr 2023 20:59:03 +0300 Subject: [PATCH 09/14] Updated size limits --- .size-limit.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.size-limit.js b/.size-limit.js index ebf8733624..3b7f44a51c 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -4,21 +4,21 @@ module.exports = [ { name: 'CJS', path: 'dist/lightweight-charts.production.cjs', - limit: '44.75 KB', + limit: '44.55 KB', }, { name: 'ESM', path: 'dist/lightweight-charts.production.mjs', - limit: '44.65 KB', + limit: '44.5 KB', }, { name: 'Standalone-ESM', path: 'dist/lightweight-charts.standalone.production.mjs', - limit: '46.35 KB', + limit: '46.2 KB', }, { name: 'Standalone', path: 'dist/lightweight-charts.standalone.production.js', - limit: '46.4 KB', + limit: '46.25 KB', }, ]; From dc3e6c5b11dd3817ec7aa5ce56864c10a934569f Mon Sep 17 00:00:00 2001 From: Kirill Chetverikov Date: Tue, 25 Apr 2023 21:09:06 +0300 Subject: [PATCH 10/14] Fixed ESLint & small refactoring --- src/renderers/gradient-style-cache.ts | 36 +++++++++++++++------------ 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/renderers/gradient-style-cache.ts b/src/renderers/gradient-style-cache.ts index 2bbbbd97d8..f2b536fcc3 100644 --- a/src/renderers/gradient-style-cache.ts +++ b/src/renderers/gradient-style-cache.ts @@ -1,6 +1,8 @@ -import { BitmapCoordinatesRenderingScope } from "fancy-canvas"; -import { Coordinate } from "../model/coordinate"; -import { clamp } from "../helpers/mathex"; +import { BitmapCoordinatesRenderingScope } from 'fancy-canvas'; + +import { clamp } from '../helpers/mathex'; + +import { Coordinate } from '../model/coordinate'; export interface GradientCacheParams { topColor1: string @@ -17,27 +19,29 @@ export class GradientStyleCache { public get(scope: BitmapCoordinatesRenderingScope, params:GradientCacheParams ): CanvasGradient { const cachedParams = this._params; + const { topColor1, topColor2, bottomColor1, bottomColor2, bottom, baseLevelCoordinate } = params; + if ( this._cachedValue === undefined || cachedParams === undefined || - cachedParams.topColor1 !== params.topColor1 || - cachedParams.topColor2 !== params.topColor2 || - cachedParams.bottomColor1 !== params.bottomColor1 || - cachedParams.bottomColor2 !== params.bottomColor2 || - cachedParams.baseLevelCoordinate !== params.baseLevelCoordinate || - cachedParams.bottom !== params.bottom + cachedParams.topColor1 !== topColor1 || + cachedParams.topColor2 !== topColor2 || + cachedParams.bottomColor1 !== bottomColor1 || + cachedParams.bottomColor2 !== bottomColor2 || + cachedParams.baseLevelCoordinate !== baseLevelCoordinate || + cachedParams.bottom !== bottom ) { - const gradient = scope.context.createLinearGradient(0, 0, 0, params.bottom); + const gradient = scope.context.createLinearGradient(0, 0, 0, bottom); - gradient.addColorStop(0, params.topColor1); + gradient.addColorStop(0, topColor1); - if (params.baseLevelCoordinate != null) { - const baselinePercent = clamp(params.baseLevelCoordinate * scope.verticalPixelRatio / params.bottom, 0, 1); - gradient.addColorStop(baselinePercent, params.topColor2); - gradient.addColorStop(baselinePercent, params.bottomColor1); + if (baseLevelCoordinate != null) { + const baselinePercent = clamp(baseLevelCoordinate * scope.verticalPixelRatio / bottom, 0, 1); + gradient.addColorStop(baselinePercent, topColor2); + gradient.addColorStop(baselinePercent, bottomColor1); } - gradient.addColorStop(1, params.bottomColor2); + gradient.addColorStop(1, bottomColor2); this._cachedValue = gradient; this._params = params; From b1ddc972edb9d38cdd996dff751bdcae4b32d9ef Mon Sep 17 00:00:00 2001 From: Kirill Chetverikov Date: Wed, 26 Apr 2023 12:47:22 +0300 Subject: [PATCH 11/14] Fixed ESLint --- src/renderers/baseline-renderer-line.ts | 2 +- src/renderers/gradient-style-cache.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/renderers/baseline-renderer-line.ts b/src/renderers/baseline-renderer-line.ts index 2625846df8..9ca3026f4f 100644 --- a/src/renderers/baseline-renderer-line.ts +++ b/src/renderers/baseline-renderer-line.ts @@ -3,8 +3,8 @@ import { BitmapCoordinatesRenderingScope } from 'fancy-canvas'; import { Coordinate } from '../model/coordinate'; import { BaselineStrokeColorerStyle } from '../model/series-bar-colorer'; -import { LineItemBase as LineStrokeItemBase, PaneRendererLineBase, PaneRendererLineDataBase } from './line-renderer-base'; import { GradientStyleCache } from './gradient-style-cache'; +import { LineItemBase as LineStrokeItemBase, PaneRendererLineBase, PaneRendererLineDataBase } from './line-renderer-base'; export type BaselineStrokeItem = LineStrokeItemBase & BaselineStrokeColorerStyle; export interface PaneRendererBaselineLineData extends PaneRendererLineDataBase { diff --git a/src/renderers/gradient-style-cache.ts b/src/renderers/gradient-style-cache.ts index f2b536fcc3..01d344f792 100644 --- a/src/renderers/gradient-style-cache.ts +++ b/src/renderers/gradient-style-cache.ts @@ -5,7 +5,7 @@ import { clamp } from '../helpers/mathex'; import { Coordinate } from '../model/coordinate'; export interface GradientCacheParams { - topColor1: string + topColor1: string; topColor2: string; bottomColor1: string; bottomColor2: string; @@ -17,7 +17,7 @@ export class GradientStyleCache { private _params?: GradientCacheParams; private _cachedValue?: CanvasGradient; - public get(scope: BitmapCoordinatesRenderingScope, params:GradientCacheParams ): CanvasGradient { + public get(scope: BitmapCoordinatesRenderingScope, params: GradientCacheParams): CanvasGradient { const cachedParams = this._params; const { topColor1, topColor2, bottomColor1, bottomColor2, bottom, baseLevelCoordinate } = params; From 228844d4b5281e40f06d9ac27430036ec30c04e5 Mon Sep 17 00:00:00 2001 From: Kirill Chetverikov Date: Mon, 22 May 2023 15:15:13 +0300 Subject: [PATCH 12/14] Moved painting series point markers logic to a separate module --- src/renderers/area-renderer-base.ts | 2 +- src/renderers/draw-series-point-markers.ts | 46 +++++++ src/renderers/line-renderer-base.ts | 9 +- src/renderers/walk-line.ts | 139 ++++++++------------- 4 files changed, 107 insertions(+), 89 deletions(-) create mode 100644 src/renderers/draw-series-point-markers.ts diff --git a/src/renderers/area-renderer-base.ts b/src/renderers/area-renderer-base.ts index af6f1f1c92..149a8156f4 100644 --- a/src/renderers/area-renderer-base.ts +++ b/src/renderers/area-renderer-base.ts @@ -69,7 +69,7 @@ export abstract class PaneRendererAreaBase( + renderingScope: BitmapCoordinatesRenderingScope, + items: readonly TItem[], + pointMarkersRadius: number, + visibleRange: SeriesItemsIndexesRange, + // the values returned by styleGetter are compared using the operator !==, + // so if styleGetter returns objects, then styleGetter should return the same object for equal styles + styleGetter: (renderingScope: BitmapCoordinatesRenderingScope, item: TItem) => TStyle +): void { + const { horizontalPixelRatio, verticalPixelRatio, context } = renderingScope; + let prevStyle: TStyle | null = null; + + const tickWidth = Math.max(1, Math.floor(horizontalPixelRatio)); + const correction = (tickWidth % 2) / 2; + + const radius = pointMarkersRadius * verticalPixelRatio + correction; + for (let i = visibleRange.to - 1; i >= visibleRange.from; --i) { + const point = items[i]; + if (point) { + const style = styleGetter(renderingScope, point); + if (style !== prevStyle) { + context.beginPath(); + if (prevStyle !== null) { + context.fill(); + } + + context.fillStyle = style; + prevStyle = style; + } + + const centerX = Math.round(point.x * horizontalPixelRatio) + correction; // correct x coordinate only + const centerY = point.y * verticalPixelRatio; + + context.moveTo(centerX, centerY); + context.arc(centerX, centerY, radius, 0, Math.PI * 2); + } + } + + context.fill(); +} diff --git a/src/renderers/line-renderer-base.ts b/src/renderers/line-renderer-base.ts index e23fcffaa1..26f248057c 100644 --- a/src/renderers/line-renderer-base.ts +++ b/src/renderers/line-renderer-base.ts @@ -5,6 +5,7 @@ import { SeriesItemsIndexesRange, TimedValue } from '../model/time-data'; import { BitmapCoordinatesPaneRenderer } from './bitmap-coordinates-pane-renderer'; import { LinePoint, LineStyle, LineType, LineWidth, setLineStyle } from './draw-line'; +import { drawSeriesPointMarkers } from './draw-series-point-markers'; import { walkLine } from './walk-line'; export type LineItemBase = TimedValue & PricedValue & LinePoint; @@ -59,7 +60,13 @@ export abstract class PaneRendererLineBase( renderingScope: BitmapCoordinatesRenderingScope, items: readonly TItem[], - lineType: LineType | undefined, - pointMarkersRadius: number | undefined, + lineType: LineType, visibleRange: SeriesItemsIndexesRange, barWidth: number, // the values returned by styleGetter are compared using the operator !==, @@ -24,111 +23,77 @@ export function walkLine { - finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); + finishStyledArea(renderingScope, currentStyle, item1, item2); + } else { + const changeStyle = (newStyle: TStyle, currentItem: TItem) => { + finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); - ctx.beginPath(); - currentStyle = newStyle; - currentStyleFirstItem = currentItem; - }; + ctx.beginPath(); + currentStyle = newStyle; + currentStyleFirstItem = currentItem; + }; - let currentItem = currentStyleFirstItem; + let currentItem = currentStyleFirstItem; - ctx.beginPath(); - ctx.moveTo(firstItem.x * horizontalPixelRatio, firstItem.y * verticalPixelRatio); + ctx.beginPath(); + ctx.moveTo(firstItem.x * horizontalPixelRatio, firstItem.y * verticalPixelRatio); - for (let i = visibleRange.from + 1; i < visibleRange.to; ++i) { - currentItem = items[i]; - const itemStyle = styleGetter(renderingScope, currentItem); + for (let i = visibleRange.from + 1; i < visibleRange.to; ++i) { + currentItem = items[i]; + const itemStyle = styleGetter(renderingScope, currentItem); - switch (lineType) { - case LineType.Simple: - ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); - break; - case LineType.WithSteps: - ctx.lineTo(currentItem.x * horizontalPixelRatio, items[i - 1].y * verticalPixelRatio); + switch (lineType) { + case LineType.Simple: + ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); + break; + case LineType.WithSteps: + ctx.lineTo(currentItem.x * horizontalPixelRatio, items[i - 1].y * verticalPixelRatio); - if (itemStyle !== currentStyle) { - changeStyle(itemStyle, currentItem); - ctx.lineTo(currentItem.x * horizontalPixelRatio, items[i - 1].y * verticalPixelRatio); - } - - ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); - break; - case LineType.Curved: { - const [cp1, cp2] = getControlPoints(items, i - 1, i); - ctx.bezierCurveTo( - cp1.x * horizontalPixelRatio, - cp1.y * verticalPixelRatio, - cp2.x * horizontalPixelRatio, - cp2.y * verticalPixelRatio, - currentItem.x * horizontalPixelRatio, - currentItem.y * verticalPixelRatio - ); - break; + if (itemStyle !== currentStyle) { + changeStyle(itemStyle, currentItem); + ctx.lineTo(currentItem.x * horizontalPixelRatio, items[i - 1].y * verticalPixelRatio); } - } - if (lineType !== LineType.WithSteps && itemStyle !== currentStyle) { - changeStyle(itemStyle, currentItem); - ctx.moveTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); + ctx.lineTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); + break; + case LineType.Curved: { + const [cp1, cp2] = getControlPoints(items, i - 1, i); + ctx.bezierCurveTo( + cp1.x * horizontalPixelRatio, + cp1.y * verticalPixelRatio, + cp2.x * horizontalPixelRatio, + cp2.y * verticalPixelRatio, + currentItem.x * horizontalPixelRatio, + currentItem.y * verticalPixelRatio + ); + break; } } - if (currentStyleFirstItem !== currentItem || currentStyleFirstItem === currentItem && lineType === LineType.WithSteps) { - finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); + if (lineType !== LineType.WithSteps && itemStyle !== currentStyle) { + changeStyle(itemStyle, currentItem); + ctx.moveTo(currentItem.x * horizontalPixelRatio, currentItem.y * verticalPixelRatio); } } - } - let prevStyle: TStyle | null = null; - - if (pointMarkersRadius) { - const tickWidth = Math.max(1, Math.floor(horizontalPixelRatio)); - const correction = (tickWidth % 2) / 2; - - const radius = pointMarkersRadius * verticalPixelRatio + correction; - for (let i = visibleRange.to - 1; i >= visibleRange.from; --i) { - const point = items[i]; - if (point) { - const style = styleGetter(renderingScope, point); - if (style !== prevStyle) { - ctx.beginPath(); - if (prevStyle !== null) { - ctx.fill(); - } - - ctx.fillStyle = style; - prevStyle = style; - } - - const centerX = Math.round(point.x * horizontalPixelRatio) + correction; // correct x coordinate only - const centerY = point.y * verticalPixelRatio; - - ctx.moveTo(centerX, centerY); - ctx.arc(centerX, centerY, radius, 0, Math.PI * 2); - } + if (currentStyleFirstItem !== currentItem || currentStyleFirstItem === currentItem && lineType === LineType.WithSteps) { + finishStyledArea(renderingScope, currentStyle, currentStyleFirstItem, currentItem); } - - ctx.fill(); } } From c682884eb1ac71def6f49e1e677b7e4d28d9f195 Mon Sep 17 00:00:00 2001 From: Mark Silverwood Date: Mon, 22 May 2023 17:47:35 +0100 Subject: [PATCH 13/14] increased barSpacing on point markers e2e graphics tests --- .../test-cases/series/area-with-point-markers.js | 6 +++++- .../series/baseline-with-point-markers.js | 14 +++++++------- ...ne-series-with-point-markers-and-hidden-line.js | 6 +++++- .../test-cases/series/line-with-point-markers.js | 6 +++++- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/tests/e2e/graphics/test-cases/series/area-with-point-markers.js b/tests/e2e/graphics/test-cases/series/area-with-point-markers.js index 9bb317f3cc..c50aa59ee2 100644 --- a/tests/e2e/graphics/test-cases/series/area-with-point-markers.js +++ b/tests/e2e/graphics/test-cases/series/area-with-point-markers.js @@ -13,7 +13,11 @@ function generateData() { } function runTestCase(container) { - const chart = window.chart = LightweightCharts.createChart(container); + const chart = (window.chart = LightweightCharts.createChart(container, { + timeScale: { + barSpacing: 12, + }, + })); const mainSeries = chart.addAreaSeries({ pointMarkersVisible: true }); diff --git a/tests/e2e/graphics/test-cases/series/baseline-with-point-markers.js b/tests/e2e/graphics/test-cases/series/baseline-with-point-markers.js index 48a99540c8..c2fec958e5 100644 --- a/tests/e2e/graphics/test-cases/series/baseline-with-point-markers.js +++ b/tests/e2e/graphics/test-cases/series/baseline-with-point-markers.js @@ -1,7 +1,7 @@ function generateData() { const res = []; const time = new Date(Date.UTC(2018, 0, 1, 0, 0, 0, 0)); - for (let i = 0; i < 50; ++i) { + for (let i = 0; i < 10; ++i) { res.push({ time: time.getTime() / 1000, value: i * (-1), @@ -10,28 +10,28 @@ function generateData() { time.setUTCDate(time.getUTCDate() + 1); } - for (let i = 0; i < 100; ++i) { + for (let i = 0; i < 20; ++i) { res.push({ time: time.getTime() / 1000, - value: -50 + i, + value: -10 + i, }); time.setUTCDate(time.getUTCDate() + 1); } - for (let i = 0; i < 100; ++i) { + for (let i = 0; i < 20; ++i) { res.push({ time: time.getTime() / 1000, - value: 50 - i, + value: 10 - i, }); time.setUTCDate(time.getUTCDate() + 1); } - for (let i = 0; i < 100; ++i) { + for (let i = 0; i < 20; ++i) { res.push({ time: time.getTime() / 1000, - value: -50 + i, + value: -10 + i, }); time.setUTCDate(time.getUTCDate() + 1); diff --git a/tests/e2e/graphics/test-cases/series/line-series-with-point-markers-and-hidden-line.js b/tests/e2e/graphics/test-cases/series/line-series-with-point-markers-and-hidden-line.js index 9697dfa3c5..66915e7632 100644 --- a/tests/e2e/graphics/test-cases/series/line-series-with-point-markers-and-hidden-line.js +++ b/tests/e2e/graphics/test-cases/series/line-series-with-point-markers-and-hidden-line.js @@ -13,7 +13,11 @@ function generateData() { } function runTestCase(container) { - const chart = window.chart = LightweightCharts.createChart(container); + const chart = (window.chart = LightweightCharts.createChart(container, { + timeScale: { + barSpacing: 12, + }, + })); const mainSeries = chart.addLineSeries({ lineWidth: 1, diff --git a/tests/e2e/graphics/test-cases/series/line-with-point-markers.js b/tests/e2e/graphics/test-cases/series/line-with-point-markers.js index 4886cc0691..8b6acecc45 100644 --- a/tests/e2e/graphics/test-cases/series/line-with-point-markers.js +++ b/tests/e2e/graphics/test-cases/series/line-with-point-markers.js @@ -13,7 +13,11 @@ function generateData() { } function runTestCase(container) { - const chart = window.chart = LightweightCharts.createChart(container); + const chart = (window.chart = LightweightCharts.createChart(container, { + timeScale: { + barSpacing: 12, + }, + })); const mainSeries = chart.addLineSeries({ lineWidth: 1, From 45e28a5213575eedc3c370b7e7997cd3fe354ecc Mon Sep 17 00:00:00 2001 From: Mark Silverwood Date: Tue, 13 Jun 2023 13:16:56 +0100 Subject: [PATCH 14/14] update size-limit before merging to master --- .size-limit.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.size-limit.js b/.size-limit.js index 3b7f44a51c..7512fb3e78 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -4,21 +4,21 @@ module.exports = [ { name: 'CJS', path: 'dist/lightweight-charts.production.cjs', - limit: '44.55 KB', + limit: '46.94 KB', }, { name: 'ESM', path: 'dist/lightweight-charts.production.mjs', - limit: '44.5 KB', + limit: '46.86 KB', }, { name: 'Standalone-ESM', path: 'dist/lightweight-charts.standalone.production.mjs', - limit: '46.2 KB', + limit: '48.56 KB', }, { name: 'Standalone', path: 'dist/lightweight-charts.standalone.production.js', - limit: '46.25 KB', + limit: '48.61 KB', }, ];