modelHelper.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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 Model from '../../model/Model.js';
  41. import { each, curry, clone, defaults, isArray, indexOf } from 'zrender/lib/core/util.js'; // Build axisPointerModel, mergin tooltip.axisPointer model for each axis.
  42. // allAxesInfo should be updated when setOption performed.
  43. export function collect(ecModel, api) {
  44. var result = {
  45. /**
  46. * key: makeKey(axis.model)
  47. * value: {
  48. * axis,
  49. * coordSys,
  50. * axisPointerModel,
  51. * triggerTooltip,
  52. * triggerEmphasis,
  53. * involveSeries,
  54. * snap,
  55. * seriesModels,
  56. * seriesDataCount
  57. * }
  58. */
  59. axesInfo: {},
  60. seriesInvolved: false,
  61. /**
  62. * key: makeKey(coordSys.model)
  63. * value: Object: key makeKey(axis.model), value: axisInfo
  64. */
  65. coordSysAxesInfo: {},
  66. coordSysMap: {}
  67. };
  68. collectAxesInfo(result, ecModel, api); // Check seriesInvolved for performance, in case too many series in some chart.
  69. result.seriesInvolved && collectSeriesInfo(result, ecModel);
  70. return result;
  71. }
  72. function collectAxesInfo(result, ecModel, api) {
  73. var globalTooltipModel = ecModel.getComponent('tooltip');
  74. var globalAxisPointerModel = ecModel.getComponent('axisPointer'); // links can only be set on global.
  75. var linksOption = globalAxisPointerModel.get('link', true) || [];
  76. var linkGroups = []; // Collect axes info.
  77. each(api.getCoordinateSystems(), function (coordSys) {
  78. // Some coordinate system do not support axes, like geo.
  79. if (!coordSys.axisPointerEnabled) {
  80. return;
  81. }
  82. var coordSysKey = makeKey(coordSys.model);
  83. var axesInfoInCoordSys = result.coordSysAxesInfo[coordSysKey] = {};
  84. result.coordSysMap[coordSysKey] = coordSys; // Set tooltip (like 'cross') is a convenient way to show axisPointer
  85. // for user. So we enable setting tooltip on coordSys model.
  86. var coordSysModel = coordSys.model;
  87. var baseTooltipModel = coordSysModel.getModel('tooltip', globalTooltipModel);
  88. each(coordSys.getAxes(), curry(saveTooltipAxisInfo, false, null)); // If axis tooltip used, choose tooltip axis for each coordSys.
  89. // Notice this case: coordSys is `grid` but not `cartesian2D` here.
  90. if (coordSys.getTooltipAxes && globalTooltipModel // If tooltip.showContent is set as false, tooltip will not
  91. // show but axisPointer will show as normal.
  92. && baseTooltipModel.get('show')) {
  93. // Compatible with previous logic. But series.tooltip.trigger: 'axis'
  94. // or series.data[n].tooltip.trigger: 'axis' are not support any more.
  95. var triggerAxis = baseTooltipModel.get('trigger') === 'axis';
  96. var cross = baseTooltipModel.get(['axisPointer', 'type']) === 'cross';
  97. var tooltipAxes = coordSys.getTooltipAxes(baseTooltipModel.get(['axisPointer', 'axis']));
  98. if (triggerAxis || cross) {
  99. each(tooltipAxes.baseAxes, curry(saveTooltipAxisInfo, cross ? 'cross' : true, triggerAxis));
  100. }
  101. if (cross) {
  102. each(tooltipAxes.otherAxes, curry(saveTooltipAxisInfo, 'cross', false));
  103. }
  104. } // fromTooltip: true | false | 'cross'
  105. // triggerTooltip: true | false | null
  106. function saveTooltipAxisInfo(fromTooltip, triggerTooltip, axis) {
  107. var axisPointerModel = axis.model.getModel('axisPointer', globalAxisPointerModel);
  108. var axisPointerShow = axisPointerModel.get('show');
  109. if (!axisPointerShow || axisPointerShow === 'auto' && !fromTooltip && !isHandleTrigger(axisPointerModel)) {
  110. return;
  111. }
  112. if (triggerTooltip == null) {
  113. triggerTooltip = axisPointerModel.get('triggerTooltip');
  114. }
  115. axisPointerModel = fromTooltip ? makeAxisPointerModel(axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip) : axisPointerModel;
  116. var snap = axisPointerModel.get('snap');
  117. var triggerEmphasis = axisPointerModel.get('triggerEmphasis');
  118. var axisKey = makeKey(axis.model);
  119. var involveSeries = triggerTooltip || snap || axis.type === 'category'; // If result.axesInfo[key] exist, override it (tooltip has higher priority).
  120. var axisInfo = result.axesInfo[axisKey] = {
  121. key: axisKey,
  122. axis: axis,
  123. coordSys: coordSys,
  124. axisPointerModel: axisPointerModel,
  125. triggerTooltip: triggerTooltip,
  126. triggerEmphasis: triggerEmphasis,
  127. involveSeries: involveSeries,
  128. snap: snap,
  129. useHandle: isHandleTrigger(axisPointerModel),
  130. seriesModels: [],
  131. linkGroup: null
  132. };
  133. axesInfoInCoordSys[axisKey] = axisInfo;
  134. result.seriesInvolved = result.seriesInvolved || involveSeries;
  135. var groupIndex = getLinkGroupIndex(linksOption, axis);
  136. if (groupIndex != null) {
  137. var linkGroup = linkGroups[groupIndex] || (linkGroups[groupIndex] = {
  138. axesInfo: {}
  139. });
  140. linkGroup.axesInfo[axisKey] = axisInfo;
  141. linkGroup.mapper = linksOption[groupIndex].mapper;
  142. axisInfo.linkGroup = linkGroup;
  143. }
  144. }
  145. });
  146. }
  147. function makeAxisPointerModel(axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip) {
  148. var tooltipAxisPointerModel = baseTooltipModel.getModel('axisPointer');
  149. var fields = ['type', 'snap', 'lineStyle', 'shadowStyle', 'label', 'animation', 'animationDurationUpdate', 'animationEasingUpdate', 'z'];
  150. var volatileOption = {};
  151. each(fields, function (field) {
  152. volatileOption[field] = clone(tooltipAxisPointerModel.get(field));
  153. }); // category axis do not auto snap, otherwise some tick that do not
  154. // has value can not be hovered. value/time/log axis default snap if
  155. // triggered from tooltip and trigger tooltip.
  156. volatileOption.snap = axis.type !== 'category' && !!triggerTooltip; // Compatible with previous behavior, tooltip axis does not show label by default.
  157. // Only these properties can be overridden from tooltip to axisPointer.
  158. if (tooltipAxisPointerModel.get('type') === 'cross') {
  159. volatileOption.type = 'line';
  160. }
  161. var labelOption = volatileOption.label || (volatileOption.label = {}); // Follow the convention, do not show label when triggered by tooltip by default.
  162. labelOption.show == null && (labelOption.show = false);
  163. if (fromTooltip === 'cross') {
  164. // When 'cross', both axes show labels.
  165. var tooltipAxisPointerLabelShow = tooltipAxisPointerModel.get(['label', 'show']);
  166. labelOption.show = tooltipAxisPointerLabelShow != null ? tooltipAxisPointerLabelShow : true; // If triggerTooltip, this is a base axis, which should better not use cross style
  167. // (cross style is dashed by default)
  168. if (!triggerTooltip) {
  169. var crossStyle = volatileOption.lineStyle = tooltipAxisPointerModel.get('crossStyle');
  170. crossStyle && defaults(labelOption, crossStyle.textStyle);
  171. }
  172. }
  173. return axis.model.getModel('axisPointer', new Model(volatileOption, globalAxisPointerModel, ecModel));
  174. }
  175. function collectSeriesInfo(result, ecModel) {
  176. // Prepare data for axis trigger
  177. ecModel.eachSeries(function (seriesModel) {
  178. // Notice this case: this coordSys is `cartesian2D` but not `grid`.
  179. var coordSys = seriesModel.coordinateSystem;
  180. var seriesTooltipTrigger = seriesModel.get(['tooltip', 'trigger'], true);
  181. var seriesTooltipShow = seriesModel.get(['tooltip', 'show'], true);
  182. if (!coordSys || seriesTooltipTrigger === 'none' || seriesTooltipTrigger === false || seriesTooltipTrigger === 'item' || seriesTooltipShow === false || seriesModel.get(['axisPointer', 'show'], true) === false) {
  183. return;
  184. }
  185. each(result.coordSysAxesInfo[makeKey(coordSys.model)], function (axisInfo) {
  186. var axis = axisInfo.axis;
  187. if (coordSys.getAxis(axis.dim) === axis) {
  188. axisInfo.seriesModels.push(seriesModel);
  189. axisInfo.seriesDataCount == null && (axisInfo.seriesDataCount = 0);
  190. axisInfo.seriesDataCount += seriesModel.getData().count();
  191. }
  192. });
  193. });
  194. }
  195. /**
  196. * For example:
  197. * {
  198. * axisPointer: {
  199. * links: [{
  200. * xAxisIndex: [2, 4],
  201. * yAxisIndex: 'all'
  202. * }, {
  203. * xAxisId: ['a5', 'a7'],
  204. * xAxisName: 'xxx'
  205. * }]
  206. * }
  207. * }
  208. */
  209. function getLinkGroupIndex(linksOption, axis) {
  210. var axisModel = axis.model;
  211. var dim = axis.dim;
  212. for (var i = 0; i < linksOption.length; i++) {
  213. var linkOption = linksOption[i] || {};
  214. if (checkPropInLink(linkOption[dim + 'AxisId'], axisModel.id) || checkPropInLink(linkOption[dim + 'AxisIndex'], axisModel.componentIndex) || checkPropInLink(linkOption[dim + 'AxisName'], axisModel.name)) {
  215. return i;
  216. }
  217. }
  218. }
  219. function checkPropInLink(linkPropValue, axisPropValue) {
  220. return linkPropValue === 'all' || isArray(linkPropValue) && indexOf(linkPropValue, axisPropValue) >= 0 || linkPropValue === axisPropValue;
  221. }
  222. export function fixValue(axisModel) {
  223. var axisInfo = getAxisInfo(axisModel);
  224. if (!axisInfo) {
  225. return;
  226. }
  227. var axisPointerModel = axisInfo.axisPointerModel;
  228. var scale = axisInfo.axis.scale;
  229. var option = axisPointerModel.option;
  230. var status = axisPointerModel.get('status');
  231. var value = axisPointerModel.get('value'); // Parse init value for category and time axis.
  232. if (value != null) {
  233. value = scale.parse(value);
  234. }
  235. var useHandle = isHandleTrigger(axisPointerModel); // If `handle` used, `axisPointer` will always be displayed, so value
  236. // and status should be initialized.
  237. if (status == null) {
  238. option.status = useHandle ? 'show' : 'hide';
  239. }
  240. var extent = scale.getExtent().slice();
  241. extent[0] > extent[1] && extent.reverse();
  242. if ( // Pick a value on axis when initializing.
  243. value == null // If both `handle` and `dataZoom` are used, value may be out of axis extent,
  244. // where we should re-pick a value to keep `handle` displaying normally.
  245. || value > extent[1]) {
  246. // Make handle displayed on the end of the axis when init, which looks better.
  247. value = extent[1];
  248. }
  249. if (value < extent[0]) {
  250. value = extent[0];
  251. }
  252. option.value = value;
  253. if (useHandle) {
  254. option.status = axisInfo.axis.scale.isBlank() ? 'hide' : 'show';
  255. }
  256. }
  257. export function getAxisInfo(axisModel) {
  258. var coordSysAxesInfo = (axisModel.ecModel.getComponent('axisPointer') || {}).coordSysAxesInfo;
  259. return coordSysAxesInfo && coordSysAxesInfo.axesInfo[makeKey(axisModel)];
  260. }
  261. export function getAxisPointerModel(axisModel) {
  262. var axisInfo = getAxisInfo(axisModel);
  263. return axisInfo && axisInfo.axisPointerModel;
  264. }
  265. function isHandleTrigger(axisPointerModel) {
  266. return !!axisPointerModel.get(['handle', 'show']);
  267. }
  268. /**
  269. * @param {module:echarts/model/Model} model
  270. * @return {string} unique key
  271. */
  272. export function makeKey(model) {
  273. return model.type + '||' + model.id;
  274. }