Skip to content

Commit 3844954

Browse files
authored
Merge pull request #21325 from PPRAMANIK62/fix-21322
fix(candlestick): fix candlestick render error with `series.encode`
2 parents 976f5bb + f94f221 commit 3844954

File tree

7 files changed

+315
-25
lines changed

7 files changed

+315
-25
lines changed

src/chart/boxplot/BoxplotView.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class BoxplotView extends ChartView {
4646
group.removeAll();
4747
}
4848

49-
const constDim = seriesModel.get('layout') === 'horizontal' ? 1 : 0;
49+
const constDim = seriesModel.getWhiskerBoxesLayout() === 'horizontal' ? 1 : 0;
5050

5151
data.diff(oldData)
5252
.add(function (newIdx) {

src/chart/boxplot/boxplotLayout.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ function layoutSingleSeries(seriesModel: BoxplotSeriesModel, offset: number, box
144144
const coordSys = seriesModel.coordinateSystem;
145145
const data = seriesModel.getData();
146146
const halfWidth = boxWidth / 2;
147-
const cDimIdx = seriesModel.get('layout') === 'horizontal' ? 0 : 1;
147+
const cDimIdx = seriesModel.getWhiskerBoxesLayout() === 'horizontal' ? 0 : 1;
148148
const vDimIdx = 1 - cDimIdx;
149149
const coordDims = ['x', 'y'];
150150
const cDim = data.mapDimension(coordDims[cDimIdx]);

src/chart/candlestick/CandlestickSeries.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import SeriesData from '../../data/SeriesData';
3737
import Cartesian2D from '../../coord/cartesian/Cartesian2D';
3838
import { BrushCommonSelectorsForSeries } from '../../component/brush/selector';
3939
import { mixin } from 'zrender/src/core/util';
40+
import type Axis2D from '../../coord/cartesian/Axis2D';
4041

4142
type CandlestickDataValue = OptionDataValue[];
4243

@@ -158,6 +159,9 @@ class CandlestickSeriesModel extends SeriesModel<CandlestickSeriesOption> {
158159
}
159160
}
160161

162+
interface CandlestickSeriesModel extends WhiskerBoxCommonMixin<CandlestickSeriesOption> {
163+
getBaseAxis(): Axis2D
164+
}
161165
mixin(CandlestickSeriesModel, WhiskerBoxCommonMixin, true);
162166

163167
export default CandlestickSeriesModel;

src/chart/candlestick/CandlestickView.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ class CandlestickView extends ChartView {
106106
group.removeAll();
107107
}
108108

109+
const transPointDim = getTransPointDimension(seriesModel);
110+
109111
data.diff(oldData)
110112
.add(function (newIdx) {
111113
if (data.hasValue(newIdx)) {
@@ -115,7 +117,7 @@ class CandlestickView extends ChartView {
115117
return;
116118
}
117119

118-
const el = createNormalBox(itemLayout, newIdx, true);
120+
const el = createNormalBox(itemLayout, newIdx, transPointDim, true);
119121
graphic.initProps(el, {shape: {points: itemLayout.ends}}, seriesModel, newIdx);
120122

121123
setBoxCommon(el, data, newIdx, isSimpleBox);
@@ -141,7 +143,7 @@ class CandlestickView extends ChartView {
141143
}
142144

143145
if (!el) {
144-
el = createNormalBox(itemLayout, newIdx);
146+
el = createNormalBox(itemLayout, newIdx, transPointDim);
145147
}
146148
else {
147149
graphic.updateProps(el, {
@@ -188,10 +190,12 @@ class CandlestickView extends ChartView {
188190
const data = seriesModel.getData();
189191
const isSimpleBox = data.getLayout('isSimpleBox');
190192

193+
const transPointDim = getTransPointDimension(seriesModel);
194+
191195
let dataIndex;
192196
while ((dataIndex = params.next()) != null) {
193197
const itemLayout = data.getItemLayout(dataIndex) as CandlestickItemLayout;
194-
const el = createNormalBox(itemLayout, dataIndex);
198+
const el = createNormalBox(itemLayout, dataIndex, transPointDim);
195199
setBoxCommon(el, data, dataIndex, isSimpleBox);
196200

197201
el.incremental = true;
@@ -262,12 +266,17 @@ class NormalBoxPath extends Path<NormalBoxPathProps> {
262266
}
263267

264268

265-
function createNormalBox(itemLayout: CandlestickItemLayout, dataIndex: number, isInit?: boolean) {
269+
function createNormalBox(
270+
itemLayout: CandlestickItemLayout,
271+
dataIndex: number,
272+
constDim: number,
273+
isInit?: boolean
274+
) {
266275
const ends = itemLayout.ends;
267276
return new NormalBoxPath({
268277
shape: {
269278
points: isInit
270-
? transInit(ends, itemLayout)
279+
? transInit(ends, constDim, itemLayout)
271280
: ends
272281
},
273282
z2: 100
@@ -310,14 +319,18 @@ function setBoxCommon(el: NormalBoxPath, data: SeriesData, dataIndex: number, is
310319
toggleHoverEmphasis(el, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled'));
311320
}
312321

313-
function transInit(points: number[][], itemLayout: CandlestickItemLayout) {
322+
function transInit(points: number[][], dim: number, itemLayout: CandlestickItemLayout) {
314323
return zrUtil.map(points, function (point) {
315324
point = point.slice();
316-
point[1] = itemLayout.initBaseline;
325+
point[dim] = itemLayout.initBaseline;
317326
return point;
318327
});
319328
}
320329

330+
function getTransPointDimension(seriesModel: CandlestickSeriesModel): number {
331+
return seriesModel.getWhiskerBoxesLayout() === 'horizontal' ? 1 : 0;
332+
}
333+
321334

322335

323336
class LargeBoxPathShape {

src/chart/candlestick/candlestickLayout.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ const candlestickLayout: StageHandler = {
5151
const coordSys = seriesModel.coordinateSystem;
5252
const data = seriesModel.getData();
5353
const candleWidth = calculateCandleWidth(seriesModel, data);
54-
const cDimIdx = 0;
55-
const vDimIdx = 1;
54+
const cDimIdx = seriesModel.getWhiskerBoxesLayout() === 'horizontal' ? 0 : 1;
55+
const vDimIdx = 1 - cDimIdx;
5656
const coordDims = ['x', 'y'];
5757
const cDimI = data.getDimensionIndex(data.mapDimension(coordDims[cDimIdx]));
5858
const vDimsI = map(data.mapDimensionsAll(coordDims[vDimIdx]), data.getDimensionIndex, data);

src/chart/helper/whiskerBoxCommon.ts

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ import type Axis2D from '../../coord/cartesian/Axis2D';
3030
import { CoordDimensionDefinition } from '../../data/helper/createDimensions';
3131

3232
interface CommonOption extends SeriesOption, SeriesOnCartesianOptionMixin {
33+
// - 'horizontal': Multiple whisker boxes (each drawn vertically)
34+
// are arranged side by side horizontally.
35+
// - 'vertical': The opposite.
3336
layout?: LayoutOrient
3437

3538
// data?: (DataItemOption | number[])[]
@@ -44,14 +47,15 @@ interface DataItemOption {
4447
interface WhiskerBoxCommonMixin<Opts extends CommonOption> extends SeriesModel<Opts>{}
4548
class WhiskerBoxCommonMixin<Opts extends CommonOption> {
4649

47-
/**
48-
* @private
49-
* @type {string}
50-
*/
51-
_baseAxisDim: string;
50+
private _baseAxisDim: string;
5251

5352
defaultValueDimensions: CoordDimensionDefinition['dimsDef'];
5453

54+
/**
55+
* Computed layout.
56+
*/
57+
private _layout: CommonOption['layout'];
58+
5559
/**
5660
* @private
5761
*/
@@ -76,25 +80,33 @@ class WhiskerBoxCommonMixin<Opts extends CommonOption> {
7680
const yAxisType = yAxisModel.get('type');
7781
let addOrdinal;
7882

79-
// FIXME
80-
// Consider time axis.
81-
83+
// Theoretically, if `encode` and/or `layout` are not specified, they can be derived from
84+
// the specified one (also according to axis types). However, only the logic for deriving
85+
// `encode` from `layout` is implemented; the reverse direction is not implemented yet,
86+
// due to its complexity and low priority.
87+
let layout = option.layout;
88+
// 'category' axis has historically been enforcing `layout` regardless of its presence.
89+
// This behavior is preserved until it causes problems.
8290
if (xAxisType === 'category') {
83-
option.layout = 'horizontal';
91+
layout = 'horizontal';
8492
ordinalMeta = xAxisModel.getOrdinalMeta();
8593
addOrdinal = !this._hasEncodeRule('x');
8694
}
8795
else if (yAxisType === 'category') {
88-
option.layout = 'vertical';
96+
layout = 'vertical';
8997
ordinalMeta = yAxisModel.getOrdinalMeta();
9098
addOrdinal = !this._hasEncodeRule('y');
9199
}
92-
else {
93-
option.layout = option.layout || 'horizontal';
100+
if (!layout) {
101+
layout = yAxisType === 'time' ? 'vertical' : 'horizontal';
102+
// It is theoretically possible for an axis with type "time" to serve as the "value axis".
103+
// `layout` can be explicitly specified for that case.
94104
}
105+
// Do not assign the computed `layout` to `option.layout`, otherwise the idempotent may be broken.
106+
this._layout = layout;
95107

96108
const coordDims = ['x', 'y'];
97-
const baseAxisDimIndex = option.layout === 'horizontal' ? 0 : 1;
109+
const baseAxisDimIndex = layout === 'horizontal' ? 0 : 1;
98110
const baseAxisDim = this._baseAxisDim = coordDims[baseAxisDimIndex];
99111
const otherAxisDim = coordDims[1 - baseAxisDimIndex];
100112
const axisModels = [xAxisModel, yAxisModel];
@@ -166,7 +178,11 @@ class WhiskerBoxCommonMixin<Opts extends CommonOption> {
166178
) as CartesianAxisModel).axis;
167179
}
168180

181+
getWhiskerBoxesLayout() {
182+
return this._layout;
183+
}
184+
169185
};
170186

171187

172-
export {WhiskerBoxCommonMixin};
188+
export { WhiskerBoxCommonMixin };

0 commit comments

Comments
 (0)