|
1 | 1 | import { BitmapCoordinatesRenderingScope, CanvasRenderingTarget2D } from 'fancy-canvas'; |
2 | 2 |
|
3 | | -import { CustomBarItemData, ICustomSeriesPaneRenderer, PaneRendererCustomData, PriceToCoordinateConverter, SeriesDataItemTypeMap, SingleValueData } from 'lightweight-charts'; |
| 3 | +import { CustomBarItemData, ICustomSeriesPaneRenderer, PaneRendererCustomData, PriceToCoordinateConverter } from 'lightweight-charts'; |
4 | 4 |
|
5 | 5 | import { PrettyHistogramSeriesOptions } from './options'; |
6 | 6 | import { PrettyHistogramData } from './data'; |
| 7 | +import { positionsBox } from '../../helpers/dimensions/positions'; |
7 | 8 |
|
8 | 9 | interface PrettyHistogramBarItem { |
9 | 10 | x: number; |
@@ -48,38 +49,40 @@ export class PrettyHistogramSeriesRenderer<HorzScaleItem, TData extends PrettyHi |
48 | 49 | const bars: PrettyHistogramBarItem[] = this._data.bars.map((bar: CustomBarItemData<HorzScaleItem, TData>) => { |
49 | 50 | return { |
50 | 51 | x: bar.x * renderingScope.horizontalPixelRatio, |
51 | | - value: priceToCoordinate(bar.originalData.value!)! * renderingScope.verticalPixelRatio, |
| 52 | + value: priceToCoordinate(bar.originalData.value!)!, |
52 | 53 | color: bar.barColor ?? options.color, |
53 | 54 | }; |
54 | 55 | }); |
55 | 56 |
|
56 | | - const zeroCoordinate = priceToCoordinate(0)! * renderingScope.verticalPixelRatio; |
| 57 | + const zeroCoordinate = priceToCoordinate(0) ?? 0; |
57 | 58 |
|
58 | 59 | const ctx = renderingScope.context; |
59 | 60 |
|
60 | 61 | let prevColor: string | null = null; |
61 | 62 | ctx.beginPath(); |
62 | 63 | const width = Math.max(1, Math.round(0.01 * options.widthPercent * this._data.barSpacing * renderingScope.horizontalPixelRatio)); |
63 | 64 | const radius = Math.floor(options.radius * renderingScope.horizontalPixelRatio); |
64 | | - bars.forEach((item: PrettyHistogramBarItem) => { |
| 65 | + bars.slice(this._data.visibleRange.from, this._data.visibleRange.to + 1).forEach((item: PrettyHistogramBarItem) => { |
65 | 66 | const color = item.color; |
66 | 67 | if (prevColor !== null && prevColor !== color) { |
67 | 68 | ctx.fill(); |
68 | 69 | ctx.beginPath(); |
69 | 70 | } |
70 | 71 | ctx.fillStyle = color; |
71 | | - const height = item.value - zeroCoordinate; |
72 | | - const actualRadius = Math.floor(Math.min(radius, width / 2, Math.abs(height))); |
73 | | - const vertRadius = Math.sign(height) * actualRadius; |
| 72 | + const yPositionBox = positionsBox( |
| 73 | + zeroCoordinate, |
| 74 | + item.value, |
| 75 | + renderingScope.verticalPixelRatio |
| 76 | + ) |
| 77 | + const actualRadius = Math.floor(Math.min(radius, width / 2, Math.abs(yPositionBox.length))); |
74 | 78 | const left = Math.round(item.x - width / 2); |
75 | | - const right = left + width; |
76 | | - ctx.moveTo(left, zeroCoordinate); |
77 | | - ctx.lineTo(left, item.value - vertRadius); |
78 | | - ctx.arcTo(left, item.value, left + actualRadius, item.value, actualRadius); |
79 | | - ctx.lineTo(right - actualRadius, item.value); |
80 | | - ctx.arcTo(right, item.value, right, item.value - vertRadius, actualRadius); |
81 | | - ctx.lineTo(right, zeroCoordinate); |
82 | | - ctx.lineTo(left, zeroCoordinate); |
| 79 | + ctx.roundRect( |
| 80 | + left, |
| 81 | + yPositionBox.position, |
| 82 | + width, |
| 83 | + yPositionBox.length, |
| 84 | + item.value < zeroCoordinate ? [actualRadius, actualRadius, 0, 0] : [0, 0, actualRadius, actualRadius] |
| 85 | + ); |
83 | 86 | prevColor = color; |
84 | 87 | }); |
85 | 88 | ctx.fill(); |
|
0 commit comments