Skip to content

Commit

Permalink
Merge pull request #640 from klinecharts/feature/#495
Browse files Browse the repository at this point in the history
feat: styles add `candle.bar.compareRule` and `indicator.ohlc.compareRule`
  • Loading branch information
liihuu authored Jan 16, 2025
2 parents c6d1dcc + dd65fed commit 28858fb
Show file tree
Hide file tree
Showing 12 changed files with 576 additions and 1,114 deletions.
527 changes: 527 additions & 0 deletions docs/@views/styles/config.md

Large diffs are not rendered by default.

529 changes: 1 addition & 528 deletions docs/en-US/guide/styles.md

Large diffs are not rendered by default.

550 changes: 1 addition & 549 deletions docs/guide/styles.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "klinecharts",
"version": "10.0.0-alpha2",
"version": "10.0.0-alpha3",
"description": "Lightweight k-line chart built with html5 canvas",
"type": "module",
"main": "./dist/index.cjs",
Expand Down
6 changes: 5 additions & 1 deletion src/Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,11 @@ export default class StoreImp implements Store {
this._visibleRangeDataList.push({
dataIndex: i,
x,
data: kLineData
data: {
prev: this._dataList[i - 1] ?? kLineData,
current: kLineData,
next: this._dataList[i - 1] ?? kLineData
}
})
if (isValid(kLineData)) {
if (this._visibleRangeHighLowPrice[0].price < kLineData.high) {
Expand Down
8 changes: 7 additions & 1 deletion src/common/Data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@

import type Nullable from './Nullable'

export interface NeighborData<D> {
prev: D
current: D
next: D
}

export interface KLineData {
timestamp: number
open: number
Expand All @@ -28,5 +34,5 @@ export interface KLineData {
export interface VisibleRangeData {
dataIndex: number
x: number
data: Nullable<KLineData>
data: NeighborData<Nullable<KLineData>>
}
20 changes: 11 additions & 9 deletions src/common/Styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*/

import type Nullable from './Nullable'
import type { KLineData } from './Data'
import type { KLineData, NeighborData } from './Data'

export interface Margin {
marginLeft: number
Expand Down Expand Up @@ -214,13 +214,7 @@ export interface CandleTooltipRectStyle extends Omit<RectStyle, 'style' | 'borde
position: CandleTooltipRectPosition
}

export interface CandleTooltipCustomCallbackData {
prev: Nullable<KLineData>
current: KLineData
next: Nullable<KLineData>
}

export type CandleTooltipCustomCallback = (data: CandleTooltipCustomCallbackData, styles: CandleStyle) => TooltipLegend[]
export type CandleTooltipCustomCallback = (data: NeighborData<Nullable<KLineData>>, styles: CandleStyle) => TooltipLegend[]

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

export enum CandleBarColorCompareRule {
CurrentOpen = 'current_open',
PreviousClose = 'previous_close'
}

export interface CandleBarColor extends ChangeColor {
compareRule: CandleBarColorCompareRule
upBorderColor: string
downBorderColor: string
noChangeBorderColor: string
Expand Down Expand Up @@ -266,7 +266,7 @@ export interface IndicatorTooltipStyle extends TooltipStyle, Offset {
}

export interface IndicatorStyle {
ohlc: ChangeColor
ohlc: Pick<CandleBarColor, 'compareRule' | 'upColor' | 'downColor' | 'noChangeColor'>
bars: IndicatorPolygonStyle[]
lines: SmoothLineStyle[]
circles: IndicatorPolygonStyle[]
Expand Down Expand Up @@ -393,6 +393,7 @@ function getDefaultCandleStyle (): CandleStyle {
return {
type: CandleType.CandleSolid,
bar: {
compareRule: CandleBarColorCompareRule.CurrentOpen,
upColor: green,
downColor: red,
noChangeColor: grey,
Expand Down Expand Up @@ -519,6 +520,7 @@ function getDefaultIndicatorStyle (): IndicatorStyle {

return {
ohlc: {
compareRule: CandleBarColorCompareRule.CurrentOpen,
upColor: alphaGreen,
downColor: alphaRed,
noChangeColor: grey
Expand Down
15 changes: 4 additions & 11 deletions src/component/Indicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import type Nullable from '../common/Nullable'
import type DeepPartial from '../common/DeepPartial'
import type ExcludePickPartial from '../common/ExcludePickPartial'
import type { KLineData } from '../common/Data'
import type { KLineData, NeighborData } from '../common/Data'
import type Bounding from '../common/Bounding'
import type BarSpace from '../common/BarSpace'
import type Crosshair from '../common/Crosshair'
Expand Down Expand Up @@ -43,24 +43,17 @@ export type IndicatorFigureStyle = Partial<Omit<SmoothLineStyle, 'style'>> & Par

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

export interface IndicatorFigureCallbackBrother<PCN> {
prev: PCN
current: PCN
next: PCN
}

export interface IndicatorFigureAttrsCallbackParams<D> {
data: IndicatorFigureCallbackBrother<Nullable<D>>
coordinate: IndicatorFigureCallbackBrother<Record<keyof D, number> & { x: number }>
data: NeighborData<Nullable<D>>
coordinate: NeighborData<Record<keyof D, number> & { x: number }>
bounding: Bounding
barSpace: BarSpace
xAxis: XAxis
yAxis: YAxis
}

export interface IndicatorFigureStylesCallbackParams<D> {
data: IndicatorFigureCallbackBrother<Nullable<D>>

data: NeighborData<Nullable<D>>
indicator: Indicator<D>
defaultStyles?: IndicatorStyle
}
Expand Down
4 changes: 3 additions & 1 deletion src/component/YAxis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ export default abstract class YAxisImp extends AxisImp implements YAxis {
const isArea = candleStyles.type === CandleType.Area
const areaValueKey = candleStyles.area.value
const shouldCompareHighLow = (inCandle && !isArea) || (!inCandle && shouldOhlc)
visibleRangeDataList.forEach(({ dataIndex, data }) => {
visibleRangeDataList.forEach((visibleData) => {
const dataIndex = visibleData.dataIndex
const data = visibleData.data.current
if (isValid(data)) {
if (shouldCompareHighLow) {
min = Math.min(min, data.low)
Expand Down
6 changes: 3 additions & 3 deletions src/view/CandleAreaView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
*/

import type Coordinate from '../common/Coordinate'
import type { VisibleRangeData } from '../common/Data'
import type { GradientColor } from '../common/Styles'
import Animation from '../common/Animation'
import { isNumber, isArray, isValid } from '../common/utils/typeChecks'
Expand Down Expand Up @@ -58,8 +57,9 @@ export default class CandleAreaView extends ChildrenView {
let minY = Number.MAX_SAFE_INTEGER
let areaStartX: number = Number.MIN_SAFE_INTEGER
let ripplePointCoordinate: Nullable<Coordinate> = null
this.eachChildren((data: VisibleRangeData) => {
const { data: kLineData, x } = data
this.eachChildren((data) => {
const x = data.x
const { current: kLineData } = data.data
const value = kLineData?.[styles.value]
if (isNumber(value)) {
const y = yAxis.convertToPixel(value)
Expand Down
19 changes: 10 additions & 9 deletions src/view/CandleBarView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type { VisibleRangeData } from '../common/Data'
import type BarSpace from '../common/BarSpace'
import type { EventHandler } from '../common/SyntheticEvent'
import { ActionType } from '../common/Action'
import { CandleType, type CandleBarColor, type RectStyle, PolygonType } from '../common/Styles'
import { CandleType, type CandleBarColor, type RectStyle, PolygonType, CandleBarColorCompareRule } from '../common/Styles'

import type { FigureCreate } from '../component/Figure'
import type { RectAttrs } from '../extension/figure/rect'
Expand All @@ -44,6 +44,7 @@ export default class CandleBarView extends ChildrenView {
const chartStore = pane.getChart().getChartStore()
const candleBarOptions = this.getCandleBarOptions()
if (candleBarOptions !== null) {
const { type, styles } = candleBarOptions
let ohlcSize = 0
let halfOhlcSize = 0
if (candleBarOptions.type === CandleType.Ohlc) {
Expand All @@ -55,17 +56,17 @@ export default class CandleBarView extends ChildrenView {
halfOhlcSize = Math.floor(halfOhlcSize / 2)
}
const yAxis = pane.getAxisComponent()
this.eachChildren((data, barSpace) => {
const { data: kLineData, x } = data
if (isValid(kLineData)) {
const { open, high, low, close } = kLineData
const { type, styles } = candleBarOptions
this.eachChildren((visibleData, barSpace) => {
const { x, data: { current, prev } } = visibleData
if (isValid(current)) {
const { open, high, low, close } = current
const comparePrice = styles.compareRule === CandleBarColorCompareRule.CurrentOpen ? open : (prev?.close ?? close)
const colors: string[] = []
if (close > open) {
if (close > comparePrice) {
colors[0] = styles.upColor
colors[1] = styles.upBorderColor
colors[2] = styles.upWickColor
} else if (close < open) {
} else if (close < comparePrice) {
colors[0] = styles.downColor
colors[1] = styles.downBorderColor
colors[2] = styles.downWickColor
Expand Down Expand Up @@ -144,7 +145,7 @@ export default class CandleBarView extends ChildrenView {
let handler: Nullable<EventHandler> = null
if (isMain) {
handler = {
mouseClickEvent: this._boundCandleBarClickEvent(data)
mouseClickEvent: this._boundCandleBarClickEvent(visibleData)
}
}
this.createFigure(rect, handler ?? undefined)?.draw(ctx)
Expand Down
4 changes: 3 additions & 1 deletion src/view/IndicatorView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*/

import type Nullable from '../common/Nullable'
import { CandleType, type SmoothLineStyle } from '../common/Styles'
import { type CandleBarColorCompareRule, CandleType, type SmoothLineStyle } from '../common/Styles'
import { formatValue } from '../common/utils/format'
import { isNumber, isValid } from '../common/utils/typeChecks'
import type Coordinate from '../common/Coordinate'
Expand All @@ -33,12 +33,14 @@ export default class IndicatorView extends CandleBarView {
if (indicator.shouldOhlc && indicator.visible) {
const indicatorStyles = indicator.styles
const defaultStyles = chartStore.getStyles().indicator
const compareRule = formatValue(indicatorStyles, 'ohlc.compareRule', defaultStyles.ohlc.compareRule) as CandleBarColorCompareRule
const upColor = formatValue(indicatorStyles, 'ohlc.upColor', defaultStyles.ohlc.upColor) as string
const downColor = formatValue(indicatorStyles, 'ohlc.downColor', defaultStyles.ohlc.downColor) as string
const noChangeColor = formatValue(indicatorStyles, 'ohlc.noChangeColor', defaultStyles.ohlc.noChangeColor) as string
return {
type: CandleType.Ohlc,
styles: {
compareRule,
upColor,
downColor,
noChangeColor,
Expand Down

0 comments on commit 28858fb

Please sign in to comment.