This is an automated email from the ASF dual-hosted git repository.

sushuang pushed a commit to branch pr-21325
in repository https://gitbox.apache.org/repos/asf/echarts.git

commit f94f2214f637fe5a680519c0ee2f606424d27432
Author: 100pah <[email protected]>
AuthorDate: Thu Oct 30 15:41:22 2025 +0800

    fix: (1) priority of defaults by layout and axis types. (2) init animation.
---
 src/chart/boxplot/BoxplotView.ts           |  2 +-
 src/chart/boxplot/boxplotLayout.ts         |  2 +-
 src/chart/candlestick/CandlestickSeries.ts |  4 +++
 src/chart/candlestick/CandlestickView.ts   | 27 +++++++++++++-----
 src/chart/candlestick/candlestickLayout.ts |  3 +-
 src/chart/helper/whiskerBoxCommon.ts       | 45 +++++++++++++++++++-----------
 test/candlestick-horizontal.html           | 23 ++++++++++++++-
 7 files changed, 78 insertions(+), 28 deletions(-)

diff --git a/src/chart/boxplot/BoxplotView.ts b/src/chart/boxplot/BoxplotView.ts
index f48cdf67b..0d8830977 100644
--- a/src/chart/boxplot/BoxplotView.ts
+++ b/src/chart/boxplot/BoxplotView.ts
@@ -46,7 +46,7 @@ class BoxplotView extends ChartView {
             group.removeAll();
         }
 
-        const constDim = seriesModel.get('layout') === 'horizontal' ? 1 : 0;
+        const constDim = seriesModel.getWhiskerBoxesLayout() === 'horizontal' 
? 1 : 0;
 
         data.diff(oldData)
             .add(function (newIdx) {
diff --git a/src/chart/boxplot/boxplotLayout.ts 
b/src/chart/boxplot/boxplotLayout.ts
index cf6017b3c..053462d2f 100644
--- a/src/chart/boxplot/boxplotLayout.ts
+++ b/src/chart/boxplot/boxplotLayout.ts
@@ -144,7 +144,7 @@ function layoutSingleSeries(seriesModel: 
BoxplotSeriesModel, offset: number, box
     const coordSys = seriesModel.coordinateSystem;
     const data = seriesModel.getData();
     const halfWidth = boxWidth / 2;
-    const cDimIdx = seriesModel.get('layout') === 'horizontal' ? 0 : 1;
+    const cDimIdx = seriesModel.getWhiskerBoxesLayout() === 'horizontal' ? 0 : 
1;
     const vDimIdx = 1 - cDimIdx;
     const coordDims = ['x', 'y'];
     const cDim = data.mapDimension(coordDims[cDimIdx]);
diff --git a/src/chart/candlestick/CandlestickSeries.ts 
b/src/chart/candlestick/CandlestickSeries.ts
index f152fce2c..55938e3b4 100644
--- a/src/chart/candlestick/CandlestickSeries.ts
+++ b/src/chart/candlestick/CandlestickSeries.ts
@@ -37,6 +37,7 @@ import SeriesData from '../../data/SeriesData';
 import Cartesian2D from '../../coord/cartesian/Cartesian2D';
 import { BrushCommonSelectorsForSeries } from '../../component/brush/selector';
 import { mixin } from 'zrender/src/core/util';
+import type Axis2D from '../../coord/cartesian/Axis2D';
 
 type CandlestickDataValue = OptionDataValue[];
 
@@ -158,6 +159,9 @@ class CandlestickSeriesModel extends 
SeriesModel<CandlestickSeriesOption> {
     }
 }
 
+interface CandlestickSeriesModel extends 
WhiskerBoxCommonMixin<CandlestickSeriesOption> {
+    getBaseAxis(): Axis2D
+}
 mixin(CandlestickSeriesModel, WhiskerBoxCommonMixin, true);
 
 export default CandlestickSeriesModel;
diff --git a/src/chart/candlestick/CandlestickView.ts 
b/src/chart/candlestick/CandlestickView.ts
index 728291424..706cae6fc 100644
--- a/src/chart/candlestick/CandlestickView.ts
+++ b/src/chart/candlestick/CandlestickView.ts
@@ -106,6 +106,8 @@ class CandlestickView extends ChartView {
             group.removeAll();
         }
 
+        const transPointDim = getTransPointDimension(seriesModel);
+
         data.diff(oldData)
             .add(function (newIdx) {
                 if (data.hasValue(newIdx)) {
@@ -115,7 +117,7 @@ class CandlestickView extends ChartView {
                         return;
                     }
 
-                    const el = createNormalBox(itemLayout, newIdx, true);
+                    const el = createNormalBox(itemLayout, newIdx, 
transPointDim, true);
                     graphic.initProps(el, {shape: {points: itemLayout.ends}}, 
seriesModel, newIdx);
 
                     setBoxCommon(el, data, newIdx, isSimpleBox);
@@ -141,7 +143,7 @@ class CandlestickView extends ChartView {
                 }
 
                 if (!el) {
-                    el = createNormalBox(itemLayout, newIdx);
+                    el = createNormalBox(itemLayout, newIdx, transPointDim);
                 }
                 else {
                     graphic.updateProps(el, {
@@ -188,10 +190,12 @@ class CandlestickView extends ChartView {
         const data = seriesModel.getData();
         const isSimpleBox = data.getLayout('isSimpleBox');
 
+        const transPointDim = getTransPointDimension(seriesModel);
+
         let dataIndex;
         while ((dataIndex = params.next()) != null) {
             const itemLayout = data.getItemLayout(dataIndex) as 
CandlestickItemLayout;
-            const el = createNormalBox(itemLayout, dataIndex);
+            const el = createNormalBox(itemLayout, dataIndex, transPointDim);
             setBoxCommon(el, data, dataIndex, isSimpleBox);
 
             el.incremental = true;
@@ -262,12 +266,17 @@ class NormalBoxPath extends Path<NormalBoxPathProps> {
 }
 
 
-function createNormalBox(itemLayout: CandlestickItemLayout, dataIndex: number, 
isInit?: boolean) {
+function createNormalBox(
+    itemLayout: CandlestickItemLayout,
+    dataIndex: number,
+    constDim: number,
+    isInit?: boolean
+) {
     const ends = itemLayout.ends;
     return new NormalBoxPath({
         shape: {
             points: isInit
-                ? transInit(ends, itemLayout)
+                ? transInit(ends, constDim, itemLayout)
                 : ends
         },
         z2: 100
@@ -310,14 +319,18 @@ function setBoxCommon(el: NormalBoxPath, data: 
SeriesData, dataIndex: number, is
     toggleHoverEmphasis(el, emphasisModel.get('focus'), 
emphasisModel.get('blurScope'), emphasisModel.get('disabled'));
 }
 
-function transInit(points: number[][], itemLayout: CandlestickItemLayout) {
+function transInit(points: number[][], dim: number, itemLayout: 
CandlestickItemLayout) {
     return zrUtil.map(points, function (point) {
         point = point.slice();
-        point[1] = itemLayout.initBaseline;
+        point[dim] = itemLayout.initBaseline;
         return point;
     });
 }
 
+function getTransPointDimension(seriesModel: CandlestickSeriesModel): number {
+    return seriesModel.getWhiskerBoxesLayout() === 'horizontal' ? 1 : 0;
+}
+
 
 
 class LargeBoxPathShape {
diff --git a/src/chart/candlestick/candlestickLayout.ts 
b/src/chart/candlestick/candlestickLayout.ts
index 77e5c65d8..6b6fa03a6 100644
--- a/src/chart/candlestick/candlestickLayout.ts
+++ b/src/chart/candlestick/candlestickLayout.ts
@@ -51,8 +51,7 @@ const candlestickLayout: StageHandler = {
         const coordSys = seriesModel.coordinateSystem;
         const data = seriesModel.getData();
         const candleWidth = calculateCandleWidth(seriesModel, data);
-        const layout = seriesModel.get('layout');
-        const cDimIdx = layout === 'horizontal' ? 0 : 1;
+        const cDimIdx = seriesModel.getWhiskerBoxesLayout() === 'horizontal' ? 
0 : 1;
         const vDimIdx = 1 - cDimIdx;
         const coordDims = ['x', 'y'];
         const cDimI = 
data.getDimensionIndex(data.mapDimension(coordDims[cDimIdx]));
diff --git a/src/chart/helper/whiskerBoxCommon.ts 
b/src/chart/helper/whiskerBoxCommon.ts
index 891a0dd69..294fd0eae 100644
--- a/src/chart/helper/whiskerBoxCommon.ts
+++ b/src/chart/helper/whiskerBoxCommon.ts
@@ -30,6 +30,9 @@ import type Axis2D from '../../coord/cartesian/Axis2D';
 import { CoordDimensionDefinition } from '../../data/helper/createDimensions';
 
 interface CommonOption extends SeriesOption, SeriesOnCartesianOptionMixin {
+    // - 'horizontal': Multiple whisker boxes (each drawn vertically)
+    //      are arranged side by side horizontally.
+    // - 'vertical': The opposite.
     layout?: LayoutOrient
 
     // data?: (DataItemOption | number[])[]
@@ -44,14 +47,15 @@ interface DataItemOption {
 interface WhiskerBoxCommonMixin<Opts extends CommonOption> extends 
SeriesModel<Opts>{}
 class WhiskerBoxCommonMixin<Opts extends CommonOption> {
 
-    /**
-     * @private
-     * @type {string}
-     */
-    _baseAxisDim: string;
+    private _baseAxisDim: string;
 
     defaultValueDimensions: CoordDimensionDefinition['dimsDef'];
 
+    /**
+     * Computed layout.
+     */
+    private _layout: CommonOption['layout'];
+
     /**
      * @private
      */
@@ -76,28 +80,33 @@ class WhiskerBoxCommonMixin<Opts extends CommonOption> {
         const yAxisType = yAxisModel.get('type');
         let addOrdinal;
 
+        // Theoretically, if `encode` and/or `layout` are not specified, they 
can be derived from
+        // the specified one (also according to axis types). However, only the 
logic for deriving
+        // `encode` from `layout` is implemented; the reverse direction is not 
implemented yet,
+        // due to its complexity and low priority.
+        let layout = option.layout;
+        // 'category' axis has historically been enforcing `layout` regardless 
of its presence.
+        // This behavior is preserved until it causes problems.
         if (xAxisType === 'category') {
-            option.layout = 'horizontal';
+            layout = 'horizontal';
             ordinalMeta = xAxisModel.getOrdinalMeta();
             addOrdinal = !this._hasEncodeRule('x');
         }
         else if (yAxisType === 'category') {
-            option.layout = 'vertical';
+            layout = 'vertical';
             ordinalMeta = yAxisModel.getOrdinalMeta();
             addOrdinal = !this._hasEncodeRule('y');
         }
-        else if (xAxisType === 'time') {
-            option.layout = 'horizontal';
-        }
-        else if (yAxisType === 'time') {
-            option.layout = 'vertical';
-        }
-        else {
-            option.layout = option.layout || 'horizontal';
+        if (!layout) {
+            layout = yAxisType === 'time' ? 'vertical' : 'horizontal';
+            // It is theoretically possible for an axis with type "time" to 
serve as the "value axis".
+            // `layout` can be explicitly specified for that case.
         }
+        // Do not assign the computed `layout` to `option.layout`, otherwise 
the idempotent may be broken.
+        this._layout = layout;
 
         const coordDims = ['x', 'y'];
-        const baseAxisDimIndex = option.layout === 'horizontal' ? 0 : 1;
+        const baseAxisDimIndex = layout === 'horizontal' ? 0 : 1;
         const baseAxisDim = this._baseAxisDim = coordDims[baseAxisDimIndex];
         const otherAxisDim = coordDims[1 - baseAxisDimIndex];
         const axisModels = [xAxisModel, yAxisModel];
@@ -169,6 +178,10 @@ class WhiskerBoxCommonMixin<Opts extends CommonOption> {
         ) as CartesianAxisModel).axis;
     }
 
+    getWhiskerBoxesLayout() {
+        return this._layout;
+    }
+
 };
 
 
diff --git a/test/candlestick-horizontal.html b/test/candlestick-horizontal.html
index 49bf05f88..bc5fb0db4 100644
--- a/test/candlestick-horizontal.html
+++ b/test/candlestick-horizontal.html
@@ -41,6 +41,7 @@ under the License.
         <div id="main6"></div>
         <div id="main7"></div>
         <div id="main8"></div>
+        <div id="main9"></div>
 
         <script>
             require(["echarts"], function (echarts) {
@@ -69,7 +70,8 @@ under the License.
                     xAxisType,
                     yAxisType,
                     encode,
-                    data
+                    data,
+                    layout,
                 ) {
                     var itemStyle =
                         chartType === "candlestick"
@@ -101,6 +103,7 @@ under the License.
                                 type: chartType,
                                 encode: encode,
                                 data: data,
+                                layout: layout,
                                 itemStyle: itemStyle,
                             },
                         ],
@@ -221,6 +224,24 @@ under the License.
                             reversedaray
                         ),
                     },
+                    {
+                        id: "main9",
+                        title: "boxplot with dual time axes",
+                        option: createChartOption(
+                            "boxplot",
+                            "time",
+                            "time",
+                            { y: [0, 1, 2, 3, 4], x: 5 },
+                            reversedaray.map(item => {
+                                const newItem = item.slice();
+                                for (let i = 0; i < 5; i++) {
+                                    newItem[i] = new Date(newItem[i] + 
1761804046510).toISOString();
+                                }
+                                return newItem;
+                            }),
+                            'horizontal'
+                        ),
+                    },
                 ];
 
                 // Create all charts


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to