diff --git a/src/common/Styles.ts b/src/common/Styles.ts index badb484b7..077da825f 100644 --- a/src/common/Styles.ts +++ b/src/common/Styles.ts @@ -514,7 +514,7 @@ function getDefaultCandleStyle (): CandleStyle { function getDefaultIndicatorStyle (): IndicatorStyle { const lines = ['#FF9600', '#935EBD', blue, '#E11D74', '#01C5C4'].map(color => ({ style: LineType.Solid, - smooth: true, + smooth: false, size: 1, dashedValue: [2, 2], color diff --git a/src/component/Indicator.ts b/src/component/Indicator.ts index 7ed2f2df6..596fa4870 100644 --- a/src/component/Indicator.ts +++ b/src/component/Indicator.ts @@ -216,7 +216,7 @@ export type IndicatorCreate = ExcludePickPartial, 're export type IndicatorConstructor = new () => IndicatorImp -export type EachFigureCallback = (figure: IndicatorFigure, figureStyles: IndicatorFigureStyle) => void +export type EachFigureCallback = (figure: IndicatorFigure, figureStyles: IndicatorFigureStyle, index: number) => void export function eachFigures ( kLineDataList: KLineData[], @@ -243,21 +243,25 @@ export function eachFigures ( let lineCount = 0 let defaultFigureStyles + let figureIndex = 0 figures.forEach(figure => { switch (figure.type) { case 'circle': { + figureIndex = circleCount const styles = circleStyles[circleCount % circleStyleCount] defaultFigureStyles = { ...styles, color: styles.noChangeColor } circleCount++ break } case 'bar': { + figureIndex = barCount const styles = barStyles[barCount % barStyleCount] defaultFigureStyles = { ...styles, color: styles.noChangeColor } barCount++ break } case 'line': { + figureIndex = lineCount defaultFigureStyles = lineStyles[lineCount % lineStyleCount] lineCount++ break @@ -272,7 +276,7 @@ export function eachFigures ( } const ss = figure.styles?.(cbData, indicator, defaultStyles) // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - eachFigureCallback(figure, { ...defaultFigureStyles, ...ss }) + eachFigureCallback(figure, { ...defaultFigureStyles, ...ss }, figureIndex) } }) } diff --git a/src/view/IndicatorView.ts b/src/view/IndicatorView.ts index a2e4201bc..7193eea6f 100644 --- a/src/view/IndicatorView.ts +++ b/src/view/IndicatorView.ts @@ -15,7 +15,10 @@ import type Nullable from '../common/Nullable' import type VisibleData from '../common/VisibleData' import type BarSpace from '../common/BarSpace' -import { CandleType } from '../common/Styles' +import { 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' import type ChartStore from '../store/ChartStore' @@ -23,9 +26,6 @@ import { eachFigures, type IndicatorFigure, type IndicatorFigureAttrs, type Indi import CandleBarView, { type CandleBarOptions } from './CandleBarView' -import { formatValue } from '../common/utils/format' -import { isNumber, isValid } from '../common/utils/typeChecks' - export default class IndicatorView extends CandleBarView { override getCandleBarOptions (chartStore: ChartStore): Nullable { const pane = this.getWidget().getPane() @@ -99,6 +99,7 @@ export default class IndicatorView extends CandleBarView { } if (!isCover) { const result = indicator.result + const lines: Array> = [] this.eachChildren((data: VisibleData, barSpace: BarSpace) => { const { halfGapBar, gapBar } = barSpace @@ -125,7 +126,7 @@ export default class IndicatorView extends CandleBarView { nextCoordinate[key] = yAxis.convertToPixel(nextValue) } }) - eachFigures(dataList, indicator, dataIndex, defaultStyles, (figure: IndicatorFigure, figureStyles: IndicatorFigureStyle) => { + eachFigures(dataList, indicator, dataIndex, defaultStyles, (figure: IndicatorFigure, figureStyles: IndicatorFigureStyle, figureIndex: number) => { if (isValid(currentIndicatorData[figure.key])) { const valueY = currentCoordinate[figure.key] let attrs = figure.attrs?.({ @@ -164,30 +165,76 @@ export default class IndicatorView extends CandleBarView { break } case 'line': { + if (!isValid(lines[figureIndex])) { + lines[figureIndex] = [] + } if (isNumber(currentCoordinate[figure.key]) && isNumber(nextCoordinate[figure.key])) { - attrs = { + lines[figureIndex].push({ coordinates: [ { x: currentCoordinate.x, y: currentCoordinate[figure.key] }, { x: nextCoordinate.x, y: nextCoordinate[figure.key] } - ] - } + ], + styles: figureStyles as unknown as SmoothLineStyle + }) } break } default: { break } } } - if (isValid(attrs)) { - const name = figure.type! + const type = figure.type! + if (isValid(attrs) && type !== 'line') { this.createFigure({ - name: name === 'bar' ? 'rect' : name, + name: type === 'bar' ? 'rect' : type, attrs, styles: figureStyles })?.draw(ctx) } + // merge line render } }) }) + + // merge line and render + lines.forEach(items => { + if (items.length > 1) { + const mergeLines = [ + { + coordinates: [items[0].coordinates[0], items[0].coordinates[1]], + styles: items[0].styles + } + ] + for (let i = 1; i < items.length; i++) { + const lastMergeLine = mergeLines[mergeLines.length - 1] + const current = items[i] + const lastMergeLineLastCoordinate = lastMergeLine.coordinates[lastMergeLine.coordinates.length - 1] + if ( + lastMergeLineLastCoordinate.x === current.coordinates[0].x && + lastMergeLineLastCoordinate.y === current.coordinates[0].y && + lastMergeLine.styles.style === current.styles.style && + lastMergeLine.styles.color === current.styles.color && + lastMergeLine.styles.size === current.styles.size && + lastMergeLine.styles.smooth === current.styles.smooth && + lastMergeLine.styles.dashedValue[0] === current.styles.dashedValue[0] && + lastMergeLine.styles.dashedValue[1] === current.styles.dashedValue[1] + ) { + lastMergeLine.coordinates.push(current.coordinates[1]) + } else { + mergeLines.push({ + coordinates: [current.coordinates[0], current.coordinates[1]], + styles: current.styles + }) + } + } + mergeLines.forEach(({ coordinates, styles }) => { + this.createFigure({ + name: 'line', + attrs: { coordinates }, + styles + })?.draw(ctx) + }) + } + }) } } })