LegendView.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  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 { __extends } from "tslib";
  41. import * as zrUtil from 'zrender/lib/core/util.js';
  42. import { parse, stringify } from 'zrender/lib/tool/color.js';
  43. import * as graphic from '../../util/graphic.js';
  44. import { enableHoverEmphasis } from '../../util/states.js';
  45. import { setLabelStyle, createTextStyle } from '../../label/labelStyle.js';
  46. import { makeBackground } from '../helper/listComponent.js';
  47. import * as layoutUtil from '../../util/layout.js';
  48. import ComponentView from '../../view/Component.js';
  49. import { createSymbol } from '../../util/symbol.js';
  50. import { createOrUpdatePatternFromDecal } from '../../util/decal.js';
  51. import { getECData } from '../../util/innerStore.js';
  52. import tokens from '../../visual/tokens.js';
  53. var curry = zrUtil.curry;
  54. var each = zrUtil.each;
  55. var Group = graphic.Group;
  56. var LegendView = /** @class */function (_super) {
  57. __extends(LegendView, _super);
  58. function LegendView() {
  59. var _this = _super !== null && _super.apply(this, arguments) || this;
  60. _this.type = LegendView.type;
  61. _this.newlineDisabled = false;
  62. return _this;
  63. }
  64. LegendView.prototype.init = function () {
  65. this.group.add(this._contentGroup = new Group());
  66. this.group.add(this._selectorGroup = new Group());
  67. this._isFirstRender = true;
  68. };
  69. /**
  70. * @protected
  71. */
  72. LegendView.prototype.getContentGroup = function () {
  73. return this._contentGroup;
  74. };
  75. /**
  76. * @protected
  77. */
  78. LegendView.prototype.getSelectorGroup = function () {
  79. return this._selectorGroup;
  80. };
  81. /**
  82. * @override
  83. */
  84. LegendView.prototype.render = function (legendModel, ecModel, api) {
  85. var isFirstRender = this._isFirstRender;
  86. this._isFirstRender = false;
  87. this.resetInner();
  88. if (!legendModel.get('show', true)) {
  89. return;
  90. }
  91. var itemAlign = legendModel.get('align');
  92. var orient = legendModel.get('orient');
  93. if (!itemAlign || itemAlign === 'auto') {
  94. itemAlign = legendModel.get('left') === 'right' && orient === 'vertical' ? 'right' : 'left';
  95. }
  96. // selector has been normalized to an array in model
  97. var selector = legendModel.get('selector', true);
  98. var selectorPosition = legendModel.get('selectorPosition', true);
  99. if (selector && (!selectorPosition || selectorPosition === 'auto')) {
  100. selectorPosition = orient === 'horizontal' ? 'end' : 'start';
  101. }
  102. this.renderInner(itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition);
  103. // Perform layout.
  104. var refContainer = layoutUtil.createBoxLayoutReference(legendModel, api).refContainer;
  105. var positionInfo = legendModel.getBoxLayoutParams();
  106. var padding = legendModel.get('padding');
  107. var maxSize = layoutUtil.getLayoutRect(positionInfo, refContainer, padding);
  108. var mainRect = this.layoutInner(legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition);
  109. // Place mainGroup, based on the calculated `mainRect`.
  110. var layoutRect = layoutUtil.getLayoutRect(zrUtil.defaults({
  111. width: mainRect.width,
  112. height: mainRect.height
  113. }, positionInfo), refContainer, padding);
  114. this.group.x = layoutRect.x - mainRect.x;
  115. this.group.y = layoutRect.y - mainRect.y;
  116. this.group.markRedraw();
  117. // Render background after group is layout.
  118. this.group.add(this._backgroundEl = makeBackground(mainRect,
  119. // FXIME: most itemStyle options does not work in background because inherit is not handled yet.
  120. legendModel));
  121. };
  122. LegendView.prototype.resetInner = function () {
  123. this.getContentGroup().removeAll();
  124. this._backgroundEl && this.group.remove(this._backgroundEl);
  125. this.getSelectorGroup().removeAll();
  126. };
  127. LegendView.prototype.renderInner = function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) {
  128. var contentGroup = this.getContentGroup();
  129. var legendDrawnMap = zrUtil.createHashMap();
  130. var selectMode = legendModel.get('selectedMode');
  131. var triggerEvent = legendModel.get('triggerEvent');
  132. var excludeSeriesId = [];
  133. ecModel.eachRawSeries(function (seriesModel) {
  134. !seriesModel.get('legendHoverLink') && excludeSeriesId.push(seriesModel.id);
  135. });
  136. each(legendModel.getData(), function (legendItemModel, dataIndex) {
  137. var _this = this;
  138. var name = legendItemModel.get('name');
  139. // Use empty string or \n as a newline string
  140. if (!this.newlineDisabled && (name === '' || name === '\n')) {
  141. var g = new Group();
  142. // @ts-ignore
  143. g.newline = true;
  144. contentGroup.add(g);
  145. return;
  146. }
  147. // Representitive series.
  148. var seriesModel = ecModel.getSeriesByName(name)[0];
  149. if (legendDrawnMap.get(name)) {
  150. // Have been drawn
  151. return;
  152. }
  153. // Legend to control series.
  154. if (seriesModel) {
  155. var data = seriesModel.getData();
  156. var lineVisualStyle = data.getVisual('legendLineStyle') || {};
  157. var legendIcon = data.getVisual('legendIcon');
  158. /**
  159. * `data.getVisual('style')` may be the color from the register
  160. * in series. For example, for line series,
  161. */
  162. var style = data.getVisual('style');
  163. var itemGroup = this._createItem(seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, lineVisualStyle, style, legendIcon, selectMode, api);
  164. itemGroup.on('click', curry(dispatchSelectAction, name, null, api, excludeSeriesId)).on('mouseover', curry(dispatchHighlightAction, seriesModel.name, null, api, excludeSeriesId)).on('mouseout', curry(dispatchDownplayAction, seriesModel.name, null, api, excludeSeriesId));
  165. if (ecModel.ssr) {
  166. itemGroup.eachChild(function (child) {
  167. var ecData = getECData(child);
  168. ecData.seriesIndex = seriesModel.seriesIndex;
  169. ecData.dataIndex = dataIndex;
  170. ecData.ssrType = 'legend';
  171. });
  172. }
  173. if (triggerEvent) {
  174. itemGroup.eachChild(function (child) {
  175. _this.packEventData(child, legendModel, seriesModel, dataIndex, name);
  176. });
  177. }
  178. legendDrawnMap.set(name, true);
  179. } else {
  180. // Legend to control data. In pie and funnel.
  181. ecModel.eachRawSeries(function (seriesModel) {
  182. var _this = this;
  183. // In case multiple series has same data name
  184. if (legendDrawnMap.get(name)) {
  185. return;
  186. }
  187. if (seriesModel.legendVisualProvider) {
  188. var provider = seriesModel.legendVisualProvider;
  189. if (!provider.containName(name)) {
  190. return;
  191. }
  192. var idx = provider.indexOfName(name);
  193. var style = provider.getItemVisual(idx, 'style');
  194. var legendIcon = provider.getItemVisual(idx, 'legendIcon');
  195. var colorArr = parse(style.fill);
  196. // Color may be set to transparent in visualMap when data is out of range.
  197. // Do not show nothing.
  198. if (colorArr && colorArr[3] === 0) {
  199. colorArr[3] = 0.2;
  200. // TODO color is set to 0, 0, 0, 0. Should show correct RGBA
  201. style = zrUtil.extend(zrUtil.extend({}, style), {
  202. fill: stringify(colorArr, 'rgba')
  203. });
  204. }
  205. var itemGroup = this._createItem(seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, {}, style, legendIcon, selectMode, api);
  206. // FIXME: consider different series has items with the same name.
  207. itemGroup.on('click', curry(dispatchSelectAction, null, name, api, excludeSeriesId))
  208. // Should not specify the series name, consider legend controls
  209. // more than one pie series.
  210. .on('mouseover', curry(dispatchHighlightAction, null, name, api, excludeSeriesId)).on('mouseout', curry(dispatchDownplayAction, null, name, api, excludeSeriesId));
  211. if (ecModel.ssr) {
  212. itemGroup.eachChild(function (child) {
  213. var ecData = getECData(child);
  214. ecData.seriesIndex = seriesModel.seriesIndex;
  215. ecData.dataIndex = dataIndex;
  216. ecData.ssrType = 'legend';
  217. });
  218. }
  219. if (triggerEvent) {
  220. itemGroup.eachChild(function (child) {
  221. _this.packEventData(child, legendModel, seriesModel, dataIndex, name);
  222. });
  223. }
  224. legendDrawnMap.set(name, true);
  225. }
  226. }, this);
  227. }
  228. if (process.env.NODE_ENV !== 'production') {
  229. if (!legendDrawnMap.get(name)) {
  230. console.warn(name + ' series not exists. Legend data should be same with series name or data name.');
  231. }
  232. }
  233. }, this);
  234. if (selector) {
  235. this._createSelector(selector, legendModel, api, orient, selectorPosition);
  236. }
  237. };
  238. LegendView.prototype.packEventData = function (el, legendModel, seriesModel, dataIndex, name) {
  239. var eventData = {
  240. componentType: 'legend',
  241. componentIndex: legendModel.componentIndex,
  242. dataIndex: dataIndex,
  243. value: name,
  244. seriesIndex: seriesModel.seriesIndex
  245. };
  246. getECData(el).eventData = eventData;
  247. };
  248. ;
  249. LegendView.prototype._createSelector = function (selector, legendModel, api, orient, selectorPosition) {
  250. var selectorGroup = this.getSelectorGroup();
  251. each(selector, function createSelectorButton(selectorItem) {
  252. var type = selectorItem.type;
  253. var labelText = new graphic.Text({
  254. style: {
  255. x: 0,
  256. y: 0,
  257. align: 'center',
  258. verticalAlign: 'middle'
  259. },
  260. onclick: function () {
  261. api.dispatchAction({
  262. type: type === 'all' ? 'legendAllSelect' : 'legendInverseSelect',
  263. legendId: legendModel.id
  264. });
  265. }
  266. });
  267. selectorGroup.add(labelText);
  268. var labelModel = legendModel.getModel('selectorLabel');
  269. var emphasisLabelModel = legendModel.getModel(['emphasis', 'selectorLabel']);
  270. setLabelStyle(labelText, {
  271. normal: labelModel,
  272. emphasis: emphasisLabelModel
  273. }, {
  274. defaultText: selectorItem.title
  275. });
  276. enableHoverEmphasis(labelText);
  277. });
  278. };
  279. LegendView.prototype._createItem = function (seriesModel, name, dataIndex, legendItemModel, legendModel, itemAlign, lineVisualStyle, itemVisualStyle, legendIcon, selectMode, api) {
  280. var drawType = seriesModel.visualDrawType;
  281. var itemWidth = legendModel.get('itemWidth');
  282. var itemHeight = legendModel.get('itemHeight');
  283. var isSelected = legendModel.isSelected(name);
  284. var iconRotate = legendItemModel.get('symbolRotate');
  285. var symbolKeepAspect = legendItemModel.get('symbolKeepAspect');
  286. var legendIconType = legendItemModel.get('icon');
  287. legendIcon = legendIconType || legendIcon || 'roundRect';
  288. var style = getLegendStyle(legendIcon, legendItemModel, lineVisualStyle, itemVisualStyle, drawType, isSelected, api);
  289. var itemGroup = new Group();
  290. var textStyleModel = legendItemModel.getModel('textStyle');
  291. if (zrUtil.isFunction(seriesModel.getLegendIcon) && (!legendIconType || legendIconType === 'inherit')) {
  292. // Series has specific way to define legend icon
  293. itemGroup.add(seriesModel.getLegendIcon({
  294. itemWidth: itemWidth,
  295. itemHeight: itemHeight,
  296. icon: legendIcon,
  297. iconRotate: iconRotate,
  298. itemStyle: style.itemStyle,
  299. lineStyle: style.lineStyle,
  300. symbolKeepAspect: symbolKeepAspect
  301. }));
  302. } else {
  303. // Use default legend icon policy for most series
  304. var rotate = legendIconType === 'inherit' && seriesModel.getData().getVisual('symbol') ? iconRotate === 'inherit' ? seriesModel.getData().getVisual('symbolRotate') : iconRotate : 0; // No rotation for no icon
  305. itemGroup.add(getDefaultLegendIcon({
  306. itemWidth: itemWidth,
  307. itemHeight: itemHeight,
  308. icon: legendIcon,
  309. iconRotate: rotate,
  310. itemStyle: style.itemStyle,
  311. lineStyle: style.lineStyle,
  312. symbolKeepAspect: symbolKeepAspect
  313. }));
  314. }
  315. var textX = itemAlign === 'left' ? itemWidth + 5 : -5;
  316. var textAlign = itemAlign;
  317. var formatter = legendModel.get('formatter');
  318. var content = name;
  319. if (zrUtil.isString(formatter) && formatter) {
  320. content = formatter.replace('{name}', name != null ? name : '');
  321. } else if (zrUtil.isFunction(formatter)) {
  322. content = formatter(name);
  323. }
  324. var textColor = isSelected ? textStyleModel.getTextColor() : legendItemModel.get('inactiveColor');
  325. itemGroup.add(new graphic.Text({
  326. style: createTextStyle(textStyleModel, {
  327. text: content,
  328. x: textX,
  329. y: itemHeight / 2,
  330. fill: textColor,
  331. align: textAlign,
  332. verticalAlign: 'middle'
  333. }, {
  334. inheritColor: textColor
  335. })
  336. }));
  337. // Add a invisible rect to increase the area of mouse hover
  338. var hitRect = new graphic.Rect({
  339. shape: itemGroup.getBoundingRect(),
  340. style: {
  341. // Cannot use 'invisible' because SVG SSR will miss the node
  342. fill: 'transparent'
  343. }
  344. });
  345. var tooltipModel = legendItemModel.getModel('tooltip');
  346. if (tooltipModel.get('show')) {
  347. graphic.setTooltipConfig({
  348. el: hitRect,
  349. componentModel: legendModel,
  350. itemName: name,
  351. itemTooltipOption: tooltipModel.option
  352. });
  353. }
  354. itemGroup.add(hitRect);
  355. itemGroup.eachChild(function (child) {
  356. child.silent = true;
  357. });
  358. hitRect.silent = !selectMode;
  359. this.getContentGroup().add(itemGroup);
  360. enableHoverEmphasis(itemGroup);
  361. // @ts-ignore
  362. itemGroup.__legendDataIndex = dataIndex;
  363. return itemGroup;
  364. };
  365. LegendView.prototype.layoutInner = function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) {
  366. var contentGroup = this.getContentGroup();
  367. var selectorGroup = this.getSelectorGroup();
  368. // Place items in contentGroup.
  369. layoutUtil.box(legendModel.get('orient'), contentGroup, legendModel.get('itemGap'), maxSize.width, maxSize.height);
  370. var contentRect = contentGroup.getBoundingRect();
  371. var contentPos = [-contentRect.x, -contentRect.y];
  372. selectorGroup.markRedraw();
  373. contentGroup.markRedraw();
  374. if (selector) {
  375. // Place buttons in selectorGroup
  376. layoutUtil.box(
  377. // Buttons in selectorGroup always layout horizontally
  378. 'horizontal', selectorGroup, legendModel.get('selectorItemGap', true));
  379. var selectorRect = selectorGroup.getBoundingRect();
  380. var selectorPos = [-selectorRect.x, -selectorRect.y];
  381. var selectorButtonGap = legendModel.get('selectorButtonGap', true);
  382. var orientIdx = legendModel.getOrient().index;
  383. var wh = orientIdx === 0 ? 'width' : 'height';
  384. var hw = orientIdx === 0 ? 'height' : 'width';
  385. var yx = orientIdx === 0 ? 'y' : 'x';
  386. if (selectorPosition === 'end') {
  387. selectorPos[orientIdx] += contentRect[wh] + selectorButtonGap;
  388. } else {
  389. contentPos[orientIdx] += selectorRect[wh] + selectorButtonGap;
  390. }
  391. // Always align selector to content as 'middle'
  392. selectorPos[1 - orientIdx] += contentRect[hw] / 2 - selectorRect[hw] / 2;
  393. selectorGroup.x = selectorPos[0];
  394. selectorGroup.y = selectorPos[1];
  395. contentGroup.x = contentPos[0];
  396. contentGroup.y = contentPos[1];
  397. var mainRect = {
  398. x: 0,
  399. y: 0
  400. };
  401. mainRect[wh] = contentRect[wh] + selectorButtonGap + selectorRect[wh];
  402. mainRect[hw] = Math.max(contentRect[hw], selectorRect[hw]);
  403. mainRect[yx] = Math.min(0, selectorRect[yx] + selectorPos[1 - orientIdx]);
  404. return mainRect;
  405. } else {
  406. contentGroup.x = contentPos[0];
  407. contentGroup.y = contentPos[1];
  408. return this.group.getBoundingRect();
  409. }
  410. };
  411. /**
  412. * @protected
  413. */
  414. LegendView.prototype.remove = function () {
  415. this.getContentGroup().removeAll();
  416. this._isFirstRender = true;
  417. };
  418. LegendView.type = 'legend.plain';
  419. return LegendView;
  420. }(ComponentView);
  421. function getLegendStyle(iconType, legendItemModel, lineVisualStyle, itemVisualStyle, drawType, isSelected, api) {
  422. /**
  423. * Use series style if is inherit;
  424. * elsewise, use legend style
  425. */
  426. function handleCommonProps(style, visualStyle) {
  427. // If lineStyle.width is 'auto', it is set to be 2 if series has border
  428. if (style.lineWidth === 'auto') {
  429. style.lineWidth = visualStyle.lineWidth > 0 ? 2 : 0;
  430. }
  431. each(style, function (propVal, propName) {
  432. style[propName] === 'inherit' && (style[propName] = visualStyle[propName]);
  433. });
  434. }
  435. // itemStyle
  436. var itemStyleModel = legendItemModel.getModel('itemStyle');
  437. var itemStyle = itemStyleModel.getItemStyle();
  438. var iconBrushType = iconType.lastIndexOf('empty', 0) === 0 ? 'fill' : 'stroke';
  439. var decalStyle = itemStyleModel.getShallow('decal');
  440. itemStyle.decal = !decalStyle || decalStyle === 'inherit' ? itemVisualStyle.decal : createOrUpdatePatternFromDecal(decalStyle, api);
  441. if (itemStyle.fill === 'inherit') {
  442. /**
  443. * Series with visualDrawType as 'stroke' should have
  444. * series stroke as legend fill
  445. */
  446. itemStyle.fill = itemVisualStyle[drawType];
  447. }
  448. if (itemStyle.stroke === 'inherit') {
  449. /**
  450. * icon type with "emptyXXX" should use fill color
  451. * in visual style
  452. */
  453. itemStyle.stroke = itemVisualStyle[iconBrushType];
  454. }
  455. if (itemStyle.opacity === 'inherit') {
  456. /**
  457. * Use lineStyle.opacity if drawType is stroke
  458. */
  459. itemStyle.opacity = (drawType === 'fill' ? itemVisualStyle : lineVisualStyle).opacity;
  460. }
  461. handleCommonProps(itemStyle, itemVisualStyle);
  462. // lineStyle
  463. var legendLineModel = legendItemModel.getModel('lineStyle');
  464. var lineStyle = legendLineModel.getLineStyle();
  465. handleCommonProps(lineStyle, lineVisualStyle);
  466. // Fix auto color to real color
  467. itemStyle.fill === 'auto' && (itemStyle.fill = itemVisualStyle.fill);
  468. itemStyle.stroke === 'auto' && (itemStyle.stroke = itemVisualStyle.fill);
  469. lineStyle.stroke === 'auto' && (lineStyle.stroke = itemVisualStyle.fill);
  470. if (!isSelected) {
  471. var borderWidth = legendItemModel.get('inactiveBorderWidth');
  472. /**
  473. * Since stroke is set to be inactiveBorderColor, it may occur that
  474. * there is no border in series but border in legend, so we need to
  475. * use border only when series has border if is set to be auto
  476. */
  477. var visualHasBorder = itemStyle[iconBrushType];
  478. itemStyle.lineWidth = borderWidth === 'auto' ? itemVisualStyle.lineWidth > 0 && visualHasBorder ? 2 : 0 : itemStyle.lineWidth;
  479. itemStyle.fill = legendItemModel.get('inactiveColor');
  480. itemStyle.stroke = legendItemModel.get('inactiveBorderColor');
  481. lineStyle.stroke = legendLineModel.get('inactiveColor');
  482. lineStyle.lineWidth = legendLineModel.get('inactiveWidth');
  483. }
  484. return {
  485. itemStyle: itemStyle,
  486. lineStyle: lineStyle
  487. };
  488. }
  489. function getDefaultLegendIcon(opt) {
  490. var symboType = opt.icon || 'roundRect';
  491. var icon = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill, opt.symbolKeepAspect);
  492. icon.setStyle(opt.itemStyle);
  493. icon.rotation = (opt.iconRotate || 0) * Math.PI / 180;
  494. icon.setOrigin([opt.itemWidth / 2, opt.itemHeight / 2]);
  495. if (symboType.indexOf('empty') > -1) {
  496. icon.style.stroke = icon.style.fill;
  497. icon.style.fill = tokens.color.neutral00;
  498. icon.style.lineWidth = 2;
  499. }
  500. return icon;
  501. }
  502. function dispatchSelectAction(seriesName, dataName, api, excludeSeriesId) {
  503. // downplay before unselect
  504. dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId);
  505. api.dispatchAction({
  506. type: 'legendToggleSelect',
  507. name: seriesName != null ? seriesName : dataName
  508. });
  509. // highlight after select
  510. // TODO highlight immediately may cause animation loss.
  511. dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId);
  512. }
  513. function isUseHoverLayer(api) {
  514. var list = api.getZr().storage.getDisplayList();
  515. var emphasisState;
  516. var i = 0;
  517. var len = list.length;
  518. while (i < len && !(emphasisState = list[i].states.emphasis)) {
  519. i++;
  520. }
  521. return emphasisState && emphasisState.hoverLayer;
  522. }
  523. function dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId) {
  524. // If element hover will move to a hoverLayer.
  525. if (!isUseHoverLayer(api)) {
  526. api.dispatchAction({
  527. type: 'highlight',
  528. seriesName: seriesName,
  529. name: dataName,
  530. excludeSeriesId: excludeSeriesId
  531. });
  532. }
  533. }
  534. function dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId) {
  535. // If element hover will move to a hoverLayer.
  536. if (!isUseHoverLayer(api)) {
  537. api.dispatchAction({
  538. type: 'downplay',
  539. seriesName: seriesName,
  540. name: dataName,
  541. excludeSeriesId: excludeSeriesId
  542. });
  543. }
  544. }
  545. export default LegendView;