states.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. /**
  20. * AUTO-GENERATED FILE. DO NOT MODIFY.
  21. */
  22. /*
  23. * Licensed to the Apache Software Foundation (ASF) under one
  24. * or more contributor license agreements. See the NOTICE file
  25. * distributed with this work for additional information
  26. * regarding copyright ownership. The ASF licenses this file
  27. * to you under the Apache License, Version 2.0 (the
  28. * "License"); you may not use this file except in compliance
  29. * with the License. You may obtain a copy of the License at
  30. *
  31. * http://www.apache.org/licenses/LICENSE-2.0
  32. *
  33. * Unless required by applicable law or agreed to in writing,
  34. * software distributed under the License is distributed on an
  35. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  36. * KIND, either express or implied. See the License for the
  37. * specific language governing permissions and limitations
  38. * under the License.
  39. */
  40. import { extend, indexOf, isArrayLike, isObject, keys, isArray, each } from 'zrender/lib/core/util.js';
  41. import { getECData } from './innerStore.js';
  42. import { liftColor } from 'zrender/lib/tool/color.js';
  43. import { queryDataIndex, makeInner } from './model.js';
  44. import Path from 'zrender/lib/graphic/Path.js';
  45. import { getViewOfComponentOrSeries } from '../core/ExtensionAPI.js';
  46. import { error } from './log.js';
  47. // Reserve 0 as default.
  48. var _highlightNextDigit = 1;
  49. var _highlightKeyMap = {};
  50. var getSavedStates = makeInner();
  51. var getComponentStates = makeInner();
  52. export var HOVER_STATE_NORMAL = 0;
  53. export var HOVER_STATE_BLUR = 1;
  54. export var HOVER_STATE_EMPHASIS = 2;
  55. export var SPECIAL_STATES = ['emphasis', 'blur', 'select'];
  56. export var DISPLAY_STATES = ['normal', 'emphasis', 'blur', 'select'];
  57. export var Z2_EMPHASIS_LIFT = 10;
  58. export var Z2_SELECT_LIFT = 9;
  59. export var HIGHLIGHT_ACTION_TYPE = 'highlight';
  60. export var DOWNPLAY_ACTION_TYPE = 'downplay';
  61. export var SELECT_ACTION_TYPE = 'select';
  62. export var UNSELECT_ACTION_TYPE = 'unselect';
  63. export var TOGGLE_SELECT_ACTION_TYPE = 'toggleSelect';
  64. export var SELECT_CHANGED_EVENT_TYPE = 'selectchanged';
  65. function hasFillOrStroke(fillOrStroke) {
  66. return fillOrStroke != null && fillOrStroke !== 'none';
  67. }
  68. function doChangeHoverState(el, stateName, hoverStateEnum) {
  69. if (el.onHoverStateChange && (el.hoverState || 0) !== hoverStateEnum) {
  70. el.onHoverStateChange(stateName);
  71. }
  72. el.hoverState = hoverStateEnum;
  73. }
  74. function singleEnterEmphasis(el) {
  75. // Only mark the flag.
  76. // States will be applied in the echarts.ts in next frame.
  77. doChangeHoverState(el, 'emphasis', HOVER_STATE_EMPHASIS);
  78. }
  79. function singleLeaveEmphasis(el) {
  80. // Only mark the flag.
  81. // States will be applied in the echarts.ts in next frame.
  82. if (el.hoverState === HOVER_STATE_EMPHASIS) {
  83. doChangeHoverState(el, 'normal', HOVER_STATE_NORMAL);
  84. }
  85. }
  86. function singleEnterBlur(el) {
  87. doChangeHoverState(el, 'blur', HOVER_STATE_BLUR);
  88. }
  89. function singleLeaveBlur(el) {
  90. if (el.hoverState === HOVER_STATE_BLUR) {
  91. doChangeHoverState(el, 'normal', HOVER_STATE_NORMAL);
  92. }
  93. }
  94. function singleEnterSelect(el) {
  95. el.selected = true;
  96. }
  97. function singleLeaveSelect(el) {
  98. el.selected = false;
  99. }
  100. function updateElementState(el, updater, commonParam) {
  101. updater(el, commonParam);
  102. }
  103. function traverseUpdateState(el, updater, commonParam) {
  104. updateElementState(el, updater, commonParam);
  105. el.isGroup && el.traverse(function (child) {
  106. updateElementState(child, updater, commonParam);
  107. });
  108. }
  109. export function setStatesFlag(el, stateName) {
  110. switch (stateName) {
  111. case 'emphasis':
  112. el.hoverState = HOVER_STATE_EMPHASIS;
  113. break;
  114. case 'normal':
  115. el.hoverState = HOVER_STATE_NORMAL;
  116. break;
  117. case 'blur':
  118. el.hoverState = HOVER_STATE_BLUR;
  119. break;
  120. case 'select':
  121. el.selected = true;
  122. }
  123. }
  124. /**
  125. * If we reuse elements when rerender.
  126. * DON'T forget to clearStates before we update the style and shape.
  127. * Or we may update on the wrong state instead of normal state.
  128. */
  129. export function clearStates(el) {
  130. if (el.isGroup) {
  131. el.traverse(function (child) {
  132. child.clearStates();
  133. });
  134. } else {
  135. el.clearStates();
  136. }
  137. }
  138. function getFromStateStyle(el, props, toStateName, defaultValue) {
  139. var style = el.style;
  140. var fromState = {};
  141. for (var i = 0; i < props.length; i++) {
  142. var propName = props[i];
  143. var val = style[propName];
  144. fromState[propName] = val == null ? defaultValue && defaultValue[propName] : val;
  145. }
  146. for (var i = 0; i < el.animators.length; i++) {
  147. var animator = el.animators[i];
  148. if (animator.__fromStateTransition
  149. // Don't consider the animation to emphasis state.
  150. && animator.__fromStateTransition.indexOf(toStateName) < 0 && animator.targetName === 'style') {
  151. animator.saveTo(fromState, props);
  152. }
  153. }
  154. return fromState;
  155. }
  156. function createEmphasisDefaultState(el, stateName, targetStates, state) {
  157. var hasSelect = targetStates && indexOf(targetStates, 'select') >= 0;
  158. var cloned = false;
  159. if (el instanceof Path) {
  160. var store = getSavedStates(el);
  161. var fromFill = hasSelect ? store.selectFill || store.normalFill : store.normalFill;
  162. var fromStroke = hasSelect ? store.selectStroke || store.normalStroke : store.normalStroke;
  163. if (hasFillOrStroke(fromFill) || hasFillOrStroke(fromStroke)) {
  164. state = state || {};
  165. var emphasisStyle = state.style || {};
  166. // inherit case
  167. if (emphasisStyle.fill === 'inherit') {
  168. cloned = true;
  169. state = extend({}, state);
  170. emphasisStyle = extend({}, emphasisStyle);
  171. emphasisStyle.fill = fromFill;
  172. }
  173. // Apply default color lift
  174. else if (!hasFillOrStroke(emphasisStyle.fill) && hasFillOrStroke(fromFill)) {
  175. cloned = true;
  176. // Not modify the original value.
  177. state = extend({}, state);
  178. emphasisStyle = extend({}, emphasisStyle);
  179. // Already being applied 'emphasis'. DON'T lift color multiple times.
  180. emphasisStyle.fill = liftColor(fromFill);
  181. }
  182. // Not highlight stroke if fill has been highlighted.
  183. else if (!hasFillOrStroke(emphasisStyle.stroke) && hasFillOrStroke(fromStroke)) {
  184. if (!cloned) {
  185. state = extend({}, state);
  186. emphasisStyle = extend({}, emphasisStyle);
  187. }
  188. emphasisStyle.stroke = liftColor(fromStroke);
  189. }
  190. state.style = emphasisStyle;
  191. }
  192. }
  193. if (state) {
  194. // TODO Share with textContent?
  195. if (state.z2 == null) {
  196. if (!cloned) {
  197. state = extend({}, state);
  198. }
  199. var z2EmphasisLift = el.z2EmphasisLift;
  200. state.z2 = el.z2 + (z2EmphasisLift != null ? z2EmphasisLift : Z2_EMPHASIS_LIFT);
  201. }
  202. }
  203. return state;
  204. }
  205. function createSelectDefaultState(el, stateName, state) {
  206. // const hasSelect = indexOf(el.currentStates, stateName) >= 0;
  207. if (state) {
  208. // TODO Share with textContent?
  209. if (state.z2 == null) {
  210. state = extend({}, state);
  211. var z2SelectLift = el.z2SelectLift;
  212. state.z2 = el.z2 + (z2SelectLift != null ? z2SelectLift : Z2_SELECT_LIFT);
  213. }
  214. }
  215. return state;
  216. }
  217. function createBlurDefaultState(el, stateName, state) {
  218. var hasBlur = indexOf(el.currentStates, stateName) >= 0;
  219. var currentOpacity = el.style.opacity;
  220. var fromState = !hasBlur ? getFromStateStyle(el, ['opacity'], stateName, {
  221. opacity: 1
  222. }) : null;
  223. state = state || {};
  224. var blurStyle = state.style || {};
  225. if (blurStyle.opacity == null) {
  226. // clone state
  227. state = extend({}, state);
  228. blurStyle = extend({
  229. // Already being applied 'emphasis'. DON'T mul opacity multiple times.
  230. opacity: hasBlur ? currentOpacity : fromState.opacity * 0.1
  231. }, blurStyle);
  232. state.style = blurStyle;
  233. }
  234. return state;
  235. }
  236. function elementStateProxy(stateName, targetStates) {
  237. var state = this.states[stateName];
  238. if (this.style) {
  239. if (stateName === 'emphasis') {
  240. return createEmphasisDefaultState(this, stateName, targetStates, state);
  241. } else if (stateName === 'blur') {
  242. return createBlurDefaultState(this, stateName, state);
  243. } else if (stateName === 'select') {
  244. return createSelectDefaultState(this, stateName, state);
  245. }
  246. }
  247. return state;
  248. }
  249. /**
  250. * Set hover style (namely "emphasis style") of element.
  251. * @param el Should not be `zrender/graphic/Group`.
  252. * @param focus 'self' | 'selfInSeries' | 'series'
  253. */
  254. export function setDefaultStateProxy(el) {
  255. el.stateProxy = elementStateProxy;
  256. var textContent = el.getTextContent();
  257. var textGuide = el.getTextGuideLine();
  258. if (textContent) {
  259. textContent.stateProxy = elementStateProxy;
  260. }
  261. if (textGuide) {
  262. textGuide.stateProxy = elementStateProxy;
  263. }
  264. }
  265. export function enterEmphasisWhenMouseOver(el, e) {
  266. !shouldSilent(el, e)
  267. // "emphasis" event highlight has higher priority than mouse highlight.
  268. && !el.__highByOuter && traverseUpdateState(el, singleEnterEmphasis);
  269. }
  270. export function leaveEmphasisWhenMouseOut(el, e) {
  271. !shouldSilent(el, e)
  272. // "emphasis" event highlight has higher priority than mouse highlight.
  273. && !el.__highByOuter && traverseUpdateState(el, singleLeaveEmphasis);
  274. }
  275. export function enterEmphasis(el, highlightDigit) {
  276. el.__highByOuter |= 1 << (highlightDigit || 0);
  277. traverseUpdateState(el, singleEnterEmphasis);
  278. }
  279. export function leaveEmphasis(el, highlightDigit) {
  280. !(el.__highByOuter &= ~(1 << (highlightDigit || 0))) && traverseUpdateState(el, singleLeaveEmphasis);
  281. }
  282. export function enterBlur(el) {
  283. traverseUpdateState(el, singleEnterBlur);
  284. }
  285. export function leaveBlur(el) {
  286. traverseUpdateState(el, singleLeaveBlur);
  287. }
  288. export function enterSelect(el) {
  289. traverseUpdateState(el, singleEnterSelect);
  290. }
  291. export function leaveSelect(el) {
  292. traverseUpdateState(el, singleLeaveSelect);
  293. }
  294. function shouldSilent(el, e) {
  295. return el.__highDownSilentOnTouch && e.zrByTouch;
  296. }
  297. export function allLeaveBlur(api) {
  298. var model = api.getModel();
  299. var leaveBlurredSeries = [];
  300. var allComponentViews = [];
  301. model.eachComponent(function (componentType, componentModel) {
  302. var componentStates = getComponentStates(componentModel);
  303. var view = getViewOfComponentOrSeries(api, componentModel);
  304. var isSeries = componentType === 'series';
  305. !isSeries && allComponentViews.push(view);
  306. if (componentStates.isBlured) {
  307. // Leave blur anyway
  308. view.group.traverse(function (child) {
  309. singleLeaveBlur(child);
  310. });
  311. isSeries && leaveBlurredSeries.push(componentModel);
  312. }
  313. componentStates.isBlured = false;
  314. });
  315. each(allComponentViews, function (view) {
  316. if (view && view.toggleBlurSeries) {
  317. view.toggleBlurSeries(leaveBlurredSeries, false, model);
  318. }
  319. });
  320. }
  321. export function blurSeries(targetSeriesIndex, focus, blurScope, api) {
  322. var ecModel = api.getModel();
  323. blurScope = blurScope || 'coordinateSystem';
  324. function leaveBlurOfIndices(data, dataIndices) {
  325. for (var i = 0; i < dataIndices.length; i++) {
  326. var itemEl = data.getItemGraphicEl(dataIndices[i]);
  327. itemEl && leaveBlur(itemEl);
  328. }
  329. }
  330. if (targetSeriesIndex == null) {
  331. return;
  332. }
  333. if (!focus || focus === 'none') {
  334. return;
  335. }
  336. var targetSeriesModel = ecModel.getSeriesByIndex(targetSeriesIndex);
  337. var targetCoordSys = targetSeriesModel.coordinateSystem;
  338. if (targetCoordSys && targetCoordSys.master) {
  339. targetCoordSys = targetCoordSys.master;
  340. }
  341. var blurredSeries = [];
  342. ecModel.eachSeries(function (seriesModel) {
  343. var sameSeries = targetSeriesModel === seriesModel;
  344. var coordSys = seriesModel.coordinateSystem;
  345. if (coordSys && coordSys.master) {
  346. coordSys = coordSys.master;
  347. }
  348. var sameCoordSys = coordSys && targetCoordSys ? coordSys === targetCoordSys : sameSeries; // If there is no coordinate system. use sameSeries instead.
  349. if (!(
  350. // Not blur other series if blurScope series
  351. blurScope === 'series' && !sameSeries
  352. // Not blur other coordinate system if blurScope is coordinateSystem
  353. || blurScope === 'coordinateSystem' && !sameCoordSys
  354. // Not blur self series if focus is series.
  355. || focus === 'series' && sameSeries
  356. // TODO blurScope: coordinate system
  357. )) {
  358. var view = api.getViewOfSeriesModel(seriesModel);
  359. view.group.traverse(function (child) {
  360. // For the elements that have been triggered by other components,
  361. // and are still required to be highlighted,
  362. // because the current is directly forced to blur the element,
  363. // it will cause the focus self to be unable to highlight, so skip the blur of this element.
  364. if (child.__highByOuter && sameSeries && focus === 'self') {
  365. return;
  366. }
  367. singleEnterBlur(child);
  368. });
  369. if (isArrayLike(focus)) {
  370. leaveBlurOfIndices(seriesModel.getData(), focus);
  371. } else if (isObject(focus)) {
  372. var dataTypes = keys(focus);
  373. for (var d = 0; d < dataTypes.length; d++) {
  374. leaveBlurOfIndices(seriesModel.getData(dataTypes[d]), focus[dataTypes[d]]);
  375. }
  376. }
  377. blurredSeries.push(seriesModel);
  378. getComponentStates(seriesModel).isBlured = true;
  379. }
  380. });
  381. ecModel.eachComponent(function (componentType, componentModel) {
  382. if (componentType === 'series') {
  383. return;
  384. }
  385. var view = api.getViewOfComponentModel(componentModel);
  386. if (view && view.toggleBlurSeries) {
  387. view.toggleBlurSeries(blurredSeries, true, ecModel);
  388. }
  389. });
  390. }
  391. export function blurComponent(componentMainType, componentIndex, api) {
  392. if (componentMainType == null || componentIndex == null) {
  393. return;
  394. }
  395. var componentModel = api.getModel().getComponent(componentMainType, componentIndex);
  396. if (!componentModel) {
  397. return;
  398. }
  399. getComponentStates(componentModel).isBlured = true;
  400. var view = api.getViewOfComponentModel(componentModel);
  401. if (!view || !view.focusBlurEnabled) {
  402. return;
  403. }
  404. view.group.traverse(function (child) {
  405. singleEnterBlur(child);
  406. });
  407. }
  408. export function blurSeriesFromHighlightPayload(seriesModel, payload, api) {
  409. var seriesIndex = seriesModel.seriesIndex;
  410. var data = seriesModel.getData(payload.dataType);
  411. if (!data) {
  412. if (process.env.NODE_ENV !== 'production') {
  413. error("Unknown dataType " + payload.dataType);
  414. }
  415. return;
  416. }
  417. var dataIndex = queryDataIndex(data, payload);
  418. // Pick the first one if there is multiple/none exists.
  419. dataIndex = (isArray(dataIndex) ? dataIndex[0] : dataIndex) || 0;
  420. var el = data.getItemGraphicEl(dataIndex);
  421. if (!el) {
  422. var count = data.count();
  423. var current = 0;
  424. // If data on dataIndex is NaN.
  425. while (!el && current < count) {
  426. el = data.getItemGraphicEl(current++);
  427. }
  428. }
  429. if (el) {
  430. var ecData = getECData(el);
  431. blurSeries(seriesIndex, ecData.focus, ecData.blurScope, api);
  432. } else {
  433. // If there is no element put on the data. Try getting it from raw option
  434. // TODO Should put it on seriesModel?
  435. var focus_1 = seriesModel.get(['emphasis', 'focus']);
  436. var blurScope = seriesModel.get(['emphasis', 'blurScope']);
  437. if (focus_1 != null) {
  438. blurSeries(seriesIndex, focus_1, blurScope, api);
  439. }
  440. }
  441. }
  442. export function findComponentHighDownDispatchers(componentMainType, componentIndex, name, api) {
  443. var ret = {
  444. focusSelf: false,
  445. dispatchers: null
  446. };
  447. if (componentMainType == null || componentMainType === 'series' || componentIndex == null || name == null) {
  448. return ret;
  449. }
  450. var componentModel = api.getModel().getComponent(componentMainType, componentIndex);
  451. if (!componentModel) {
  452. return ret;
  453. }
  454. var view = api.getViewOfComponentModel(componentModel);
  455. if (!view || !view.findHighDownDispatchers) {
  456. return ret;
  457. }
  458. var dispatchers = view.findHighDownDispatchers(name);
  459. // At presnet, the component (like Geo) only blur inside itself.
  460. // So we do not use `blurScope` in component.
  461. var focusSelf;
  462. for (var i = 0; i < dispatchers.length; i++) {
  463. if (process.env.NODE_ENV !== 'production' && !isHighDownDispatcher(dispatchers[i])) {
  464. error('param should be highDownDispatcher');
  465. }
  466. if (getECData(dispatchers[i]).focus === 'self') {
  467. focusSelf = true;
  468. break;
  469. }
  470. }
  471. return {
  472. focusSelf: focusSelf,
  473. dispatchers: dispatchers
  474. };
  475. }
  476. export function handleGlobalMouseOverForHighDown(dispatcher, e, api) {
  477. if (process.env.NODE_ENV !== 'production' && !isHighDownDispatcher(dispatcher)) {
  478. error('param should be highDownDispatcher');
  479. }
  480. var ecData = getECData(dispatcher);
  481. var _a = findComponentHighDownDispatchers(ecData.componentMainType, ecData.componentIndex, ecData.componentHighDownName, api),
  482. dispatchers = _a.dispatchers,
  483. focusSelf = _a.focusSelf;
  484. // If `findHighDownDispatchers` is supported on the component,
  485. // highlight/downplay elements with the same name.
  486. if (dispatchers) {
  487. if (focusSelf) {
  488. blurComponent(ecData.componentMainType, ecData.componentIndex, api);
  489. }
  490. each(dispatchers, function (dispatcher) {
  491. return enterEmphasisWhenMouseOver(dispatcher, e);
  492. });
  493. } else {
  494. // Try blur all in the related series. Then emphasis the hoverred.
  495. // TODO. progressive mode.
  496. blurSeries(ecData.seriesIndex, ecData.focus, ecData.blurScope, api);
  497. if (ecData.focus === 'self') {
  498. blurComponent(ecData.componentMainType, ecData.componentIndex, api);
  499. }
  500. // Other than series, component that not support `findHighDownDispatcher` will
  501. // also use it. But in this case, highlight/downplay are only supported in
  502. // mouse hover but not in dispatchAction.
  503. enterEmphasisWhenMouseOver(dispatcher, e);
  504. }
  505. }
  506. export function handleGlobalMouseOutForHighDown(dispatcher, e, api) {
  507. if (process.env.NODE_ENV !== 'production' && !isHighDownDispatcher(dispatcher)) {
  508. error('param should be highDownDispatcher');
  509. }
  510. allLeaveBlur(api);
  511. var ecData = getECData(dispatcher);
  512. var dispatchers = findComponentHighDownDispatchers(ecData.componentMainType, ecData.componentIndex, ecData.componentHighDownName, api).dispatchers;
  513. if (dispatchers) {
  514. each(dispatchers, function (dispatcher) {
  515. return leaveEmphasisWhenMouseOut(dispatcher, e);
  516. });
  517. } else {
  518. leaveEmphasisWhenMouseOut(dispatcher, e);
  519. }
  520. }
  521. export function toggleSelectionFromPayload(seriesModel, payload, api) {
  522. if (!isSelectChangePayload(payload)) {
  523. return;
  524. }
  525. var dataType = payload.dataType;
  526. var data = seriesModel.getData(dataType);
  527. var dataIndex = queryDataIndex(data, payload);
  528. if (!isArray(dataIndex)) {
  529. dataIndex = [dataIndex];
  530. }
  531. seriesModel[payload.type === TOGGLE_SELECT_ACTION_TYPE ? 'toggleSelect' : payload.type === SELECT_ACTION_TYPE ? 'select' : 'unselect'](dataIndex, dataType);
  532. }
  533. export function updateSeriesElementSelection(seriesModel) {
  534. var allData = seriesModel.getAllData();
  535. each(allData, function (_a) {
  536. var data = _a.data,
  537. type = _a.type;
  538. data.eachItemGraphicEl(function (el, idx) {
  539. seriesModel.isSelected(idx, type) ? enterSelect(el) : leaveSelect(el);
  540. });
  541. });
  542. }
  543. export function getAllSelectedIndices(ecModel) {
  544. var ret = [];
  545. ecModel.eachSeries(function (seriesModel) {
  546. var allData = seriesModel.getAllData();
  547. each(allData, function (_a) {
  548. var data = _a.data,
  549. type = _a.type;
  550. var dataIndices = seriesModel.getSelectedDataIndices();
  551. if (dataIndices.length > 0) {
  552. var item = {
  553. dataIndex: dataIndices,
  554. seriesIndex: seriesModel.seriesIndex
  555. };
  556. if (type != null) {
  557. item.dataType = type;
  558. }
  559. ret.push(item);
  560. }
  561. });
  562. });
  563. return ret;
  564. }
  565. /**
  566. * Enable the function that mouseover will trigger the emphasis state.
  567. *
  568. * NOTE:
  569. * This function should be used on the element with dataIndex, seriesIndex.
  570. *
  571. */
  572. export function enableHoverEmphasis(el, focus, blurScope) {
  573. setAsHighDownDispatcher(el, true);
  574. traverseUpdateState(el, setDefaultStateProxy);
  575. enableHoverFocus(el, focus, blurScope);
  576. }
  577. export function disableHoverEmphasis(el) {
  578. setAsHighDownDispatcher(el, false);
  579. }
  580. export function toggleHoverEmphasis(el, focus, blurScope, isDisabled) {
  581. isDisabled ? disableHoverEmphasis(el) : enableHoverEmphasis(el, focus, blurScope);
  582. }
  583. export function enableHoverFocus(el, focus, blurScope) {
  584. var ecData = getECData(el);
  585. if (focus != null) {
  586. // TODO dataIndex may be set after this function. This check is not useful.
  587. // if (ecData.dataIndex == null) {
  588. // if (__DEV__) {
  589. // console.warn('focus can only been set on element with dataIndex');
  590. // }
  591. // }
  592. // else {
  593. ecData.focus = focus;
  594. ecData.blurScope = blurScope;
  595. // }
  596. } else if (ecData.focus) {
  597. ecData.focus = null;
  598. }
  599. }
  600. var OTHER_STATES = ['emphasis', 'blur', 'select'];
  601. var defaultStyleGetterMap = {
  602. itemStyle: 'getItemStyle',
  603. lineStyle: 'getLineStyle',
  604. areaStyle: 'getAreaStyle'
  605. };
  606. /**
  607. * Set emphasis/blur/selected states of element.
  608. */
  609. export function setStatesStylesFromModel(el, itemModel, styleType,
  610. // default itemStyle
  611. getter) {
  612. styleType = styleType || 'itemStyle';
  613. for (var i = 0; i < OTHER_STATES.length; i++) {
  614. var stateName = OTHER_STATES[i];
  615. var model = itemModel.getModel([stateName, styleType]);
  616. var state = el.ensureState(stateName);
  617. // Let it throw error if getterType is not found.
  618. state.style = getter ? getter(model) : model[defaultStyleGetterMap[styleType]]();
  619. }
  620. }
  621. /**
  622. *
  623. * Set element as highlight / downplay dispatcher.
  624. * It will be checked when element received mouseover event or from highlight action.
  625. * It's in change of all highlight/downplay behavior of it's children.
  626. *
  627. * @param el
  628. * @param el.highDownSilentOnTouch
  629. * In touch device, mouseover event will be trigger on touchstart event
  630. * (see module:zrender/dom/HandlerProxy). By this mechanism, we can
  631. * conveniently use hoverStyle when tap on touch screen without additional
  632. * code for compatibility.
  633. * But if the chart/component has select feature, which usually also use
  634. * hoverStyle, there might be conflict between 'select-highlight' and
  635. * 'hover-highlight' especially when roam is enabled (see geo for example).
  636. * In this case, `highDownSilentOnTouch` should be used to disable
  637. * hover-highlight on touch device.
  638. * @param asDispatcher If `false`, do not set as "highDownDispatcher".
  639. */
  640. export function setAsHighDownDispatcher(el, asDispatcher) {
  641. var disable = asDispatcher === false;
  642. var extendedEl = el;
  643. // Make `highDownSilentOnTouch` and `onStateChange` only work after
  644. // `setAsHighDownDispatcher` called. Avoid it is modified by user unexpectedly.
  645. if (el.highDownSilentOnTouch) {
  646. extendedEl.__highDownSilentOnTouch = el.highDownSilentOnTouch;
  647. }
  648. // Simple optimize, since this method might be
  649. // called for each elements of a group in some cases.
  650. if (!disable || extendedEl.__highDownDispatcher) {
  651. // Emphasis, normal can be triggered manually by API or other components like hover link.
  652. // el[method]('emphasis', onElementEmphasisEvent)[method]('normal', onElementNormalEvent);
  653. // Also keep previous record.
  654. extendedEl.__highByOuter = extendedEl.__highByOuter || 0;
  655. extendedEl.__highDownDispatcher = !disable;
  656. }
  657. }
  658. export function isHighDownDispatcher(el) {
  659. return !!(el && el.__highDownDispatcher);
  660. }
  661. /**
  662. * Enable component highlight/downplay features:
  663. * + hover link (within the same name)
  664. * + focus blur in component
  665. */
  666. export function enableComponentHighDownFeatures(el, componentModel, componentHighDownName) {
  667. var ecData = getECData(el);
  668. ecData.componentMainType = componentModel.mainType;
  669. ecData.componentIndex = componentModel.componentIndex;
  670. ecData.componentHighDownName = componentHighDownName;
  671. }
  672. /**
  673. * Support highlight/downplay record on each elements.
  674. * For the case: hover highlight/downplay (legend, visualMap, ...) and
  675. * user triggered highlight/downplay should not conflict.
  676. * Only all of the highlightDigit cleared, return to normal.
  677. * @param {string} highlightKey
  678. * @return {number} highlightDigit
  679. */
  680. export function getHighlightDigit(highlightKey) {
  681. var highlightDigit = _highlightKeyMap[highlightKey];
  682. if (highlightDigit == null && _highlightNextDigit <= 32) {
  683. highlightDigit = _highlightKeyMap[highlightKey] = _highlightNextDigit++;
  684. }
  685. return highlightDigit;
  686. }
  687. export function isSelectChangePayload(payload) {
  688. var payloadType = payload.type;
  689. return payloadType === SELECT_ACTION_TYPE || payloadType === UNSELECT_ACTION_TYPE || payloadType === TOGGLE_SELECT_ACTION_TYPE;
  690. }
  691. export function isHighDownPayload(payload) {
  692. var payloadType = payload.type;
  693. return payloadType === HIGHLIGHT_ACTION_TYPE || payloadType === DOWNPLAY_ACTION_TYPE;
  694. }
  695. export function savePathStates(el) {
  696. var store = getSavedStates(el);
  697. store.normalFill = el.style.fill;
  698. store.normalStroke = el.style.stroke;
  699. var selectState = el.states.select || {};
  700. store.selectFill = selectState.style && selectState.style.fill || null;
  701. store.selectStroke = selectState.style && selectState.style.stroke || null;
  702. }