This is an automated email from the ASF dual-hosted git repository.
shenyi pushed a commit to branch label-enhancement
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git
The following commit(s) were added to refs/heads/label-enhancement by this push:
new 17eb9c0 feat(state): add stateAnimation in all series. use state in
sunburst.
17eb9c0 is described below
commit 17eb9c0bbd95c0135bacaad8f55f97cf23a74bdf
Author: pissang <[email protected]>
AuthorDate: Fri May 15 16:25:51 2020 +0800
feat(state): add stateAnimation in all series. use state in sunburst.
---
src/chart/gauge/GaugeView.ts | 4 +-
src/chart/pie/PieView.ts | 13 +-
src/chart/sunburst/SunburstPiece.ts | 296 ++++++++++++++++-------------------
src/chart/sunburst/SunburstSeries.ts | 5 +-
src/chart/sunburst/SunburstView.ts | 6 +-
src/echarts.ts | 25 ++-
src/model/Model.ts | 62 ++++----
src/model/Series.ts | 7 +-
src/model/globalDefault.ts | 8 +-
src/util/graphic.ts | 145 +++++------------
src/util/types.ts | 10 ++
src/visual/style.ts | 2 +-
12 files changed, 259 insertions(+), 324 deletions(-)
diff --git a/src/chart/gauge/GaugeView.ts b/src/chart/gauge/GaugeView.ts
index 77e3c8c..db84a9b 100644
--- a/src/chart/gauge/GaugeView.ts
+++ b/src/chart/gauge/GaugeView.ts
@@ -424,7 +424,7 @@ class GaugeView extends ChartView {
text: data.getName(0),
align: 'center',
verticalAlign: 'middle'
- }, {autoColor: autoColor, forceRich: true})
+ }, {autoColor: autoColor})
}));
}
}
@@ -464,7 +464,7 @@ class GaugeView extends ChartView {
height: isNaN(height) ? null : height,
align: 'center',
verticalAlign: 'middle'
- }, {autoColor: autoColor, forceRich: true})
+ }, {autoColor: autoColor})
}));
}
}
diff --git a/src/chart/pie/PieView.ts b/src/chart/pie/PieView.ts
index 56d1ac6..aa1b0d3 100644
--- a/src/chart/pie/PieView.ts
+++ b/src/chart/pie/PieView.ts
@@ -27,8 +27,6 @@ import ExtensionAPI from '../../ExtensionAPI';
import { Payload, ColorString } from '../../util/types';
import List from '../../data/List';
import PieSeriesModel, {PieDataItemOption} from './PieSeries';
-import { ElementAnimateConfig } from 'zrender/src/Element';
-import labelLayout from './labelLayout';
function updateDataSelected(
this: PiePiece,
@@ -48,13 +46,9 @@ function updateDataSelected(
seriesId: seriesModel.id
});
- const animationCfg: ElementAnimateConfig = {
- duration: seriesModel.get('animation') ? 200 : 0,
- easing: 'cubicOut'
- };
data.each(function (idx) {
const el = data.getItemGraphicEl(idx);
- el.toggleState('select', seriesModel.isSelected(data.getName(idx)),
animationCfg);
+ el.toggleState('select', seriesModel.isSelected(data.getName(idx)));
});
}
@@ -173,10 +167,7 @@ class PiePiece extends graphic.Sector {
graphic.enableHoverEmphasis(this);
// Switch after `select` state updated.
- sector.toggleState('select',
seriesModel.isSelected(data.getName(idx)), {
- duration: seriesModel.get('animation') ? 200 : 0,
- easing: 'cubicOut'
- });
+ sector.toggleState('select',
seriesModel.isSelected(data.getName(idx)));
}
private _updateLabel(data: List, idx: number, withAnimation: boolean):
void {
diff --git a/src/chart/sunburst/SunburstPiece.ts
b/src/chart/sunburst/SunburstPiece.ts
index aa44e40..0afe37a 100644
--- a/src/chart/sunburst/SunburstPiece.ts
+++ b/src/chart/sunburst/SunburstPiece.ts
@@ -19,11 +19,13 @@
import * as zrUtil from 'zrender/src/core/util';
import * as graphic from '../../util/graphic';
-import { ColorString } from '../../util/types';
import { TreeNode } from '../../data/Tree';
import SunburstSeriesModel, { SunburstSeriesNodeItemOption,
SunburstSeriesOption } from './SunburstSeries';
import GlobalModel from '../../model/Global';
import { AllPropTypes } from 'zrender/src/core/types';
+import { PathStyleProps } from 'zrender/src/graphic/Path';
+import { ColorString } from '../../util/types';
+import Model from '../../model/Model';
const NodeHighlightPolicy = {
NONE: 'none', // not downplay others
@@ -41,7 +43,7 @@ interface DrawTreeNode extends TreeNode {
/**
* Sunburstce of Sunburst including Sector, Label, LabelLine
*/
-class SunburstPiece extends graphic.Group {
+class SunburstPiece extends graphic.Sector {
node: TreeNode;
@@ -51,22 +53,20 @@ class SunburstPiece extends graphic.Group {
constructor(node: TreeNode, seriesModel: SunburstSeriesModel, ecModel:
GlobalModel) {
super();
- const sector = new graphic.Sector({
- z2: DEFAULT_SECTOR_Z,
- textConfig: {
- inside: true
- }
- });
- this.add(sector);
- graphic.getECData(sector).seriesIndex = seriesModel.seriesIndex;
+ this.z2 = DEFAULT_SECTOR_Z;
+ this.textConfig = {
+ inside: true
+ };
+
+ graphic.getECData(this).seriesIndex = seriesModel.seriesIndex;
const text = new graphic.Text({
z2: DEFAULT_TEXT_Z,
silent:
node.getModel<SunburstSeriesNodeItemOption>().get(['label', 'silent'])
});
- sector.setTextContent(text);
+ this.setTextContent(text);
- this.updateData(true, node, 'normal', seriesModel, ecModel);
+ this.updateData(true, node, seriesModel, ecModel);
// Hover to change label and labelLine
// FIXME
@@ -85,7 +85,7 @@ class SunburstPiece extends graphic.Group {
updateData(
firstCreate: boolean,
node: TreeNode,
- state: 'emphasis' | 'normal' | 'highlight' | 'downplay',
+ // state: 'emphasis' | 'normal' | 'highlight' | 'downplay',
seriesModel?: SunburstSeriesModel,
ecModel?: GlobalModel
) {
@@ -95,7 +95,7 @@ class SunburstPiece extends graphic.Group {
seriesModel = seriesModel || this._seriesModel;
ecModel = ecModel || this._ecModel;
- const sector = this.childAt(0) as graphic.Sector;
+ const sector = this;
graphic.getECData(sector).dataIndex = node.dataIndex;
const itemModel = node.getModel<SunburstSeriesNodeItemOption>();
@@ -108,23 +108,13 @@ class SunburstPiece extends graphic.Group {
// const visualColor = getNodeColor(node, seriesModel, ecModel);
// fillDefaultColor(node, seriesModel, visualColor);
- const normalStyle = node.getVisual('style');
- let style;
- if (state === 'normal') {
- style = normalStyle;
- }
- else {
- const stateStyle = itemModel.getModel([state, 'itemStyle'])
- .getItemStyle();
- style = zrUtil.merge(stateStyle, normalStyle);
- }
- // style = zrUtil.defaults(
- // {
- // lineJoin: 'bevel',
- // fill: style.fill || visualColor
- // },
- // style
- // );
+ const normalStyle = node.getVisual('style') as PathStyleProps;
+ normalStyle.lineJoin = 'bevel';
+
+ zrUtil.each(['emphasis', 'highlight', 'downplay'] as const, function
(stateName) {
+ const state = sector.ensureState(stateName);
+ state.style = itemModel.getModel([stateName,
'itemStyle']).getItemStyle();
+ });
if (firstCreate) {
sector.setShape(sectorShape);
@@ -139,26 +129,16 @@ class SunburstPiece extends graphic.Group {
seriesModel,
node.dataIndex
);
- sector.useStyle(style);
- }
- else if (typeof style.fill === 'object' && style.fill.type
- || typeof sector.style.fill === 'object' && sector.style.fill.type
- ) {
- // Disable animation for gradient since no interpolation method
- // is supported for gradient
- graphic.updateProps(sector, {
- shape: sectorShape
- }, seriesModel);
- sector.useStyle(style);
- }
- else {
- graphic.updateProps(sector, {
- shape: sectorShape,
- style: style
- }, seriesModel);
}
- this._updateLabel(seriesModel, style.fill, state);
+ // Disable animation for gradient since no interpolation method
+ // is supported for gradient
+ graphic.updateProps(sector, {
+ shape: sectorShape
+ }, seriesModel);
+ sector.useStyle(normalStyle);
+
+ this._updateLabel(seriesModel);
const cursorStyle = itemModel.getShallow('cursor');
cursorStyle && sector.attr('cursor', cursorStyle);
@@ -177,13 +157,13 @@ class SunburstPiece extends graphic.Group {
this.node.hostTree.root.eachNode(function (n: DrawTreeNode) {
if (n.piece) {
if (that.node === n) {
- n.piece.updateData(false, n, 'emphasis');
+ n.piece.useState('emphasis', true);
}
else if (isNodeHighlighted(n, that.node, highlightPolicy)) {
- n.piece.childAt(0).trigger('highlight');
+ n.piece.useState('highlight', true);
}
else if (highlightPolicy !== NodeHighlightPolicy.NONE) {
- n.piece.childAt(0).trigger('downplay');
+ n.piece.useState('downplay', true);
}
}
});
@@ -192,141 +172,139 @@ class SunburstPiece extends graphic.Group {
onNormal() {
this.node.hostTree.root.eachNode(function (n: DrawTreeNode) {
if (n.piece) {
- n.piece.updateData(false, n, 'normal');
+ n.piece.clearStates();
+ // n.piece.updateData(false, n, 'normal');
}
});
}
onHighlight() {
- this.updateData(false, this.node, 'highlight');
+ this.removeState('downplay');
+ this.useState('highlight', true);
}
onDownplay() {
- this.updateData(false, this.node, 'downplay');
+ this.removeState('highlight');
+ this.useState('downplay', true);
}
_updateLabel(
- seriesModel: SunburstSeriesModel,
- visualColor: ColorString,
- state: 'emphasis' | 'normal' | 'highlight' | 'downplay'
+ seriesModel: SunburstSeriesModel
) {
const itemModel = this.node.getModel<SunburstSeriesNodeItemOption>();
- const normalModel = itemModel.getModel('label');
- const labelModel = state === 'normal' || state === 'emphasis'
- ? normalModel
- : itemModel.getModel([state, 'label']);
- const labelHoverModel = itemModel.getModel(['emphasis', 'label']);
-
- let text = zrUtil.retrieve(
- seriesModel.getFormattedLabel(this.node.dataIndex, state),
- this.node.name
- );
- if (getLabelAttr('show') === false) {
- text = '';
- }
+ const normalLabelModel = itemModel.getModel('label');
const layout = this.node.getLayout();
- let labelMinAngle = labelModel.get('minAngle');
- if (labelMinAngle == null) {
- labelMinAngle = normalModel.get('minAngle');
- }
- labelMinAngle = labelMinAngle / 180 * Math.PI;
const angle = layout.endAngle - layout.startAngle;
- if (labelMinAngle != null && Math.abs(angle) < labelMinAngle) {
- // Not displaying text when angle is too small
- text = '';
- }
-
- const sector = this.childAt(0);
- const label = sector.getTextContent();
-
const midAngle = (layout.startAngle + layout.endAngle) / 2;
const dx = Math.cos(midAngle);
const dy = Math.sin(midAngle);
- let r;
- const labelPosition = getLabelAttr('position');
- const labelPadding = getLabelAttr('distance') || 0;
- let textAlign = getLabelAttr('align');
- if (labelPosition === 'outside') {
- r = layout.r + labelPadding;
- textAlign = midAngle > Math.PI / 2 ? 'right' : 'left';
- }
- else {
- if (!textAlign || textAlign === 'center') {
- r = (layout.r + layout.r0) / 2;
- textAlign = 'center';
+ const sector = this;
+ const label = sector.getTextContent();
+ const dataIndex = this.node.dataIndex;
+
+ zrUtil.each(['normal', 'emphasis', 'highlight', 'downplay'] as const,
(stateName) => {
+
+ const labelStateModel = stateName === 'normal' ?
itemModel.getModel('label')
+ : itemModel.getModel([stateName, 'label']);
+ const labelMinAngle = labelStateModel.get('minAngle') / 180 *
Math.PI;
+ const isNormal = stateName === 'normal';
+
+ const state = isNormal ? label : label.ensureState(stateName);
+ let text = seriesModel.getFormattedLabel(dataIndex, stateName);
+ if (isNormal) {
+ text = text || this.node.name;
}
- else if (textAlign === 'left') {
- r = layout.r0 + labelPadding;
- if (midAngle > Math.PI / 2) {
- textAlign = 'right';
- }
+
+ state.style = graphic.createTextStyle(labelStateModel, {
+ }, null, stateName !== 'normal', true);
+ if (text) {
+ state.style.text = text;
}
- else if (textAlign === 'right') {
- r = layout.r - labelPadding;
- if (midAngle > Math.PI / 2) {
- textAlign = 'left';
- }
+
+ // Not displaying text when angle is too small
+ state.ignore = labelMinAngle != null && Math.abs(angle) <
labelMinAngle;
+
+ const labelPosition = getLabelAttr(labelStateModel, 'position');
+
+ const sectorState = isNormal ? sector : sector.states[stateName];
+ const labelColor = sectorState.style.fill as ColorString;
+ sectorState.textConfig = {
+ inside: labelPosition !== 'outside'
+ };
+ if (labelColor) {
+ sectorState.textConfig.insideStroke =
sectorState.textConfig.outsideFill = labelColor;
}
- }
- graphic.setLabelStyle(
- label, normalModel, labelHoverModel,
- {
- defaultText: labelModel.getShallow('show') ? text : null
+ let r;
+ const labelPadding = getLabelAttr(labelStateModel, 'distance') ||
0;
+ let textAlign = getLabelAttr(labelStateModel, 'align');
+ if (labelPosition === 'outside') {
+ r = layout.r + labelPadding;
+ textAlign = midAngle > Math.PI / 2 ? 'right' : 'left';
+ }
+ else {
+ if (!textAlign || textAlign === 'center') {
+ r = (layout.r + layout.r0) / 2;
+ textAlign = 'center';
+ }
+ else if (textAlign === 'left') {
+ r = layout.r0 + labelPadding;
+ if (midAngle > Math.PI / 2) {
+ textAlign = 'right';
+ }
+ }
+ else if (textAlign === 'right') {
+ r = layout.r - labelPadding;
+ if (midAngle > Math.PI / 2) {
+ textAlign = 'left';
+ }
+ }
}
- );
- sector.setTextConfig({
- inside: labelPosition !== 'outside',
- insideStroke: visualColor,
- // insideFill: 'auto',
- outsideFill: visualColor
- });
- label.attr('style', {
- text: text,
- align: textAlign,
- verticalAlign: getLabelAttr('verticalAlign') || 'middle',
- opacity: getLabelAttr('opacity')
- });
+ state.style.align = textAlign;
+ state.style.verticalAlign = getLabelAttr(labelStateModel,
'verticalAlign') || 'middle';
- label.x = r * dx + layout.cx;
- label.y = r * dy + layout.cy;
+ state.x = r * dx + layout.cx;
+ state.y = r * dy + layout.cy;
- const rotateType = getLabelAttr('rotate');
- let rotate = 0;
- if (rotateType === 'radial') {
- rotate = -midAngle;
- if (rotate < -Math.PI / 2) {
- rotate += Math.PI;
+ const rotateType = getLabelAttr(labelStateModel, 'rotate');
+ let rotate = 0;
+ if (rotateType === 'radial') {
+ rotate = -midAngle;
+ if (rotate < -Math.PI / 2) {
+ rotate += Math.PI;
+ }
}
- }
- else if (rotateType === 'tangential') {
- rotate = Math.PI / 2 - midAngle;
- if (rotate > Math.PI / 2) {
- rotate -= Math.PI;
+ else if (rotateType === 'tangential') {
+ rotate = Math.PI / 2 - midAngle;
+ if (rotate > Math.PI / 2) {
+ rotate -= Math.PI;
+ }
+ else if (rotate < -Math.PI / 2) {
+ rotate += Math.PI;
+ }
}
- else if (rotate < -Math.PI / 2) {
- rotate += Math.PI;
+ else if (typeof rotateType === 'number') {
+ rotate = rotateType * Math.PI / 180;
}
- }
- else if (typeof rotateType === 'number') {
- rotate = rotateType * Math.PI / 180;
- }
- label.attr('rotation', rotate);
- type LabelOption = SunburstSeriesNodeItemOption['label'];
- function getLabelAttr<T extends keyof LabelOption>(name: T):
LabelOption[T] {
- const stateAttr = labelModel.get(name);
+ state.rotation = rotate;
+ });
+
+
+ type LabelOpt = SunburstSeriesOption['label'];
+ function getLabelAttr<T extends keyof LabelOpt>(model:
Model<LabelOpt>, name: T): LabelOpt[T] {
+ const stateAttr = model.get(name);
if (stateAttr == null) {
- return normalModel.get(name);
- }
- else {
- return stateAttr;
+ return normalLabelModel.get(name) as LabelOpt[T];
}
+ return stateAttr;
}
+
+ label.dirtyStyle();
}
_initEvents(
@@ -351,15 +329,13 @@ class SunburstPiece extends graphic.Group {
that.onHighlight();
};
- if (seriesModel.isAnimationEnabled()) {
- sector
- .on('mouseover', onEmphasis)
- .on('mouseout', onNormal)
- .on('emphasis', onEmphasis)
- .on('normal', onNormal)
- .on('downplay', onDownplay)
- .on('highlight', onHighlight);
- }
+ sector
+ .on('mouseover', onEmphasis)
+ .on('mouseout', onNormal)
+ .on('emphasis', onEmphasis)
+ .on('normal', onNormal)
+ .on('downplay', onDownplay)
+ .on('highlight', onHighlight);
}
}
diff --git a/src/chart/sunburst/SunburstSeries.ts
b/src/chart/sunburst/SunburstSeries.ts
index 327a1ab..0b4fdd6 100644
--- a/src/chart/sunburst/SunburstSeries.ts
+++ b/src/chart/sunburst/SunburstSeries.ts
@@ -242,7 +242,10 @@ class SunburstSeriesModel extends
SeriesModel<SunburstSeriesOption> {
},
downplay: {
itemStyle: {
- opacity: 0.9
+ opacity: 0.5
+ },
+ label: {
+ opacity: 0.6
}
},
diff --git a/src/chart/sunburst/SunburstView.ts
b/src/chart/sunburst/SunburstView.ts
index bef20f9..6a3e4f8 100644
--- a/src/chart/sunburst/SunburstView.ts
+++ b/src/chart/sunburst/SunburstView.ts
@@ -130,7 +130,7 @@ class SunburstView extends ChartView {
if (newNode) {
// Update
oldNode.piece.updateData(
- false, newNode, 'normal', seriesModel, ecModel);
+ false, newNode, seriesModel, ecModel);
// For tooltip
data.setItemGraphicEl(newNode.dataIndex,
oldNode.piece);
@@ -172,7 +172,7 @@ class SunburstView extends ChartView {
if (self.virtualPiece) {
// Update
self.virtualPiece.updateData(
- false, virtualRoot, 'normal', seriesModel, ecModel);
+ false, virtualRoot, seriesModel, ecModel);
}
else {
// Add
@@ -208,7 +208,7 @@ class SunburstView extends ChartView {
const viewRoot = this.seriesModel.getViewRoot();
viewRoot.eachNode((node: DrawTreeNode) => {
if (!targetFound
- && node.piece && node.piece.childAt(0) === e.target
+ && node.piece && node.piece === e.target
) {
const nodeClick =
node.getModel<SunburstSeriesNodeItemOption>().get('nodeClick');
if (nodeClick === 'rootToNode') {
diff --git a/src/echarts.ts b/src/echarts.ts
index b92fcd7..ddca382 100644
--- a/src/echarts.ts
+++ b/src/echarts.ts
@@ -1673,6 +1673,8 @@ class ECharts extends Eventful {
updateBlend(seriesModel, chartView);
+ updateStates(seriesModel, chartView);
+
updateHoverEmphasisHandler(chartView);
// Add albels.
@@ -1681,8 +1683,8 @@ class ECharts extends Eventful {
scheduler.unfinished = unfinished || scheduler.unfinished;
- labelManager.updateLayoutConfig(api);
- labelManager.layout();
+ // labelManager.updateLayoutConfig(api);
+ // labelManager.layout();
// If use hover layer
updateHoverLayerStatus(ecIns, ecModel);
@@ -1753,7 +1755,7 @@ class ECharts extends Eventful {
const zlevel = model.get('zlevel');
// Set z and zlevel
view.group.traverse(function (el: Displayable) {
- if (el.type !== 'group') {
+ if (!el.isGroup) {
z != null && (el.z = z);
zlevel != null && (el.zlevel = zlevel);
@@ -1769,6 +1771,22 @@ class ECharts extends Eventful {
});
};
+ updateStates = function (seriesModel: SeriesModel, view: ChartView):
void {
+ const stateAnimationModel = seriesModel.getModel('stateAnimation');
+ const enableAnimation = seriesModel.isAnimationEnabled();
+ view.group.traverse(function (el: Displayable) {
+ if (el.states && el.states.emphasis) {
+ if (enableAnimation) {
+ // TODO textContent?
+ graphic.setStateTransition(el, stateAnimationModel);
+ }
+ else if (el.stateTransition) {
+ el.stateTransition = null;
+ }
+ }
+ });
+ };
+
function getHighDownDispatcher(target: Element) {
while (target && !graphic.isHighDownDispatcher(target)) {
target = target.parent;
@@ -1888,6 +1906,7 @@ let renderSeries: (
let performPostUpdateFuncs: (ecModel: GlobalModel, api: ExtensionAPI) => void;
let updateHoverLayerStatus: (ecIns: ECharts, ecModel: GlobalModel) => void;
let updateBlend: (seriesModel: SeriesModel, chartView: ChartView) => void;
+let updateStates: (model: SeriesModel, chartView: ChartView) => void;
let updateZ: (model: ComponentModel, view: ComponentView | ChartView) => void;
let updateHoverEmphasisHandler: (view: ComponentView | ChartView) => void;
let createExtensionAPI: (ecIns: ECharts) => ExtensionAPI;
diff --git a/src/model/Model.ts b/src/model/Model.ts
index 3f42f72..a2f588f 100644
--- a/src/model/Model.ts
+++ b/src/model/Model.ts
@@ -169,37 +169,37 @@ class Model<Opt extends ModelOption = ModelOption> {
// TODO: TYPE use unkown
*
* @param deepMerge If do deep merge. Default to be false.
*/
- squash(
- deepMerge?: boolean,
- handleCallback?: (func: () => object) => object
- ) {
- const optionStack = [];
- let model: Model = this;
- while (model) {
- if (model.option) {
- optionStack.push(model.option);
- }
- model = model.parentModel;
- }
-
- const newOption = {} as Opt;
- let option;
- while (option = optionStack.pop()) { // Top down merge
- if (isFunction(option) && handleCallback) {
- option = handleCallback(option);
- }
- if (deepMerge) {
- merge(newOption, option);
- }
- else {
- extend(newOption, option);
- }
- }
-
- // Remove parentModel
- this.option = newOption;
- this.parentModel = null;
- }
+ // squash(
+ // deepMerge?: boolean,
+ // handleCallback?: (func: () => object) => object
+ // ) {
+ // const optionStack = [];
+ // let model: Model = this;
+ // while (model) {
+ // if (model.option) {
+ // optionStack.push(model.option);
+ // }
+ // model = model.parentModel;
+ // }
+
+ // const newOption = {} as Opt;
+ // let option;
+ // while (option = optionStack.pop()) { // Top down merge
+ // if (isFunction(option) && handleCallback) {
+ // option = handleCallback(option);
+ // }
+ // if (deepMerge) {
+ // merge(newOption, option);
+ // }
+ // else {
+ // extend(newOption, option);
+ // }
+ // }
+
+ // // Remove parentModel
+ // this.option = newOption;
+ // this.parentModel = null;
+ // }
/**
* If model has option
diff --git a/src/model/Series.ts b/src/model/Series.ts
index fbceb6f..bce6b82 100644
--- a/src/model/Series.ts
+++ b/src/model/Series.ts
@@ -534,10 +534,7 @@ class SeriesModel<Opt extends SeriesOption = SeriesOption>
extends ComponentMode
};
}
- /**
- * @return {boolean}
- */
- isAnimationEnabled() {
+ isAnimationEnabled(): boolean {
if (env.node) {
return false;
}
@@ -547,7 +544,7 @@ class SeriesModel<Opt extends SeriesOption = SeriesOption>
extends ComponentMode
animationEnabled = false;
}
}
- return animationEnabled;
+ return !!animationEnabled;
}
restoreData() {
diff --git a/src/model/globalDefault.ts b/src/model/globalDefault.ts
index ad2199b..fe4feb3 100644
--- a/src/model/globalDefault.ts
+++ b/src/model/globalDefault.ts
@@ -59,13 +59,19 @@ export default {
// Default is source-over
blendMode: null,
+ stateAnimation: {
+ duration: 300,
+ easing: 'cubicOut'
+ },
+
animation: 'auto',
animationDuration: 1000,
animationDurationUpdate: 300,
- animationEasing: 'exponentialOut',
+ animationEasing: 'cubicOut',
animationEasingUpdate: 'cubicOut',
animationThreshold: 2000,
+
// Configuration for progressive/incremental rendering
progressiveThreshold: 3000,
progressive: 400,
diff --git a/src/util/graphic.ts b/src/util/graphic.ts
index ea75df7..182b69c 100644
--- a/src/util/graphic.ts
+++ b/src/util/graphic.ts
@@ -60,7 +60,8 @@ import {
ColorString,
DataModel,
ECEventData,
- ZRStyleProps
+ ZRStyleProps,
+ AnimationOption
} from './types';
import GlobalModel from '../model/Global';
import { makeInner } from './model';
@@ -127,8 +128,6 @@ type TextCommonParams = {
*/
autoColor?: ColorString
- forceRich?: boolean
-
getTextPosition?: (textStyleModel: Model, isEmphasis?: boolean) => string
| string[] | number[]
defaultOutsidePosition?: LabelOption['position']
@@ -379,19 +378,13 @@ function singleEnterEmphasis(el: Element) {
return;
}
- el.useState('emphasis', true, {
- duration: 300,
- // TODO Configuration
- easing: 'cubicOut'
- });
+ el.useState('emphasis', true);
// TODO hover layer
}
function singleLeaveEmphasis(el: Element) {
- el.removeState('emphasis', {
- duration: 300
- });
+ el.removeState('emphasis');
(el as ExtendedElement).__highlighted = false;
}
@@ -549,6 +542,23 @@ export function enableHoverEmphasis(el: Element,
hoverStyle?: ZRStyleProps) {
}
/**
+ * Set animation config on state transition.
+ */
+export function setStateTransition(el: Element, animatableModel:
Model<AnimationOption>) {
+ const duration = animatableModel.get('duration');
+ if (duration > 0) {
+ el.stateTransition = {
+ duration,
+ delay: animatableModel.get('delay'),
+ easing: animatableModel.get('easing')
+ };
+ }
+ else if (el.stateTransition) {
+ el.stateTransition = null;
+ }
+}
+
+/**
* @param {module:zrender/Element} el
* @param {Function} [el.onStateChange] Called when state updated.
* Since `setHoverStyle` has the constraint that it must be called after
@@ -648,37 +658,6 @@ interface SetLabelStyleOpt<LDI> extends TextCommonParams {
}
-// function handleSquashCallback<LDI>(
-// func: Function,
-// labelDataIndex: LDI,
-// labelFetcher: SetLabelStyleOpt<LDI>['labelFetcher'],
-// rect: RectLike,
-// status: DisplayState
-// ) {
-// let params: {
-// status?: DisplayState
-// rect?: RectLike
-// };
-// if (labelFetcher && labelFetcher.getDataParams) {
-// params = labelFetcher.getDataParams(labelDataIndex);
-// }
-// else {
-// params = {};
-// }
-// params.status = status;
-// params.rect = rect;
-// return func(params);
-// }
-
-// function getGlobalBoundingRect(el: Element) {
-// const rect = el.getBoundingRect().clone();
-// const transform = el.getComputedTransform();
-// if (transform) {
-// rect.applyTransform(transform);
-// }
-// return rect;
-// }
-
type LabelModel = Model<LabelOption & {
formatter?: string | ((params: any) => string)
}>;
@@ -717,33 +696,9 @@ function setLabelStyle<LDI>(
const labelDataIndex = opt.labelDataIndex;
const labelDimIndex = opt.labelDimIndex;
- // TODO Performance optimization
- // normalModel.squash(false, function (func: Function) {
- // return handleSquashCallback(
- // func,
- // labelDataIndex,
- // labelFetcher,
- // isSetOnText ? null : getGlobalBoundingRect(targetEl),
- // 'normal'
- // );
- // });
-
- // emphasisModel.squash(false, function (func: Function) {
- // return handleSquashCallback(
- // func,
- // labelDataIndex,
- // labelFetcher,
- // isSetOnText ? null : getGlobalBoundingRect(targetEl),
- // 'emphasis'
- // );
- // });
-
const showNormal = normalModel.getShallow('show');
const showEmphasis = emphasisModel.getShallow('show');
- // Consider performance, only fetch label when necessary.
- // If `normal.show` is `false` and `emphasis.show` is `true` and
`emphasis.formatter` is not set,
- // label should be displayed, where text is fetched by `normal.formatter`
or `opt.defaultText`.
let richText = isSetOnText ? targetEl as ZRText : null;
if (showNormal || showEmphasis) {
let baseText;
@@ -780,12 +735,6 @@ function setLabelStyle<LDI>(
const emphasisState = richText.ensureState('emphasis');
emphasisState.ignore = !showEmphasis;
- // Always set `textStyle` even if `normalStyle.text` is null, because
default
- // values have to be set on `normalStyle`.
- // If we set default values on `emphasisStyle`, consider case:
- // Firstly, `setOption(... label: {normal: {text: null}, emphasis:
{show: true}} ...);`
- // Secondly, `setOption(... label: {noraml: {show: true, text: 'abc',
color: 'red'} ...);`
- // Then the 'red' will not work on emphasis.
const normalStyle = createTextStyle(
normalModel,
normalSpecified,
@@ -848,12 +797,12 @@ export {setLabelStyle};
export function createTextStyle(
textStyleModel: Model,
specifiedTextStyle?: TextStyleProps, // Can be overrided by settings in
model.
- opt?: TextCommonParams,
- isEmphasis?: boolean,
+ opt?: Pick<TextCommonParams, 'autoColor' | 'disableBox'>,
+ isNotNormal?: boolean,
isAttached?: boolean // If text is attached on an element. If so, auto
color will handling in zrender.
) {
const textStyle: TextStyleProps = {};
- setTextStyleCommon(textStyle, textStyleModel, opt, isEmphasis, isAttached);
+ setTextStyleCommon(textStyle, textStyleModel, opt, isNotNormal,
isAttached);
specifiedTextStyle && extend(textStyle, specifiedTextStyle);
// textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false);
@@ -863,25 +812,25 @@ export function createTextStyle(
export function createTextConfig(
textStyle: TextStyleProps,
textStyleModel: Model,
- opt?: TextCommonParams,
- isEmphasis?: boolean
+ opt?: Pick<TextCommonParams, 'getTextPosition' | 'defaultOutsidePosition'
| 'autoColor'>,
+ isNotNormal?: boolean
) {
const textConfig: ElementTextConfig = {};
let labelPosition;
let labelRotate = textStyleModel.getShallow('rotate');
const labelDistance = retrieve2(
- textStyleModel.getShallow('distance'), isEmphasis ? null : 5
+ textStyleModel.getShallow('distance'), isNotNormal ? null : 5
);
const labelOffset = textStyleModel.getShallow('offset');
if (opt.getTextPosition) {
- labelPosition = opt.getTextPosition(textStyleModel, isEmphasis);
+ labelPosition = opt.getTextPosition(textStyleModel, isNotNormal);
}
else {
labelPosition = textStyleModel.getShallow('position')
- || (isEmphasis ? null : 'inside');
+ || (isNotNormal ? null : 'inside');
// 'outside' is not a valid zr textPostion value, but used
- // in bar series, and magric type should be considered.
+ // in bar series, and magic type should be considered.
labelPosition === 'outside' && (labelPosition =
opt.defaultOutsidePosition || 'top');
}
@@ -905,17 +854,6 @@ export function createTextConfig(
// Set default stroke, which is useful when label is over other
// messy graphics (like lines) in background.
textConfig.outsideStroke = 'rgba(255, 255, 255, 0.9)';
- // if (!textStyle.fill) {
- // textConfig.insideFill = 'auto';
- // textConfig.outsideFill = opt.autoColor || null;
- // }
- // if (!textStyle.stroke) {
- // textConfig.insideStroke = 'auto';
- // }
- // else if (opt.autoColor) {
- // // TODO: stroke set to autoColor. if label is inside?
- // textConfig.insideStroke = opt.autoColor;
- // }
return textConfig;
}
@@ -933,8 +871,8 @@ export function createTextConfig(
function setTextStyleCommon(
textStyle: TextStyleProps,
textStyleModel: Model,
- opt?: TextCommonParams,
- isEmphasis?: boolean,
+ opt?: Pick<TextCommonParams, 'autoColor' | 'disableBox'>,
+ isNotNormal?: boolean,
isAttached?: boolean
) {
// Consider there will be abnormal when merge hover style to normal style
if given default value.
@@ -970,7 +908,7 @@ function setTextStyleCommon(
// the default color `'blue'` will not be adopted if no color
declared in `rich`.
// That might confuses users. So probably we should put
`textStyleModel` as the
// root ancestor of the `richTextStyle`. But that would be a
break change.
- setTokenTextStyle(richResult[name] = {}, richTextStyle,
globalTextStyle, opt, isEmphasis, isAttached);
+ setTokenTextStyle(richResult[name] = {}, richTextStyle,
globalTextStyle, opt, isNotNormal, isAttached);
}
}
}
@@ -983,12 +921,7 @@ function setTextStyleCommon(
textStyle.overflow = overflow;
}
- setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt,
isEmphasis, isAttached, true);
-
- // TODO
- if (opt.forceRich && !opt.textStyle) {
- opt.textStyle = {};
- }
+ setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt,
isNotNormal, isAttached, true);
}
// Consider case:
@@ -1025,7 +958,7 @@ function getRichItemNames(textStyleModel:
Model<LabelOption>) {
}
const TEXT_PROPS_WITH_GLOBAL = [
- 'fontStyle', 'fontWeight', 'fontSize', 'fontFamily',
+ 'fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'opacity',
'textShadowColor', 'textShadowBlur', 'textShadowOffsetX',
'textShadowOffsetY'
] as const;
@@ -1043,13 +976,13 @@ function setTokenTextStyle(
textStyle: TextStyleProps['rich'][string],
textStyleModel: Model<LabelOption>,
globalTextStyle: LabelOption,
- opt?: TextCommonParams,
- isEmphasis?: boolean,
+ opt?: Pick<TextCommonParams, 'autoColor' | 'disableBox'>,
+ isNotNormal?: boolean,
isAttached?: boolean,
isBlock?: boolean
) {
// In merge mode, default value should not be given.
- globalTextStyle = !isEmphasis && globalTextStyle || EMPTY_OBJ;
+ globalTextStyle = !isNotNormal && globalTextStyle || EMPTY_OBJ;
const autoColor = opt && opt.autoColor;
let fillColor = textStyleModel.getShallow('color');
@@ -1078,7 +1011,7 @@ function setTokenTextStyle(
}
// TODO
- if (!isEmphasis && !isAttached) {
+ if (!isNotNormal && !isAttached) {
// Set default finally.
if (textStyle.fill == null && opt.autoColor) {
textStyle.fill = opt.autoColor;
diff --git a/src/util/types.ts b/src/util/types.ts
index ea3c3b8..d9bbd1b 100644
--- a/src/util/types.ts
+++ b/src/util/types.ts
@@ -546,6 +546,11 @@ export type AnimationDelayCallbackParam = {
export type AnimationDurationCallback = (idx: number) => number;
export type AnimationDelayCallback = (idx: number, params?:
AnimationDelayCallbackParam) => number;
+export interface AnimationOption {
+ duration?: number
+ easing?: AnimationEasing
+ delay?: number
+}
/**
* Mixin of option set to control the animation of series.
*/
@@ -1122,6 +1127,11 @@ export interface SeriesOption extends
* Global label layout option in label layout stage.
*/
labelLayout?: LabelLayoutOption | LabelLayoutOptionCallback
+
+ /**
+ * Animation config for state transition.
+ */
+ stateAnimation?: AnimationOption
}
export interface SeriesOnCartesianOptionMixin {
diff --git a/src/visual/style.ts b/src/visual/style.ts
index 605edee..1d52fcf 100644
--- a/src/visual/style.ts
+++ b/src/visual/style.ts
@@ -187,7 +187,7 @@ const dataColorPaletteTask: StageHandler = {
idxMap[rawIdx] = idx;
});
- // Iterate on dat before filtered. To make sure color from palette
can be
+ // Iterate on data before filtered. To make sure color from
palette can be
// Consistent when toggling legend.
dataAll.each(function (rawIdx) {
const idx = idxMap[rawIdx];
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]