You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by sh...@apache.org on 2020/10/19 09:35:28 UTC

[incubator-echarts] branch next updated: refact(label): provide general method for value animation

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

shenyi pushed a commit to branch next
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git


The following commit(s) were added to refs/heads/next by this push:
     new c358735  refact(label): provide general method for value animation
c358735 is described below

commit c3587358caf147b30fc99757caadb5aa2ec56766
Author: pissang <bm...@gmail.com>
AuthorDate: Mon Oct 19 17:32:44 2020 +0800

    refact(label): provide general method for value animation
---
 src/chart/bar/BarView.ts        | 30 +++++---------
 src/chart/helper/labelHelper.ts |  2 +-
 src/label/LabelManager.ts       | 23 +++++++----
 src/label/labelStyle.ts         | 87 ++++++++++++++++++++++++++++++++++++++++-
 src/util/graphic.ts             | 78 +-----------------------------------
 5 files changed, 113 insertions(+), 107 deletions(-)

diff --git a/src/chart/bar/BarView.ts b/src/chart/bar/BarView.ts
index 8cb3556..8e4469e 100644
--- a/src/chart/bar/BarView.ts
+++ b/src/chart/bar/BarView.ts
@@ -25,13 +25,11 @@ import {
     Sector,
     updateProps,
     initProps,
-    updateLabel,
-    initLabel,
     removeElementWithFadeOut
 } from '../../util/graphic';
 import { getECData } from '../../util/innerStore';
 import { enableHoverEmphasis, setStatesStylesFromModel } from '../../util/states';
-import { setLabelStyle, getLabelStatesModels, labelInner } from '../../label/labelStyle';
+import { setLabelStyle, getLabelStatesModels, labelInner, setLabelValueAnimation } from '../../label/labelStyle';
 import {throttle} from '../../util/throttle';
 import {createClipPath} from '../helper/createClipPathFromCoordSys';
 import Sausage from '../../util/shape/sausage';
@@ -291,16 +289,10 @@ class BarView extends ChartView {
                     el, data, dataIndex, itemModel, layout,
                     seriesModel, isHorizontalOrRadial, coord.type === 'polar'
                 );
-
-                initLabel(
-                    el, data, dataIndex, itemModel.getModel('label'), seriesModel, animationModel, defaultTextGetter
-                );
                 if (isInitSort) {
                     (el as Rect).attr({ shape: layout });
                 }
                 else if (realtimeSort) {
-                    (el as unknown as ECElement).disableLabelAnimation = true;
-
                     updateRealtimeAnimation(
                         seriesModel,
                         axis2DModel,
@@ -381,17 +373,12 @@ class BarView extends ChartView {
                         el, data, newIndex, itemModel, layout,
                         seriesModel, isHorizontalOrRadial, coord.type === 'polar'
                     );
-                    updateLabel(
-                        el, data, newIndex, itemModel.getModel('label'), seriesModel, animationModel, defaultTextGetter
-                    );
                 }
 
                 if (isInitSort) {
                     (el as Rect).attr({ shape: layout });
                 }
                 else if (realtimeSort) {
-                    (el as unknown as ECElement).disableLabelAnimation = true;
-
                     updateRealtimeAnimation(
                         seriesModel,
                         axis2DModel,
@@ -863,9 +850,10 @@ function updateStyle(
         const labelPositionOutside = isHorizontal
             ? ((layout as RectLayout).height > 0 ? 'bottom' as const : 'top' as const)
             : ((layout as RectLayout).width > 0 ? 'left' as const : 'right' as const);
+        const labelStatesModels = getLabelStatesModels(itemModel);
 
         setLabelStyle(
-            el, getLabelStatesModels(itemModel),
+            el, labelStatesModels,
             {
                 labelFetcher: seriesModel,
                 labelDataIndex: dataIndex,
@@ -876,11 +864,13 @@ function updateStyle(
         );
 
         const label = el.getTextContent();
-        if (label) {
-            const obj = labelInner(label);
-            obj.prevValue = obj.value;
-            obj.value = seriesModel.getRawValue(dataIndex) as ParsedValue | ParsedValue[];
-        }
+
+        setLabelValueAnimation(
+            label,
+            labelStatesModels,
+            seriesModel.getRawValue(dataIndex) as ParsedValue,
+            (value: number) => getDefaultInterpolatedLabel(data, value)
+        );
     }
 
     const emphasisModel = itemModel.getModel(['emphasis']);
diff --git a/src/chart/helper/labelHelper.ts b/src/chart/helper/labelHelper.ts
index 2396e93..5e45f21 100644
--- a/src/chart/helper/labelHelper.ts
+++ b/src/chart/helper/labelHelper.ts
@@ -49,7 +49,7 @@ export function getDefaultLabel(
 export function getDefaultInterpolatedLabel(
     data: List,
     interpolatedValue: ParsedValue | ParsedValue[]
-) {
+): string {
     const labelDims = data.mapDimensionsAll('defaultedLabel');
     if (!isArray(interpolatedValue)) {
         return interpolatedValue + '';
diff --git a/src/label/LabelManager.ts b/src/label/LabelManager.ts
index eb7e65e..76a41ca 100644
--- a/src/label/LabelManager.ts
+++ b/src/label/LabelManager.ts
@@ -51,6 +51,7 @@ import { retrieve2, each, keys, isFunction, filter, indexOf } from 'zrender/src/
 import { PathStyleProps } from 'zrender/src/graphic/Path';
 import Model from '../model/Model';
 import { prepareLayoutList, hideOverlap, shiftLayoutOnX, shiftLayoutOnY } from './labelLayoutHelper';
+import { labelInner, animateLabelValue } from './labelStyle';
 
 interface LabelDesc {
     label: ZRText
@@ -495,20 +496,26 @@ class LabelManager {
         if (textEl && !textEl.ignore && !textEl.invisible && !(el as ECElement).disableLabelAnimation) {
             const layoutStore = labelLayoutInnerStore(textEl);
             const oldLayout = layoutStore.oldLayout;
-            const dataIndex = getECData(el).dataIndex;
+            const ecData = getECData(el);
+            const dataIndex = ecData.dataIndex;
             const newProps = {
                 x: textEl.x,
                 y: textEl.y,
                 rotation: textEl.rotation
             };
+            const data = seriesModel.getData(ecData.dataType);
+
             if (!oldLayout) {
                 textEl.attr(newProps);
-                const oldOpacity = retrieve2(textEl.style.opacity, 1);
-                // Fade in animation
-                textEl.style.opacity = 0;
-                initProps(textEl, {
-                    style: { opacity: oldOpacity }
-                }, seriesModel, dataIndex);
+                // Disable fade in animation if value animation is enabled.
+                if (!labelInner(textEl).valueAnimation) {
+                    const oldOpacity = retrieve2(textEl.style.opacity, 1);
+                    // Fade in animation
+                    textEl.style.opacity = 0;
+                    initProps(textEl, {
+                        style: { opacity: oldOpacity }
+                    }, seriesModel, dataIndex);
+                }
             }
             else {
                 textEl.attr(oldLayout);
@@ -538,6 +545,8 @@ class LabelManager {
                 extendWithKeys(layoutEmphasis, newProps, LABEL_LAYOUT_PROPS);
                 extendWithKeys(layoutEmphasis, textEl.states.emphasis, LABEL_LAYOUT_PROPS);
             }
+
+            animateLabelValue(textEl, dataIndex, data, seriesModel);
         }
 
         if (guideLine && !guideLine.ignore && !guideLine.invisible) {
diff --git a/src/label/labelStyle.ts b/src/label/labelStyle.ts
index d166dcd..4471fb8 100644
--- a/src/label/labelStyle.ts
+++ b/src/label/labelStyle.ts
@@ -17,7 +17,10 @@ import GlobalModel from '../model/Global';
 import { isFunction, retrieve2, extend, keys, trim } from 'zrender/src/core/util';
 import { SPECIAL_STATES, DISPLAY_STATES } from '../util/states';
 import { deprecateReplaceLog } from '../util/log';
-import { makeInner } from '../util/model';
+import { makeInner, interpolateRawValues } from '../util/model';
+import List from '../data/List';
+import SeriesModel from '../model/Series';
+import { initProps, updateProps } from '../util/graphic';
 
 type TextCommonParams = {
     /**
@@ -586,7 +589,87 @@ export const labelInner = makeInner<{
      */
     value?: ParsedValue | ParsedValue[]
     /**
+     * If enable value animation
+     */
+    valueAnimation?: boolean
+    /**
+     * Label value precision during animation.
+     */
+    precision?: number | 'auto'
+
+    /**
+     * If enable value animation
+     */
+    statesModels?: LabelStatesModels<LabelModelForText>
+    /**
+     * Default text getter during interpolation
+     */
+    defaultInterpolatedText?: (value: ParsedValue[] | ParsedValue) => string
+    /**
      * Change label text from interpolated text during animation
      */
     setLabelText?(overrideValue?: ParsedValue | ParsedValue[]): void
-}, ZRText>();
\ No newline at end of file
+}, ZRText>();
+
+export function setLabelValueAnimation(
+    label: ZRText,
+    labelStatesModels: LabelStatesModels<LabelModelForText>,
+    value: ParsedValue | ParsedValue[],
+    getDefaultText: (value: ParsedValue[] | ParsedValue) => string
+) {
+    if (!label) {
+        return;
+    }
+
+    const obj = labelInner(label);
+    obj.prevValue = obj.value;
+    obj.value = value;
+
+    const normalLabelModel = labelStatesModels.normal;
+
+    obj.valueAnimation = normalLabelModel.get('valueAnimation');
+
+    if (obj.valueAnimation) {
+        obj.precision = normalLabelModel.get('precision');
+        obj.defaultInterpolatedText = getDefaultText;
+        obj.statesModels = labelStatesModels;
+    }
+}
+
+export function animateLabelValue(
+    textEl: ZRText,
+    dataIndex: number,
+    data: List,
+    seriesModel: SeriesModel
+) {
+    const labelInnerStore = labelInner(textEl);
+    if (!labelInnerStore.valueAnimation) {
+        return;
+    }
+    const defaultInterpolatedText = labelInnerStore.defaultInterpolatedText;
+    const prevValue = labelInnerStore.prevValue;
+    const currentValue = labelInnerStore.value;
+
+    function during(percent: number) {
+        const interpolated = interpolateRawValues(
+            data,
+            labelInnerStore.precision,
+            prevValue,
+            currentValue,
+            percent
+        );
+
+        const labelText = getLabelText({
+            labelDataIndex: dataIndex,
+            // labelFetcher: seriesModel,
+            defaultText: defaultInterpolatedText
+                ? defaultInterpolatedText(interpolated)
+                : interpolated + ''
+        }, labelInnerStore.statesModels, interpolated);
+
+        setLabelText(textEl, labelText);
+    }
+
+    (prevValue == null ? initProps
+        : updateProps)(textEl, {}, seriesModel, dataIndex, null, during);
+}
\ No newline at end of file
diff --git a/src/util/graphic.ts b/src/util/graphic.ts
index 01490d7..dfeb952 100644
--- a/src/util/graphic.ts
+++ b/src/util/graphic.ts
@@ -45,15 +45,13 @@ import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';
 import * as subPixelOptimizeUtil from 'zrender/src/graphic/helper/subPixelOptimize';
 import { Dictionary } from 'zrender/src/core/types';
 import Displayable, { DisplayableProps } from 'zrender/src/graphic/Displayable';
-import Element, { ElementProps } from 'zrender/src/Element';
+import Element from 'zrender/src/Element';
 import Model from '../model/Model';
 import {
     AnimationOptionMixin,
-    LabelOption,
     AnimationDelayCallbackParam,
     ZRRectLike,
     ZRStyleProps,
-    ParsedValue,
     PayloadAnimationPart
 } from './types';
 import {
@@ -63,12 +61,8 @@ import {
     defaults,
     isObject
 } from 'zrender/src/core/util';
-import SeriesModel from '../model/Series';
-import List from '../data/List';
-import { getLabelText, setLabelText, labelInner } from '../label/labelStyle';
 import { AnimationEasing } from 'zrender/src/animation/easing';
 import { getECData } from './innerStore';
-import {interpolateRawValues} from './model';
 
 
 const mathMax = Math.max;
@@ -531,76 +525,6 @@ export function isElementRemoved(el: Element) {
     return false;
 }
 
-function animateOrSetLabel<Props extends PathProps>(
-    animationType: 'init' | 'update' | 'remove',
-    el: Element<Props>,
-    data: List,
-    dataIndex: number,
-    labelModel: Model<LabelOption>,
-    seriesModel: SeriesModel,
-    animatableModel?: Model<AnimationOptionMixin>,
-    getDefaultText?: (value: ParsedValue[] | ParsedValue) => string
-) {
-    const valueAnimationEnabled = labelModel && labelModel.get('valueAnimation');
-    const label = el.getTextContent();
-    if (valueAnimationEnabled && label) {
-        const precision = labelModel ? labelModel.get('precision') : null;
-        const host = labelInner(label);
-
-        const sourceValue = host.prevValue;
-        const targetValue = host.value;
-
-        const during = (percent: number) => {
-            const text = el.getTextContent();
-            if (!text || !host) {
-                return;
-            }
-
-            const interpolated = interpolateRawValues(data, precision, sourceValue, targetValue, percent);
-
-            const labelText = getLabelText({
-                labelDataIndex: dataIndex,
-                labelFetcher: seriesModel,
-                defaultText: getDefaultText
-                    ? getDefaultText(interpolated)
-                    : interpolated + ''
-            }, {normal: labelModel}, interpolated);
-
-            setLabelText(text, labelText);
-        };
-
-        host.prevValue = targetValue;
-
-        const props: ElementProps = {};
-        animateOrSetProps(animationType, el, props, animatableModel, dataIndex, null, during);
-    }
-}
-
-
-export function updateLabel<Props>(
-    el: Element<Props>,
-    data: List,
-    dataIndex: number,
-    labelModel: Model<LabelOption>,
-    seriesModel: SeriesModel,
-    animatableModel?: Model<AnimationOptionMixin>,
-    defaultTextGetter?: (value: ParsedValue[] | ParsedValue) => string
-) {
-    animateOrSetLabel('update', el, data, dataIndex, labelModel, seriesModel, animatableModel, defaultTextGetter);
-}
-
-export function initLabel<Props>(
-    el: Element<Props>,
-    data: List,
-    dataIndex: number,
-    labelModel: Model<LabelOption>,
-    seriesModel: SeriesModel,
-    animatableModel?: Model<AnimationOptionMixin>,
-    defaultTextGetter?: (value: ParsedValue[] | ParsedValue) => string
-) {
-    animateOrSetLabel('init', el, data, dataIndex, labelModel, seriesModel, animatableModel, defaultTextGetter);
-}
-
 /**
  * Get transform matrix of target (param target),
  * in coordinate of its ancestor (param ancestor)


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