Skip to content

Commit 28858fb

Browse files
authored
Merge pull request #640 from klinecharts/feature/#495
feat: styles add `candle.bar.compareRule` and `indicator.ohlc.compareRule`
2 parents c6d1dcc + dd65fed commit 28858fb

File tree

12 files changed

+576
-1114
lines changed

12 files changed

+576
-1114
lines changed

docs/@views/styles/config.md

Lines changed: 527 additions & 0 deletions
Large diffs are not rendered by default.

docs/en-US/guide/styles.md

Lines changed: 1 addition & 528 deletions
Large diffs are not rendered by default.

docs/guide/styles.md

Lines changed: 1 addition & 549 deletions
Large diffs are not rendered by default.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "klinecharts",
3-
"version": "10.0.0-alpha2",
3+
"version": "10.0.0-alpha3",
44
"description": "Lightweight k-line chart built with html5 canvas",
55
"type": "module",
66
"main": "./dist/index.cjs",

src/Store.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,11 @@ export default class StoreImp implements Store {
639639
this._visibleRangeDataList.push({
640640
dataIndex: i,
641641
x,
642-
data: kLineData
642+
data: {
643+
prev: this._dataList[i - 1] ?? kLineData,
644+
current: kLineData,
645+
next: this._dataList[i - 1] ?? kLineData
646+
}
643647
})
644648
if (isValid(kLineData)) {
645649
if (this._visibleRangeHighLowPrice[0].price < kLineData.high) {

src/common/Data.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414

1515
import type Nullable from './Nullable'
1616

17+
export interface NeighborData<D> {
18+
prev: D
19+
current: D
20+
next: D
21+
}
22+
1723
export interface KLineData {
1824
timestamp: number
1925
open: number
@@ -28,5 +34,5 @@ export interface KLineData {
2834
export interface VisibleRangeData {
2935
dataIndex: number
3036
x: number
31-
data: Nullable<KLineData>
37+
data: NeighborData<Nullable<KLineData>>
3238
}

src/common/Styles.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*/
1414

1515
import type Nullable from './Nullable'
16-
import type { KLineData } from './Data'
16+
import type { KLineData, NeighborData } from './Data'
1717

1818
export interface Margin {
1919
marginLeft: number
@@ -214,13 +214,7 @@ export interface CandleTooltipRectStyle extends Omit<RectStyle, 'style' | 'borde
214214
position: CandleTooltipRectPosition
215215
}
216216

217-
export interface CandleTooltipCustomCallbackData {
218-
prev: Nullable<KLineData>
219-
current: KLineData
220-
next: Nullable<KLineData>
221-
}
222-
223-
export type CandleTooltipCustomCallback = (data: CandleTooltipCustomCallbackData, styles: CandleStyle) => TooltipLegend[]
217+
export type CandleTooltipCustomCallback = (data: NeighborData<Nullable<KLineData>>, styles: CandleStyle) => TooltipLegend[]
224218

225219
export interface CandleTooltipStyle extends TooltipStyle, Offset {
226220
custom: CandleTooltipCustomCallback | TooltipLegend[]
@@ -236,7 +230,13 @@ export enum CandleType {
236230
Area = 'area'
237231
}
238232

233+
export enum CandleBarColorCompareRule {
234+
CurrentOpen = 'current_open',
235+
PreviousClose = 'previous_close'
236+
}
237+
239238
export interface CandleBarColor extends ChangeColor {
239+
compareRule: CandleBarColorCompareRule
240240
upBorderColor: string
241241
downBorderColor: string
242242
noChangeBorderColor: string
@@ -266,7 +266,7 @@ export interface IndicatorTooltipStyle extends TooltipStyle, Offset {
266266
}
267267

268268
export interface IndicatorStyle {
269-
ohlc: ChangeColor
269+
ohlc: Pick<CandleBarColor, 'compareRule' | 'upColor' | 'downColor' | 'noChangeColor'>
270270
bars: IndicatorPolygonStyle[]
271271
lines: SmoothLineStyle[]
272272
circles: IndicatorPolygonStyle[]
@@ -393,6 +393,7 @@ function getDefaultCandleStyle (): CandleStyle {
393393
return {
394394
type: CandleType.CandleSolid,
395395
bar: {
396+
compareRule: CandleBarColorCompareRule.CurrentOpen,
396397
upColor: green,
397398
downColor: red,
398399
noChangeColor: grey,
@@ -519,6 +520,7 @@ function getDefaultIndicatorStyle (): IndicatorStyle {
519520

520521
return {
521522
ohlc: {
523+
compareRule: CandleBarColorCompareRule.CurrentOpen,
522524
upColor: alphaGreen,
523525
downColor: alphaRed,
524526
noChangeColor: grey

src/component/Indicator.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import type Nullable from '../common/Nullable'
1616
import type DeepPartial from '../common/DeepPartial'
1717
import type ExcludePickPartial from '../common/ExcludePickPartial'
18-
import type { KLineData } from '../common/Data'
18+
import type { KLineData, NeighborData } from '../common/Data'
1919
import type Bounding from '../common/Bounding'
2020
import type BarSpace from '../common/BarSpace'
2121
import type Crosshair from '../common/Crosshair'
@@ -43,24 +43,17 @@ export type IndicatorFigureStyle = Partial<Omit<SmoothLineStyle, 'style'>> & Par
4343

4444
export type IndicatorFigureAttrs = Partial<ArcAttrs> & Partial<LineStyle> & Partial<RectAttrs> & Partial<TextAttrs> & Record<string, unknown>
4545

46-
export interface IndicatorFigureCallbackBrother<PCN> {
47-
prev: PCN
48-
current: PCN
49-
next: PCN
50-
}
51-
5246
export interface IndicatorFigureAttrsCallbackParams<D> {
53-
data: IndicatorFigureCallbackBrother<Nullable<D>>
54-
coordinate: IndicatorFigureCallbackBrother<Record<keyof D, number> & { x: number }>
47+
data: NeighborData<Nullable<D>>
48+
coordinate: NeighborData<Record<keyof D, number> & { x: number }>
5549
bounding: Bounding
5650
barSpace: BarSpace
5751
xAxis: XAxis
5852
yAxis: YAxis
5953
}
6054

6155
export interface IndicatorFigureStylesCallbackParams<D> {
62-
data: IndicatorFigureCallbackBrother<Nullable<D>>
63-
56+
data: NeighborData<Nullable<D>>
6457
indicator: Indicator<D>
6558
defaultStyles?: IndicatorStyle
6659
}

src/component/YAxis.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,9 @@ export default abstract class YAxisImp extends AxisImp implements YAxis {
119119
const isArea = candleStyles.type === CandleType.Area
120120
const areaValueKey = candleStyles.area.value
121121
const shouldCompareHighLow = (inCandle && !isArea) || (!inCandle && shouldOhlc)
122-
visibleRangeDataList.forEach(({ dataIndex, data }) => {
122+
visibleRangeDataList.forEach((visibleData) => {
123+
const dataIndex = visibleData.dataIndex
124+
const data = visibleData.data.current
123125
if (isValid(data)) {
124126
if (shouldCompareHighLow) {
125127
min = Math.min(min, data.low)

src/view/CandleAreaView.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
*/
1414

1515
import type Coordinate from '../common/Coordinate'
16-
import type { VisibleRangeData } from '../common/Data'
1716
import type { GradientColor } from '../common/Styles'
1817
import Animation from '../common/Animation'
1918
import { isNumber, isArray, isValid } from '../common/utils/typeChecks'
@@ -58,8 +57,9 @@ export default class CandleAreaView extends ChildrenView {
5857
let minY = Number.MAX_SAFE_INTEGER
5958
let areaStartX: number = Number.MIN_SAFE_INTEGER
6059
let ripplePointCoordinate: Nullable<Coordinate> = null
61-
this.eachChildren((data: VisibleRangeData) => {
62-
const { data: kLineData, x } = data
60+
this.eachChildren((data) => {
61+
const x = data.x
62+
const { current: kLineData } = data.data
6363
const value = kLineData?.[styles.value]
6464
if (isNumber(value)) {
6565
const y = yAxis.convertToPixel(value)

src/view/CandleBarView.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import type { VisibleRangeData } from '../common/Data'
1717
import type BarSpace from '../common/BarSpace'
1818
import type { EventHandler } from '../common/SyntheticEvent'
1919
import { ActionType } from '../common/Action'
20-
import { CandleType, type CandleBarColor, type RectStyle, PolygonType } from '../common/Styles'
20+
import { CandleType, type CandleBarColor, type RectStyle, PolygonType, CandleBarColorCompareRule } from '../common/Styles'
2121

2222
import type { FigureCreate } from '../component/Figure'
2323
import type { RectAttrs } from '../extension/figure/rect'
@@ -44,6 +44,7 @@ export default class CandleBarView extends ChildrenView {
4444
const chartStore = pane.getChart().getChartStore()
4545
const candleBarOptions = this.getCandleBarOptions()
4646
if (candleBarOptions !== null) {
47+
const { type, styles } = candleBarOptions
4748
let ohlcSize = 0
4849
let halfOhlcSize = 0
4950
if (candleBarOptions.type === CandleType.Ohlc) {
@@ -55,17 +56,17 @@ export default class CandleBarView extends ChildrenView {
5556
halfOhlcSize = Math.floor(halfOhlcSize / 2)
5657
}
5758
const yAxis = pane.getAxisComponent()
58-
this.eachChildren((data, barSpace) => {
59-
const { data: kLineData, x } = data
60-
if (isValid(kLineData)) {
61-
const { open, high, low, close } = kLineData
62-
const { type, styles } = candleBarOptions
59+
this.eachChildren((visibleData, barSpace) => {
60+
const { x, data: { current, prev } } = visibleData
61+
if (isValid(current)) {
62+
const { open, high, low, close } = current
63+
const comparePrice = styles.compareRule === CandleBarColorCompareRule.CurrentOpen ? open : (prev?.close ?? close)
6364
const colors: string[] = []
64-
if (close > open) {
65+
if (close > comparePrice) {
6566
colors[0] = styles.upColor
6667
colors[1] = styles.upBorderColor
6768
colors[2] = styles.upWickColor
68-
} else if (close < open) {
69+
} else if (close < comparePrice) {
6970
colors[0] = styles.downColor
7071
colors[1] = styles.downBorderColor
7172
colors[2] = styles.downWickColor
@@ -144,7 +145,7 @@ export default class CandleBarView extends ChildrenView {
144145
let handler: Nullable<EventHandler> = null
145146
if (isMain) {
146147
handler = {
147-
mouseClickEvent: this._boundCandleBarClickEvent(data)
148+
mouseClickEvent: this._boundCandleBarClickEvent(visibleData)
148149
}
149150
}
150151
this.createFigure(rect, handler ?? undefined)?.draw(ctx)

src/view/IndicatorView.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*/
1414

1515
import type Nullable from '../common/Nullable'
16-
import { CandleType, type SmoothLineStyle } from '../common/Styles'
16+
import { type CandleBarColorCompareRule, CandleType, type SmoothLineStyle } from '../common/Styles'
1717
import { formatValue } from '../common/utils/format'
1818
import { isNumber, isValid } from '../common/utils/typeChecks'
1919
import type Coordinate from '../common/Coordinate'
@@ -33,12 +33,14 @@ export default class IndicatorView extends CandleBarView {
3333
if (indicator.shouldOhlc && indicator.visible) {
3434
const indicatorStyles = indicator.styles
3535
const defaultStyles = chartStore.getStyles().indicator
36+
const compareRule = formatValue(indicatorStyles, 'ohlc.compareRule', defaultStyles.ohlc.compareRule) as CandleBarColorCompareRule
3637
const upColor = formatValue(indicatorStyles, 'ohlc.upColor', defaultStyles.ohlc.upColor) as string
3738
const downColor = formatValue(indicatorStyles, 'ohlc.downColor', defaultStyles.ohlc.downColor) as string
3839
const noChangeColor = formatValue(indicatorStyles, 'ohlc.noChangeColor', defaultStyles.ohlc.noChangeColor) as string
3940
return {
4041
type: CandleType.Ohlc,
4142
styles: {
43+
compareRule,
4244
upColor,
4345
downColor,
4446
noChangeColor,

0 commit comments

Comments
 (0)