提交 32a6f76a 编写于 作者: P pissang

refact: add hover event handler on the view group to save memory. fix states bugs.

上级 444f6c79
......@@ -621,13 +621,13 @@ function createOrUpdateRepeatSymbols(
function onMouseOver() {
eachPath(bar, function (path) {
path.trigger('emphasis');
graphic.enterEmphasis(path);
});
}
function onMouseOut() {
eachPath(bar, function (path) {
path.trigger('normal');
graphic.leaveEmphasis(path);
});
}
}
......@@ -685,11 +685,11 @@ function createOrUpdateSingleSymbol(
updateHoverAnimation(mainPath, symbolMeta);
function onMouseOver(this: typeof mainPath) {
this.trigger('emphasis');
graphic.enterEmphasis(this);
}
function onMouseOut(this: typeof mainPath) {
this.trigger('normal');
graphic.leaveEmphasis(this);
}
}
......
......@@ -19,7 +19,7 @@
import * as zrUtil from 'zrender/src/core/util';
import {createSymbol} from '../../util/symbol';
import {Group, Path} from '../../util/graphic';
import {Group, Path, enterEmphasis, leaveEmphasis} from '../../util/graphic';
import {parsePercent} from '../../util/number';
import SymbolClz from './Symbol';
import List from '../../data/List';
......@@ -151,14 +151,14 @@ class EffectSymbol extends Group {
* Highlight symbol
*/
highlight() {
this.trigger('emphasis');
enterEmphasis(this);
}
/**
* Downplay symbol
*/
downplay() {
this.trigger('normal');
leaveEmphasis(this);
}
/**
......
......@@ -303,11 +303,11 @@ class Line extends graphic.Group {
}
highlight() {
this.trigger('emphasis');
graphic.enterEmphasis(this);
}
downplay() {
this.trigger('normal');
graphic.leaveEmphasis(this);
}
updateLayout(lineData: List, idx: number) {
......
......@@ -131,14 +131,14 @@ class Symbol extends graphic.Group {
* Highlight symbol
*/
highlight() {
this.childAt(0).trigger('emphasis');
graphic.enterEmphasis(this.childAt(0));
}
/**
* Downplay symbol
*/
downplay() {
this.childAt(0).trigger('normal');
graphic.leaveEmphasis(this.childAt(0));
}
/**
......@@ -363,8 +363,8 @@ function highDownOnUpdate(this: ECSymbol, fromState: DisplayState, toState: Disp
if (toState === 'emphasis') {
const ratio = scale[1] / scale[0];
const emphasisOpt = {
x: Math.max(scale[0] * 1.1, scale[0] + 3),
y: Math.max(scale[1] * 1.1, scale[1] + 3 * ratio)
scaleX: Math.max(scale[0] * 1.1, scale[0] + 3),
scaleY: Math.max(scale[1] * 1.1, scale[1] + 3 * ratio)
};
// FIXME
// modify it after support stop specified animation.
......
......@@ -365,6 +365,7 @@ class LineView extends ChartView {
}
render(seriesModel: LineSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) {
const coordSys = seriesModel.coordinateSystem;
const group = this.group;
const data = seriesModel.getData();
......@@ -655,6 +656,7 @@ class LineView extends ChartView {
shape: {
points: points
},
segmentIgnoreThreshold: 2,
silent: true,
z2: 10
});
......@@ -678,6 +680,7 @@ class LineView extends ChartView {
points: points,
stackedOnPoints: stackedOnPoints
},
segmentIgnoreThreshold: 2,
silent: true
});
......
......@@ -156,11 +156,11 @@ class SankeyPath extends graphic.Path<SankeyPathProps> {
}
highlight() {
this.trigger('emphasis');
graphic.enterEmphasis(this);
}
downplay() {
this.trigger('normal');
graphic.leaveEmphasis(this);
}
}
......@@ -346,11 +346,11 @@ class SankeyView extends ChartView {
}
el.highlight = function () {
this.trigger('emphasis');
graphic.enterEmphasis(this);
};
el.downplay = function () {
this.trigger('normal');
graphic.leaveEmphasis(this);
};
el.focusNodeAdjHandler && el.off('mouseover', el.focusNodeAdjHandler);
......
......@@ -237,6 +237,9 @@ class MapDraw {
compoundPath.style.strokeNoScale = true;
compoundPath.culling = true;
const compoundPathEmphasisState = compoundPath.ensureState('emphasis');
compoundPathEmphasisState.style = hoverItemStyle;
// Label
const showLabel = labelModel.get('show');
const hoverShowLabel = hoverLabelModel.get('show');
......@@ -311,7 +314,7 @@ class MapDraw {
// @ts-ignore FIXME:TS fix the "compatible with each other"?
regionGroup.highDownSilentOnTouch = !!mapOrGeoModel.get('selectedMode');
graphic.enableHoverEmphasis(regionGroup, hoverItemStyle);
graphic.enableHoverEmphasis(regionGroup);
regionsGroup.add(regionGroup);
});
......
......@@ -61,7 +61,8 @@ import {
ECUnitOption,
ZRColor,
ComponentMainType,
ComponentSubType
ComponentSubType,
ZRElementEvent
} from './util/types';
import Displayable from 'zrender/src/graphic/Displayable';
import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';
......@@ -1602,6 +1603,7 @@ class ECharts extends Eventful {
componentView.render(componentModel, ecModel, api, payload);
updateZ(componentModel, componentView);
updateHoverEmphasisHandler(componentView);
});
};
......@@ -1636,6 +1638,8 @@ class ECharts extends Eventful {
updateZ(seriesModel, chartView);
updateBlend(seriesModel, chartView);
updateHoverEmphasisHandler(chartView);
});
scheduler.unfinished |= unfinished;
......@@ -1712,6 +1716,7 @@ class ECharts extends Eventful {
z != null && (el.z = z);
zlevel != null && (el.zlevel = zlevel);
// TODO if textContent is on group.
const textContent = el.getTextContent();
if (textContent) {
textContent.z = el.z;
......@@ -1723,6 +1728,29 @@ class ECharts extends Eventful {
});
};
function getHighDownDispatcher(target: Element) {
while (target && !graphic.isHighDownDispatcher(target)) {
target = target.parent;
}
return target;
}
function onMouseOver(e: ZRElementEvent) {
const dispatcher = getHighDownDispatcher(e.target);
if (dispatcher) {
graphic.enterEmphasisWhenMouseOver(dispatcher, e);
}
}
function onMouseOut(e: ZRElementEvent) {
const dispatcher = getHighDownDispatcher(e.target);
if (dispatcher) {
graphic.leaveEmphasisWhenMouseOut(dispatcher, e);
}
}
updateHoverEmphasisHandler = function (view: ComponentView | ChartView): void {
view.group.on('mouseover', onMouseOver)
.on('mouseout', onMouseOut);
};
createExtensionAPI = function (ecIns: ECharts): ExtensionAPI {
return new (class extends ExtensionAPI {
getCoordinateSystems(): CoordinateSystemMaster[] {
......@@ -1820,6 +1848,7 @@ let performPostUpdateFuncs: (ecModel: GlobalModel, api: ExtensionAPI) => void;
let updateHoverLayerStatus: (ecIns: ECharts, ecModel: GlobalModel) => void;
let updateBlend: (seriesModel: SeriesModel, chartView: ChartView) => void;
let updateZ: (model: ComponentModel, view: ComponentView | ChartView) => void;
let updateHoverEmphasisHandler: (view: ComponentView | ChartView) => void;
let createExtensionAPI: (ecIns: ECharts) => ExtensionAPI;
let enableConnect: (chart: ECharts) => void;
......
......@@ -358,36 +358,43 @@ function liftColor(color: string): string {
return liftedColor;
}
function singleEnterEmphasis(el: Displayable) {
function singleEnterEmphasis(el: Element) {
(el as ExtendedElement).__highlighted = true;
// el may be an array.
if (!el.states.emphasis) {
return;
}
const emphasisStyle = el.states.emphasis.style;
const currentFill = el.style && el.style.fill;
const currentStroke = el.style && el.style.stroke;
const disp = el as Displayable;
const emphasisStyle = disp.states.emphasis.style;
const currentFill = disp.style && disp.style.fill;
const currentStroke = disp.style && disp.style.stroke;
el.useState('emphasis');
if (emphasisStyle && !hasFillOrStroke(emphasisStyle.fill)) {
el.style.fill = liftColor(currentFill);
}
if (emphasisStyle && !hasFillOrStroke(emphasisStyle.stroke)) {
el.style.stroke = liftColor(currentStroke);
if (disp.style) { // Is not group
if (emphasisStyle && !hasFillOrStroke(emphasisStyle.fill)) {
disp.style.fill = liftColor(currentFill);
}
if (emphasisStyle && !hasFillOrStroke(emphasisStyle.stroke)) {
disp.style.stroke = liftColor(currentStroke);
}
disp.z2 += Z2_EMPHASIS_LIFT;
}
el.z2 += Z2_EMPHASIS_LIFT;
const textContent = el.getTextContent();
if (textContent) {
textContent.z2 += Z2_EMPHASIS_LIFT;
}
// TODO hover layer
}
function singleEnterNormal(el: Displayable) {
function singleEnterNormal(el: Element) {
el.clearStates();
(el as ExtendedElement).__highlighted = false;
}
function traverseUpdate<T>(
......@@ -433,32 +440,32 @@ export function enableElementHoverEmphasis(el: Displayable, hoverStl?: ZRStylePr
}
}
function onElementMouseOver(this: ExtendedDisplayable, e: ElementEvent) {
!shouldSilent(this, e)
export function enterEmphasisWhenMouseOver(el: Element, e: ElementEvent) {
!shouldSilent(el, e)
// "emphasis" event highlight has higher priority than mouse highlight.
&& !this.__highByOuter
&& traverseUpdate(this, singleEnterEmphasis);
&& !(el as ExtendedElement).__highByOuter
&& traverseUpdate((el as ExtendedElement), singleEnterEmphasis);
}
function onElementMouseOut(this: ExtendedDisplayable, e: ElementEvent) {
!shouldSilent(this, e)
export function leaveEmphasisWhenMouseOut(el: Element, e: ElementEvent) {
!shouldSilent(el, e)
// "emphasis" event highlight has higher priority than mouse highlight.
&& !this.__highByOuter
&& traverseUpdate(this, singleEnterNormal);
&& !(el as ExtendedElement).__highByOuter
&& traverseUpdate((el as ExtendedElement), singleEnterNormal);
}
function onElementEmphasisEvent(this: ExtendedDisplayable, highlightDigit: number) {
this.__highByOuter |= 1 << (highlightDigit || 0);
traverseUpdate(this, singleEnterEmphasis);
export function enterEmphasis(el: Element, highlightDigit?: number) {
(el as ExtendedElement).__highByOuter |= 1 << (highlightDigit || 0);
traverseUpdate((el as ExtendedElement), singleEnterEmphasis);
}
function onElementNormalEvent(this: ExtendedDisplayable, highlightDigit: number) {
!(this.__highByOuter &= ~(1 << (highlightDigit || 0)))
&& traverseUpdate(this, singleEnterNormal);
export function leaveEmphasis(el: Element, highlightDigit?: number) {
!((el as ExtendedElement).__highByOuter &= ~(1 << (highlightDigit || 0)))
&& traverseUpdate((el as ExtendedElement), singleEnterNormal);
}
function shouldSilent(el: ExtendedDisplayable, e: ElementEvent) {
return el.__highDownSilentOnTouch && e.zrByTouch;
function shouldSilent(el: Element, e: ElementEvent) {
return (el as ExtendedElement).__highDownSilentOnTouch && e.zrByTouch;
}
/**
......@@ -471,10 +478,10 @@ function shouldSilent(el: ExtendedDisplayable, e: ElementEvent) {
* (1)
* Call the method for a "root" element once. Do not call it for each descendants.
* If the descendants elemenets of a group has itself hover style different from the
* root group, we can simply mount the style on `el.hoverStyle` for them, but should
* root group, we can simply mount the style on `el.states.emphasis` for them, but should
* not call this method for them.
*
* (2) These input parameters can be set directly on `el`:
* (2) The given hover style will replace the style in emphasis state already exists.
*/
export function enableHoverEmphasis(el: Element, hoverStyle?: ZRStyleProps) {
setAsHighDownDispatcher(el, true);
......@@ -530,12 +537,9 @@ export function setAsHighDownDispatcher(el: Element, asDispatcher: boolean) {
// Simple optimize, since this method might be
// called for each elements of a group in some cases.
if (!disable || extendedEl.__highDownDispatcher) {
const method: 'on' | 'off' = disable ? 'off' : 'on';
// Duplicated function will be auto-ignored, see Eventful.js.
el[method]('mouseover', onElementMouseOver)[method]('mouseout', onElementMouseOut);
// Emphasis, normal can be triggered manually by API or other components like hover link.
el[method]('emphasis', onElementEmphasisEvent)[method]('normal', onElementNormalEvent);
// el[method]('emphasis', onElementEmphasisEvent)[method]('normal', onElementNormalEvent);
// Also keep previous record.
extendedEl.__highByOuter = extendedEl.__highByOuter || 0;
......@@ -624,19 +628,17 @@ export function setLabelStyle<LDI>(
baseText = isFunction(opt.defaultText) ? opt.defaultText(labelDataIndex, opt) : opt.defaultText;
}
}
const normalStyleText = showNormal ? baseText : null;
const emphasisStyleText = showEmphasis
? retrieve2(
labelFetcher
? labelFetcher.getFormattedLabel(labelDataIndex, 'emphasis', null, labelDimIndex)
: null,
baseText
)
: null;
const normalStyleText = baseText;
const emphasisStyleText = retrieve2(
labelFetcher
? labelFetcher.getFormattedLabel(labelDataIndex, 'emphasis', null, labelDimIndex)
: null,
baseText
);
let richText = isSetOnRichText ? targetEl as RichText : null;
// Optimize: If style.text is null, text will not be drawn.
if (normalStyleText != null || emphasisStyleText != null) {
if (showNormal || showEmphasis) {
if (!isSetOnRichText) {
// Reuse the previous
richText = targetEl.getTextContent();
......@@ -644,11 +646,11 @@ export function setLabelStyle<LDI>(
richText = new RichText();
targetEl.setTextContent(richText);
}
richText.ignore = !normalStyleText;
}
richText.ignore = !showNormal;
const emphasisState = richText.ensureState('emphasis');
emphasisState.ignore = !emphasisStyleText;
emphasisState.ignore = !showEmphasis;
// Always set `textStyle` even if `normalStyle.text` is null, because default
// values have to be set on `normalStyle`.
......
......@@ -35,6 +35,7 @@ import {
} from '../util/types';
import { SeriesTaskContext, SeriesTask } from '../stream/Scheduler';
import List from '../data/List';
import { graphic } from '../export';
const inner = modelUtil.makeInner<{
updateMethod: keyof ChartView
......@@ -192,7 +193,9 @@ class ChartView {
*/
function elSetState(el: Element, state: DisplayState, highlightDigit: number) {
if (el) {
el.trigger(state, highlightDigit);
state === 'emphasis' ? graphicUtil.enterEmphasis(el, highlightDigit)
: graphicUtil.leaveEmphasis(el, highlightDigit);
if (el.isGroup
// Simple optimize.
&& !graphicUtil.isHighDownDispatcher(el)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册