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

sushuang pushed a commit to branch PR/plainheart_fix/alignTicks-precision
in repository https://gitbox.apache.org/repos/asf/echarts.git

commit eb7530b3ed0687dcdc32eb68a9f2751386eb8333
Author: 100pah <[email protected]>
AuthorDate: Sun Mar 8 17:34:52 2026 +0800

    fix(appendData): Fix that the dataZoom inside is disabled when appendData 
is executed. And clarify the usage of appendData in comments.
---
 src/component/dataZoom/roams.ts | 119 ++++++++++++++++++++--------------------
 src/core/echarts.ts             |  31 ++++++-----
 src/core/lifecycle.ts           |   1 +
 src/util/model.ts               |   7 ++-
 src/util/types.ts               |  15 ++---
 test/candlestick-large3.html    |  21 ++++---
 6 files changed, 101 insertions(+), 93 deletions(-)

diff --git a/src/component/dataZoom/roams.ts b/src/component/dataZoom/roams.ts
index 38800b8c3..acd1b30fe 100644
--- a/src/component/dataZoom/roams.ts
+++ b/src/component/dataZoom/roams.ts
@@ -18,7 +18,7 @@
 */
 
 // Only create one roam controller for each coordinate system.
-// one roam controller might be refered by two inside data zoom
+// one roam controller might be referred by two inside data zoom
 // components (for example, one for x and one for y). When user
 // pan or zoom, only dispatch one action for those data zoom
 // components.
@@ -39,7 +39,6 @@ import { CoordinateSystemHostModel } from 
'../../coord/CoordinateSystem';
 import { DataZoomGetRangeHandlers } from './InsideZoomView';
 import { EChartsExtensionInstallRegisters } from '../../extension';
 
-
 interface DataZoomInfo {
     getRange: DataZoomGetRangeHandlers;
     model: InsideZoomModel;
@@ -240,71 +239,69 @@ function mergeControllerParams(
 
 export function installDataZoomRoamProcessor(registers: 
EChartsExtensionInstallRegisters) {
 
-    registers.registerProcessor(
-        registers.PRIORITY.PROCESSOR.FILTER,
-        function (ecModel: GlobalModel, api: ExtensionAPI): void {
-            const apiInner = inner(api);
-            const coordSysRecordMap = apiInner.coordSysRecordMap
-                || (apiInner.coordSysRecordMap = createHashMap<CoordSysRecord, 
string>());
-
-            coordSysRecordMap.each(function (coordSysRecord) {
-                // `coordSysRecordMap` always exists (because it holds the 
`roam controller`, which should
-                // better not re-create each time), but clear 
`dataZoomInfoMap` each round of the workflow.
-                coordSysRecord.dataZoomInfoMap = null;
-            });
+    registers.registerUpdateLifecycle('coordsys:aftercreate', (ecModel, api) 
=> {
+        const apiInner = inner(api);
+        const coordSysRecordMap = apiInner.coordSysRecordMap
+            || (apiInner.coordSysRecordMap = createHashMap<CoordSysRecord, 
string>());
 
-            ecModel.eachComponent(
-                { mainType: 'dataZoom', subType: 'inside' },
-                function (dataZoomModel: InsideZoomModel) {
-                    const dzReferCoordSysWrap = 
collectReferCoordSysModelInfo(dataZoomModel);
-
-                    each(dzReferCoordSysWrap.infoList, function 
(dzCoordSysInfo) {
-
-                        const coordSysUid = dzCoordSysInfo.model.uid;
-                        const coordSysRecord = 
coordSysRecordMap.get(coordSysUid)
-                            || coordSysRecordMap.set(coordSysUid, 
createCoordSysRecord(api, dzCoordSysInfo.model));
-
-                        const dataZoomInfoMap = coordSysRecord.dataZoomInfoMap
-                            || (coordSysRecord.dataZoomInfoMap = 
createHashMap<DataZoomInfo, string>());
-                        // Notice these props might be changed each time for a 
single dataZoomModel.
-                        dataZoomInfoMap.set(dataZoomModel.uid, {
-                            dzReferCoordSysInfo: dzCoordSysInfo,
-                            model: dataZoomModel,
-                            getRange: null
-                        });
-                    });
-                }
-            );
+        coordSysRecordMap.each(function (coordSysRecord) {
+            // `coordSysRecordMap` always exists (because it holds the `roam 
controller`, which should
+            // better not re-create each time), but clear `dataZoomInfoMap` 
each round of the workflow.
+            coordSysRecord.dataZoomInfoMap = null;
+        });
 
-            // (1) Merge dataZoom settings for each coord sys and set to the 
roam controller.
-            // (2) Clear coord sys if not refered by any dataZoom.
-            coordSysRecordMap.each(function (coordSysRecord) {
-                const controller = coordSysRecord.controller;
-                let firstDzInfo: DataZoomInfo;
-                const dataZoomInfoMap = coordSysRecord.dataZoomInfoMap;
-
-                if (dataZoomInfoMap) {
-                    const firstDzKey = dataZoomInfoMap.keys()[0];
-                    if (firstDzKey != null) {
-                        firstDzInfo = dataZoomInfoMap.get(firstDzKey);
-                    }
-                }
+        ecModel.eachComponent(
+            { mainType: 'dataZoom', subType: 'inside' },
+            function (dataZoomModel: InsideZoomModel) {
+                const dzReferCoordSysWrap = 
collectReferCoordSysModelInfo(dataZoomModel);
 
-                if (!firstDzInfo) {
-                    disposeCoordSysRecord(coordSysRecordMap, coordSysRecord);
-                    return;
+                each(dzReferCoordSysWrap.infoList, function (dzCoordSysInfo) {
+
+                    const coordSysUid = dzCoordSysInfo.model.uid;
+                    const coordSysRecord = coordSysRecordMap.get(coordSysUid)
+                        || coordSysRecordMap.set(coordSysUid, 
createCoordSysRecord(api, dzCoordSysInfo.model));
+
+                    const dataZoomInfoMap = coordSysRecord.dataZoomInfoMap
+                        || (coordSysRecord.dataZoomInfoMap = 
createHashMap<DataZoomInfo, string>());
+                    // Notice these props might be changed each time for a 
single dataZoomModel.
+                    dataZoomInfoMap.set(dataZoomModel.uid, {
+                        dzReferCoordSysInfo: dzCoordSysInfo,
+                        model: dataZoomModel,
+                        getRange: null
+                    });
+                });
+            }
+        );
+
+        // (1) Merge dataZoom settings for each coord sys and set to the roam 
controller.
+        // (2) Clear coord sys if not referred by any dataZoom.
+        coordSysRecordMap.each(function (coordSysRecord) {
+            const controller = coordSysRecord.controller;
+            let firstDzInfo: DataZoomInfo;
+            const dataZoomInfoMap = coordSysRecord.dataZoomInfoMap;
+
+            if (dataZoomInfoMap) {
+                const firstDzKey = dataZoomInfoMap.keys()[0];
+                if (firstDzKey != null) {
+                    firstDzInfo = dataZoomInfoMap.get(firstDzKey);
                 }
+            }
+
+            if (!firstDzInfo) {
+                disposeCoordSysRecord(coordSysRecordMap, coordSysRecord);
+                return;
+            }
 
-                const controllerParams = 
mergeControllerParams(dataZoomInfoMap, coordSysRecord, api);
-                controller.enable(controllerParams.controlType, 
controllerParams.opt);
+            const controllerParams = mergeControllerParams(dataZoomInfoMap, 
coordSysRecord, api);
+            controller.enable(controllerParams.controlType, 
controllerParams.opt);
 
-                throttleUtil.createOrUpdate(
-                    coordSysRecord,
-                    'dispatchAction',
-                    firstDzInfo.model.get('throttle', true),
-                    'fixRate'
-                );
-            });
+            throttleUtil.createOrUpdate(
+                coordSysRecord,
+                'dispatchAction',
+                firstDzInfo.model.get('throttle', true),
+                'fixRate'
+            );
+        });
     });
 
 }
diff --git a/src/core/echarts.ts b/src/core/echarts.ts
index ad5bb2bdc..a68bddad0 100644
--- a/src/core/echarts.ts
+++ b/src/core/echarts.ts
@@ -233,30 +233,31 @@ export const PRIORITY = {
  *
  *  - EC_PROGRESSIVE_CYCLE:
  *    - It also carries out a series of processing/updating/rendering, but out 
of EC_MAIN_CYCLE.
- *    - It is performed in each "animation frame".
- *    - It can be triggered internally or `appendData` call.
+ *    - It is performed in each subsequent "animation frame" until finished.
+ *    - It can be triggered by EC_MAIN_CYCLE or EC_APPEND_DATA_CYCLE.
  *    - A run of EC_PROGRESSIVE_CYCLE comprises:
  *      - Data processing (may be absent) (see `registerProcessor`)
  *      - Visual encoding (may be absent) (see `registerVisual`)
  *      - Layout (may be absent) (see `registerLayout`)
  *      - Rendering (`ComponentView` or `SeriesView`)
  *    - PENDING: currently all data processing tasks (via `registerProcessor`) 
run in "block" mode.
- *      (see `performDataProcessorTasks`)
+ *      (see `performDataProcessorTasks`).
  *
  *  - Other updating/rendering cycles:
+ *    - EC_APPEND_DATA_CYCLE (see `appendData`) is only supported for some 
special cases.
  *    - Some series have specific update/render cycles. For example, graph 
force layout performs
- *    layout and rendering in each "animation frame".
+ *      layout and rendering in each "animation frame".
  *
  *  - Model updating:
  *    - Model can only be modified at the beginning of ec cycles, including 
only:
  *      - EC_PREPARE_UPDATE (see method `prepare()`) in `setOption` call.
  *      - EC action handlers in `dispatchAction` call.
- *      - `appendData` (a special case, where only data is modified).
+ *      - `appendData` (a special case, where only data can be modified).
  *
  *  - The lifetime of CoordinateSystem/Axis/Scale instances:
- *    - They are only re-created per run of EC_FULL_UPDATE.
+ *    - They are only re-created per run of EC_FULL_UPDATE in EC_MAIN_CYCLE.
  *
- *  - Available caches: see `cycleCache.ts`
+ *  - Global caches: see `cycleCache.ts`
  */
 
 // See comments in EC_CYCLE.
@@ -1612,13 +1613,13 @@ class ECharts extends Eventful<ECEventDefinition> {
 
         seriesModel.appendData(params);
 
-        // Note: `appendData` does not support that update extent of coordinate
-        // system, util some scenario require that. In the expected usage of
-        // `appendData`, the initial extent of coordinate system should better
-        // be fixed by axis `min`/`max` setting or initial data, otherwise if
-        // the extent changed while `appendData`, the location of the painted
-        // graphic elements have to be changed, which make the usage of
-        // `appendData` meaningless.
+        // NOTICE:
+        // `appendData` does not support to update axis scale extent of 
coordinate
+        // systems. In the expected usage of `appendData`, the initial extent 
of
+        // coordinate system should be explicitly specified (by `xxxAxis.data` 
for
+        // 'category' axis or by `xxxAxis.min/max` for other axes). Otherwise, 
if
+        // the extent keep changing while `appendData`, the location of the 
painted
+        // graphic elements have to be changed frequently.
 
         this._scheduler.unfinished = true;
 
@@ -1873,6 +1874,8 @@ class ECharts extends Eventful<ECEventDefinition> {
                 // In LineView may save the old coordinate system and use it 
to get the original point.
                 coordSysMgr.create(ecModel, api);
 
+                lifecycle.trigger('coordsys:aftercreate', ecModel, api);
+
                 scheduler.performDataProcessorTasks(ecModel, payload);
 
                 // Current stream render is not supported in data process. So 
we can update
diff --git a/src/core/lifecycle.ts b/src/core/lifecycle.ts
index 933aca567..f42d8b38b 100644
--- a/src/core/lifecycle.ts
+++ b/src/core/lifecycle.ts
@@ -54,6 +54,7 @@ export interface UpdateLifecycleParams {
 }
 interface LifecycleEvents {
     'afterinit': [EChartsType],
+    'coordsys:aftercreate': [GlobalModel, ExtensionAPI],
     'series:beforeupdate': [GlobalModel, ExtensionAPI, UpdateLifecycleParams],
     'series:layoutlabels': [GlobalModel, ExtensionAPI, UpdateLifecycleParams],
     'series:transition': [GlobalModel, ExtensionAPI, UpdateLifecycleParams],
diff --git a/src/util/model.ts b/src/util/model.ts
index 95d7df3d6..382eeff06 100644
--- a/src/util/model.ts
+++ b/src/util/model.ts
@@ -48,13 +48,12 @@ import {
     OptionName,
     InterpolatableValue,
     NullUndefined,
-    UNDEFINED_STR,
 } from './types';
 import { Dictionary } from 'zrender/src/core/types';
 import SeriesModel from '../model/Series';
 import CartesianAxisModel from '../coord/cartesian/AxisModel';
 import type GridModel from '../coord/cartesian/GridModel';
-import { isNumeric, getRandomIdBase, getPrecision, round, MAX_SAFE_INTEGER } 
from './number';
+import { isNumeric, getRandomIdBase, getPrecision, round } from './number';
 import { error, warn } from './log';
 import type Model from '../model/Model';
 
@@ -718,6 +717,10 @@ export function queryDataIndex(data: SeriesData, payload: 
Payload & {
 }
 
 /**
+ * [CAVEAT]:
+ *  DO NOT use it in performance-sensitive scenarios.
+ *  Likely a hash map lookup; not inline-cache friendly.
+ *
  * Enable property storage to any host object.
  * Notice: Serialization is not supported.
  *
diff --git a/src/util/types.ts b/src/util/types.ts
index aebc93ce6..c885c1353 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -385,13 +385,14 @@ export interface StageHandler {
      * A SERIES_STAGE_TASK is owned by a pipeline and is specific to a single 
series.
      *
      * The `reset` method is called iff this task is "dirty" (See 
`Task['dirty']`).
-     * Task `dirty()` call typically originates from:
-     *  - A trigger of EC_MAIN_CYCLE (including EC_FULL_UPDATE and 
EC_PARTIAL_UPDATE)
-     *    (See comments in EC_CYCLE)
-     *  - NOTICE: `dirtyOnOverallProgress: true` cause that the corresponding 
`overallReset`
-     *    and `reset` of downsteams tasks may also be called in 
EC_PROGRESSIVE_CYCLE.
-     *    But in this case, `CoordinateSystem#create` and 
`CoordinateSystem#update` are
-     *    not called.
+     * Task `dirty()` call typically originates from a trigger of 
EC_MAIN_CYCLE (including
+     * EC_FULL_UPDATE and EC_PARTIAL_UPDATE) (See comments in EC_CYCLE)
+     *
+     * NOTICE: `dirtyOnOverallProgress: true` cause that the corresponding 
`overallReset`
+     *  and `reset` of downsteams tasks may also be called in 
EC_PROGRESSIVE_CYCLE.
+     *  But in this case, `CoordinateSystem#create` and 
`CoordinateSystem#update` are not called.
+     *  Only lifecycle like `coordsys:aftercreate` can be ensured to be only 
called in EC_FULL_UPDATE
+     *  of EC_MAIN_CYCLE, but not in EC_PROGRESSIVE_CYCLE and 
EC_APPEND_DATA_CYCLE.
      */
     reset?: StageHandlerReset;
 
diff --git a/test/candlestick-large3.html b/test/candlestick-large3.html
index 5f58a89b9..6c64b7afd 100644
--- a/test/candlestick-large3.html
+++ b/test/candlestick-large3.html
@@ -63,10 +63,11 @@ under the License.
             var xValueMax = rawDataChunkSize * chunkCount;
             var yValueMin = Infinity;
             var yValueMax = -Infinity;
-
+            var xData = [];
             var rawData = [];
+
             for (var i = 0; i < chunkCount; i++) {
-                rawData.push(generateOHLC(rawDataChunkSize));
+                generateOHLC(rawDataChunkSize, rawData);
             }
             yValueMax = Math.ceil(yValueMax);
             yValueMin = Math.floor(yValueMin);
@@ -75,7 +76,6 @@ under the License.
 
                 frameInsight.init(echarts, 'duration');
 
-                // var data = generateOHLC(rawDataChunkSize);
                 var chart = window.chart = init();
 
                 var loadedChunkIndex = 0;
@@ -99,7 +99,7 @@ under the License.
             }
 
             function generateOHLC(count) {
-                var data = [];
+                var seriesData = [];
 
                 var tmpVals = new Array(4);
                 var dayRange = 12;
@@ -125,10 +125,12 @@ under the License.
                         closeIdx++;
                     }
 
+                    var xValIdx = xData.length;
+                    xData.push(echarts.format.formatTime('yyyy-MM-dd 
hh:mm:ss', xValue += minute));
                     // ['open', 'close', 'lowest', 'highest']
                     // [1, 4, 3, 2]
-                    data.push([
-                        echarts.format.formatTime('yyyy-MM-dd hh:mm:ss', 
xValue += minute),
+                    seriesData.push([
+                        xValIdx,
                         +tmpVals[openIdx].toFixed(2), // open
                         +tmpVals[3].toFixed(2), // highest
                         +tmpVals[0].toFixed(2), // lowest
@@ -136,7 +138,7 @@ under the License.
                     ]);
                 }
 
-                return data;
+                rawData.push(seriesData);
             }
 
             function calculateMA(dayCount, data) {
@@ -208,8 +210,9 @@ under the License.
                             axisLine: {onZero: false},
                             splitLine: {show: false},
                             splitNumber: 20,
-                            min: xValueMin,
-                            max: xValueMax
+                            // min: xValueMin,
+                            // max: xValueMax,
+                            data: xData,
                         },
                         // {
                         //     type: 'category',


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

Reply via email to