You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by ov...@apache.org on 2022/07/04 09:32:28 UTC

[echarts] 01/02: fix(axis): add time axis special tick logic

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

ovilia pushed a commit to branch fix-17198
in repository https://gitbox.apache.org/repos/asf/echarts.git

commit a9a39296669299ed5951526bfe8c6cc2859296e7
Author: Ovilia <zw...@gmail.com>
AuthorDate: Mon Jul 4 15:04:01 2022 +0800

    fix(axis): add time axis special tick logic
---
 src/coord/Axis.ts                 |   1 +
 src/coord/axisTickLabelBuilder.ts | 112 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 113 insertions(+)

diff --git a/src/coord/Axis.ts b/src/coord/Axis.ts
index 7a334a0a4..ebbfbb221 100644
--- a/src/coord/Axis.ts
+++ b/src/coord/Axis.ts
@@ -193,6 +193,7 @@ class Axis {
             this, ticksCoords, alignWithLabel, opt.clamp
         );
 
+        console.log('ticksCoords', ticksCoords);
         return ticksCoords;
     }
 
diff --git a/src/coord/axisTickLabelBuilder.ts b/src/coord/axisTickLabelBuilder.ts
index fbc2e5c97..b56442573 100644
--- a/src/coord/axisTickLabelBuilder.ts
+++ b/src/coord/axisTickLabelBuilder.ts
@@ -31,6 +31,7 @@ import { AxisBaseOption } from './axisCommonTypes';
 import OrdinalScale from '../scale/Ordinal';
 import { AxisBaseModel } from './AxisBaseModel';
 import type Axis2D from './cartesian/Axis2D';
+import { TimeScaleTick } from '../util/types';
 
 type CacheKey = string | number;
 
@@ -72,6 +73,8 @@ export function createAxisLabels(axis: Axis): {
     // Only ordinal scale support tick interval
     return axis.type === 'category'
         ? makeCategoryLabels(axis)
+        : axis.type === 'time'
+        ? makeTimeLabels(axis)
         : makeRealNumberLabels(axis);
 }
 
@@ -90,6 +93,8 @@ export function createAxisTicks(axis: Axis, tickModel: AxisBaseModel): {
     // Only ordinal scale support tick interval
     return axis.type === 'category'
         ? makeCategoryTicks(axis, tickModel)
+        : axis.type === 'time'
+        ? makeTimeTicks(axis, tickModel)
         : {ticks: zrUtil.map(axis.scale.getTicks(), tick => tick.value) };
 }
 
@@ -102,6 +107,15 @@ function makeCategoryLabels(axis: Axis) {
         : result;
 }
 
+function makeTimeLabels(axis: Axis) {
+    const labelModel = axis.getLabelModel();
+    const result = makeTimeLabelsActually(axis, labelModel);
+
+    return (!labelModel.get('show') || axis.scale.isBlank())
+        ? {labels: []}
+        : result;
+}
+
 function makeCategoryLabelsActually(axis: Axis, labelModel: Model<AxisBaseOption['axisLabel']>) {
     const labelsCache = getListCache(axis, 'labels');
     const optionLabelInterval = getOptionCategoryInterval(labelModel);
@@ -129,6 +143,104 @@ function makeCategoryLabelsActually(axis: Axis, labelModel: Model<AxisBaseOption
     });
 }
 
+function makeTimeLabelsActually(axis: Axis, labelModel: Model<AxisBaseOption['axisLabel']>) {
+    const labelsCache = getListCache(axis, 'labels');
+    const timeKey = 'time'; // TODO: change key name
+    const result = listCacheGet(labelsCache, timeKey);
+
+    if (result) {
+        return result;
+    }
+
+    const labels = makeNonOverlappedTimeLabels(axis);
+
+    // Cache to avoid calling interval function repeatly.
+    return listCacheSet(labelsCache, timeKey, {
+        labels: labels
+    });
+}
+
+function makeNonOverlappedTimeLabels(axis: Axis): MakeLabelsResultObj[];
+function makeNonOverlappedTimeLabels(axis: Axis, onlyTick: false): MakeLabelsResultObj[];
+function makeNonOverlappedTimeLabels(axis: Axis, onlyTick: true): number[];
+function makeNonOverlappedTimeLabels(axis: Axis, onlyTick?: boolean) {
+    const ticks = axis.scale.getTicks() as TimeScaleTick[];
+    const ordinalScale = axis.scale as OrdinalScale;
+    const labelFormatter = makeLabelFormatter(axis);
+
+    const result: (MakeLabelsResultObj | number)[] = [];
+
+    function addItem(tickValue: number) {
+        const tickObj = { value: tickValue };
+        result.push(onlyTick
+            ? tickValue
+            : {
+                formattedLabel: labelFormatter(tickObj),
+                rawLabel: ordinalScale.getLabel(tickObj),  // TODO: ?
+                tickValue: tickValue
+            }
+        );
+    }
+
+    let lastMaxLevel = Number.MAX_VALUE;
+    let maxLevel;
+    while (true) {
+        maxLevel = -1;
+
+        for (let i = 0; i < ticks.length; i++) {
+            if (ticks[i].level > maxLevel && ticks[i].level < lastMaxLevel) {
+                maxLevel = ticks[i].level;
+            }
+        }
+
+        if (maxLevel < 0) {
+            break;
+        }
+
+        for (let i = 0; i < ticks.length; i++) {
+            const tick = ticks[i];
+            if (tick.level === maxLevel) {
+                // Add the tick only if it has no overlap with current ones
+                 // TODO:
+                addItem(tick.value);
+            }
+        }
+
+        if (maxLevel <= 0) {
+            break;
+        }
+        lastMaxLevel = maxLevel;
+    }
+    return result;
+}
+
+function makeTimeTicks(axis: Axis, tickModel: AxisBaseModel) {
+    const ticksCache = getListCache(axis, 'ticks');
+    const result = listCacheGet(ticksCache, 'time');
+
+    if (result) {
+        return result;
+    }
+
+    let ticks: number[];
+
+    // Optimize for the case that large category data and no label displayed,
+    // we should not return all ticks.
+    if (!tickModel.get('show') || axis.scale.isBlank()) {
+        ticks = [];
+    }
+
+    const labelsResult = makeTimeLabelsActually(axis, axis.getLabelModel());
+    ticks = zrUtil.map(labelsResult.labels, function (labelItem) {
+        return labelItem.tickValue;
+    });
+
+    // Cache to avoid calling interval function repeatly.
+    return listCacheSet(ticksCache, 'time', {
+        ticks: ticks
+    });
+}
+
 function makeCategoryTicks(axis: Axis, tickModel: AxisBaseModel) {
     const ticksCache = getListCache(axis, 'ticks');
     const optionTickInterval = getOptionCategoryInterval(tickModel);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org