MarkLineView.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  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 SeriesData from '../../data/SeriesData.js';
  42. import * as numberUtil from '../../util/number.js';
  43. import * as markerHelper from './markerHelper.js';
  44. import LineDraw from '../../chart/helper/LineDraw.js';
  45. import MarkerView from './MarkerView.js';
  46. import { getStackedDimension } from '../../data/helper/dataStackHelper.js';
  47. import { isCoordinateSystemType } from '../../coord/CoordinateSystem.js';
  48. import { getECData } from '../../util/innerStore.js';
  49. import MarkerModel from './MarkerModel.js';
  50. import { isArray, retrieve, retrieve2, clone, extend, logError, merge, map, curry, filter, isNumber } from 'zrender/lib/core/util.js';
  51. import { makeInner } from '../../util/model.js';
  52. import { getVisualFromData } from '../../visual/helper.js';
  53. var inner = makeInner();
  54. var markLineTransform = function (seriesModel, coordSys, mlModel, item) {
  55. var data = seriesModel.getData();
  56. var itemArray;
  57. if (!isArray(item)) {
  58. // Special type markLine like 'min', 'max', 'average', 'median'
  59. var mlType = item.type;
  60. if (mlType === 'min' || mlType === 'max' || mlType === 'average' || mlType === 'median' // In case
  61. // data: [{
  62. // yAxis: 10
  63. // }]
  64. || item.xAxis != null || item.yAxis != null) {
  65. var valueAxis = void 0;
  66. var value = void 0;
  67. if (item.yAxis != null || item.xAxis != null) {
  68. valueAxis = coordSys.getAxis(item.yAxis != null ? 'y' : 'x');
  69. value = retrieve(item.yAxis, item.xAxis);
  70. } else {
  71. var axisInfo = markerHelper.getAxisInfo(item, data, coordSys, seriesModel);
  72. valueAxis = axisInfo.valueAxis;
  73. var valueDataDim = getStackedDimension(data, axisInfo.valueDataDim);
  74. value = markerHelper.numCalculate(data, valueDataDim, mlType);
  75. }
  76. var valueIndex = valueAxis.dim === 'x' ? 0 : 1;
  77. var baseIndex = 1 - valueIndex; // Normized to 2d data with start and end point
  78. var mlFrom = clone(item);
  79. var mlTo = {
  80. coord: []
  81. };
  82. mlFrom.type = null;
  83. mlFrom.coord = [];
  84. mlFrom.coord[baseIndex] = -Infinity;
  85. mlTo.coord[baseIndex] = Infinity;
  86. var precision = mlModel.get('precision');
  87. if (precision >= 0 && isNumber(value)) {
  88. value = +value.toFixed(Math.min(precision, 20));
  89. }
  90. mlFrom.coord[valueIndex] = mlTo.coord[valueIndex] = value;
  91. itemArray = [mlFrom, mlTo, {
  92. type: mlType,
  93. valueIndex: item.valueIndex,
  94. // Force to use the value of calculated value.
  95. value: value
  96. }];
  97. } else {
  98. // Invalid data
  99. if (process.env.NODE_ENV !== 'production') {
  100. logError('Invalid markLine data.');
  101. }
  102. itemArray = [];
  103. }
  104. } else {
  105. itemArray = item;
  106. }
  107. var normalizedItem = [markerHelper.dataTransform(seriesModel, itemArray[0]), markerHelper.dataTransform(seriesModel, itemArray[1]), extend({}, itemArray[2])]; // Avoid line data type is extended by from(to) data type
  108. normalizedItem[2].type = normalizedItem[2].type || null; // Merge from option and to option into line option
  109. merge(normalizedItem[2], normalizedItem[0]);
  110. merge(normalizedItem[2], normalizedItem[1]);
  111. return normalizedItem;
  112. };
  113. function isInfinity(val) {
  114. return !isNaN(val) && !isFinite(val);
  115. } // If a markLine has one dim
  116. function ifMarkLineHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) {
  117. var otherDimIndex = 1 - dimIndex;
  118. var dimName = coordSys.dimensions[dimIndex];
  119. return isInfinity(fromCoord[otherDimIndex]) && isInfinity(toCoord[otherDimIndex]) && fromCoord[dimIndex] === toCoord[dimIndex] && coordSys.getAxis(dimName).containData(fromCoord[dimIndex]);
  120. }
  121. function markLineFilter(coordSys, item) {
  122. if (coordSys.type === 'cartesian2d') {
  123. var fromCoord = item[0].coord;
  124. var toCoord = item[1].coord; // In case
  125. // {
  126. // markLine: {
  127. // data: [{ yAxis: 2 }]
  128. // }
  129. // }
  130. if (fromCoord && toCoord && (ifMarkLineHasOnlyDim(1, fromCoord, toCoord, coordSys) || ifMarkLineHasOnlyDim(0, fromCoord, toCoord, coordSys))) {
  131. return true;
  132. }
  133. }
  134. return markerHelper.dataFilter(coordSys, item[0]) && markerHelper.dataFilter(coordSys, item[1]);
  135. }
  136. function updateSingleMarkerEndLayout(data, idx, isFrom, seriesModel, api) {
  137. var coordSys = seriesModel.coordinateSystem;
  138. var itemModel = data.getItemModel(idx);
  139. var point;
  140. var xPx = numberUtil.parsePercent(itemModel.get('x'), api.getWidth());
  141. var yPx = numberUtil.parsePercent(itemModel.get('y'), api.getHeight());
  142. if (!isNaN(xPx) && !isNaN(yPx)) {
  143. point = [xPx, yPx];
  144. } else {
  145. // Chart like bar may have there own marker positioning logic
  146. if (seriesModel.getMarkerPosition) {
  147. // Use the getMarkerPosition
  148. point = seriesModel.getMarkerPosition(data.getValues(data.dimensions, idx));
  149. } else {
  150. var dims = coordSys.dimensions;
  151. var x = data.get(dims[0], idx);
  152. var y = data.get(dims[1], idx);
  153. point = coordSys.dataToPoint([x, y]);
  154. } // Expand line to the edge of grid if value on one axis is Inifnity
  155. // In case
  156. // markLine: {
  157. // data: [{
  158. // yAxis: 2
  159. // // or
  160. // type: 'average'
  161. // }]
  162. // }
  163. if (isCoordinateSystemType(coordSys, 'cartesian2d')) {
  164. // TODO: TYPE ts@4.1 may still infer it as Axis instead of Axis2D. Not sure if it's a bug
  165. var xAxis = coordSys.getAxis('x');
  166. var yAxis = coordSys.getAxis('y');
  167. var dims = coordSys.dimensions;
  168. if (isInfinity(data.get(dims[0], idx))) {
  169. point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[isFrom ? 0 : 1]);
  170. } else if (isInfinity(data.get(dims[1], idx))) {
  171. point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[isFrom ? 0 : 1]);
  172. }
  173. } // Use x, y if has any
  174. if (!isNaN(xPx)) {
  175. point[0] = xPx;
  176. }
  177. if (!isNaN(yPx)) {
  178. point[1] = yPx;
  179. }
  180. }
  181. data.setItemLayout(idx, point);
  182. }
  183. var MarkLineView =
  184. /** @class */
  185. function (_super) {
  186. __extends(MarkLineView, _super);
  187. function MarkLineView() {
  188. var _this = _super !== null && _super.apply(this, arguments) || this;
  189. _this.type = MarkLineView.type;
  190. return _this;
  191. }
  192. MarkLineView.prototype.updateTransform = function (markLineModel, ecModel, api) {
  193. ecModel.eachSeries(function (seriesModel) {
  194. var mlModel = MarkerModel.getMarkerModelFromSeries(seriesModel, 'markLine');
  195. if (mlModel) {
  196. var mlData_1 = mlModel.getData();
  197. var fromData_1 = inner(mlModel).from;
  198. var toData_1 = inner(mlModel).to; // Update visual and layout of from symbol and to symbol
  199. fromData_1.each(function (idx) {
  200. updateSingleMarkerEndLayout(fromData_1, idx, true, seriesModel, api);
  201. updateSingleMarkerEndLayout(toData_1, idx, false, seriesModel, api);
  202. }); // Update layout of line
  203. mlData_1.each(function (idx) {
  204. mlData_1.setItemLayout(idx, [fromData_1.getItemLayout(idx), toData_1.getItemLayout(idx)]);
  205. });
  206. this.markerGroupMap.get(seriesModel.id).updateLayout();
  207. }
  208. }, this);
  209. };
  210. MarkLineView.prototype.renderSeries = function (seriesModel, mlModel, ecModel, api) {
  211. var coordSys = seriesModel.coordinateSystem;
  212. var seriesId = seriesModel.id;
  213. var seriesData = seriesModel.getData();
  214. var lineDrawMap = this.markerGroupMap;
  215. var lineDraw = lineDrawMap.get(seriesId) || lineDrawMap.set(seriesId, new LineDraw());
  216. this.group.add(lineDraw.group);
  217. var mlData = createList(coordSys, seriesModel, mlModel);
  218. var fromData = mlData.from;
  219. var toData = mlData.to;
  220. var lineData = mlData.line;
  221. inner(mlModel).from = fromData;
  222. inner(mlModel).to = toData; // Line data for tooltip and formatter
  223. mlModel.setData(lineData); // TODO
  224. // Functionally, `symbolSize` & `symbolOffset` can also be 2D array now.
  225. // But the related logic and type definition are not finished yet.
  226. // Finish it if required
  227. var symbolType = mlModel.get('symbol');
  228. var symbolSize = mlModel.get('symbolSize');
  229. var symbolRotate = mlModel.get('symbolRotate');
  230. var symbolOffset = mlModel.get('symbolOffset'); // TODO: support callback function like markPoint
  231. if (!isArray(symbolType)) {
  232. symbolType = [symbolType, symbolType];
  233. }
  234. if (!isArray(symbolSize)) {
  235. symbolSize = [symbolSize, symbolSize];
  236. }
  237. if (!isArray(symbolRotate)) {
  238. symbolRotate = [symbolRotate, symbolRotate];
  239. }
  240. if (!isArray(symbolOffset)) {
  241. symbolOffset = [symbolOffset, symbolOffset];
  242. } // Update visual and layout of from symbol and to symbol
  243. mlData.from.each(function (idx) {
  244. updateDataVisualAndLayout(fromData, idx, true);
  245. updateDataVisualAndLayout(toData, idx, false);
  246. }); // Update visual and layout of line
  247. lineData.each(function (idx) {
  248. var lineStyle = lineData.getItemModel(idx).getModel('lineStyle').getLineStyle(); // lineData.setItemVisual(idx, {
  249. // color: lineColor || fromData.getItemVisual(idx, 'color')
  250. // });
  251. lineData.setItemLayout(idx, [fromData.getItemLayout(idx), toData.getItemLayout(idx)]);
  252. if (lineStyle.stroke == null) {
  253. lineStyle.stroke = fromData.getItemVisual(idx, 'style').fill;
  254. }
  255. lineData.setItemVisual(idx, {
  256. fromSymbolKeepAspect: fromData.getItemVisual(idx, 'symbolKeepAspect'),
  257. fromSymbolOffset: fromData.getItemVisual(idx, 'symbolOffset'),
  258. fromSymbolRotate: fromData.getItemVisual(idx, 'symbolRotate'),
  259. fromSymbolSize: fromData.getItemVisual(idx, 'symbolSize'),
  260. fromSymbol: fromData.getItemVisual(idx, 'symbol'),
  261. toSymbolKeepAspect: toData.getItemVisual(idx, 'symbolKeepAspect'),
  262. toSymbolOffset: toData.getItemVisual(idx, 'symbolOffset'),
  263. toSymbolRotate: toData.getItemVisual(idx, 'symbolRotate'),
  264. toSymbolSize: toData.getItemVisual(idx, 'symbolSize'),
  265. toSymbol: toData.getItemVisual(idx, 'symbol'),
  266. style: lineStyle
  267. });
  268. });
  269. lineDraw.updateData(lineData); // Set host model for tooltip
  270. // FIXME
  271. mlData.line.eachItemGraphicEl(function (el) {
  272. getECData(el).dataModel = mlModel;
  273. el.traverse(function (child) {
  274. getECData(child).dataModel = mlModel;
  275. });
  276. });
  277. function updateDataVisualAndLayout(data, idx, isFrom) {
  278. var itemModel = data.getItemModel(idx);
  279. updateSingleMarkerEndLayout(data, idx, isFrom, seriesModel, api);
  280. var style = itemModel.getModel('itemStyle').getItemStyle();
  281. if (style.fill == null) {
  282. style.fill = getVisualFromData(seriesData, 'color');
  283. }
  284. data.setItemVisual(idx, {
  285. symbolKeepAspect: itemModel.get('symbolKeepAspect'),
  286. // `0` should be considered as a valid value, so use `retrieve2` instead of `||`
  287. symbolOffset: retrieve2(itemModel.get('symbolOffset', true), symbolOffset[isFrom ? 0 : 1]),
  288. symbolRotate: retrieve2(itemModel.get('symbolRotate', true), symbolRotate[isFrom ? 0 : 1]),
  289. // TODO: when 2d array is supported, it should ignore parent
  290. symbolSize: retrieve2(itemModel.get('symbolSize'), symbolSize[isFrom ? 0 : 1]),
  291. symbol: retrieve2(itemModel.get('symbol', true), symbolType[isFrom ? 0 : 1]),
  292. style: style
  293. });
  294. }
  295. this.markKeep(lineDraw);
  296. lineDraw.group.silent = mlModel.get('silent') || seriesModel.get('silent');
  297. };
  298. MarkLineView.type = 'markLine';
  299. return MarkLineView;
  300. }(MarkerView);
  301. function createList(coordSys, seriesModel, mlModel) {
  302. var coordDimsInfos;
  303. if (coordSys) {
  304. coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) {
  305. var info = seriesModel.getData().getDimensionInfo(seriesModel.getData().mapDimension(coordDim)) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys
  306. return extend(extend({}, info), {
  307. name: coordDim,
  308. // DON'T use ordinalMeta to parse and collect ordinal.
  309. ordinalMeta: null
  310. });
  311. });
  312. } else {
  313. coordDimsInfos = [{
  314. name: 'value',
  315. type: 'float'
  316. }];
  317. }
  318. var fromData = new SeriesData(coordDimsInfos, mlModel);
  319. var toData = new SeriesData(coordDimsInfos, mlModel); // No dimensions
  320. var lineData = new SeriesData([], mlModel);
  321. var optData = map(mlModel.get('data'), curry(markLineTransform, seriesModel, coordSys, mlModel));
  322. if (coordSys) {
  323. optData = filter(optData, curry(markLineFilter, coordSys));
  324. }
  325. var dimValueGetter = markerHelper.createMarkerDimValueGetter(!!coordSys, coordDimsInfos);
  326. fromData.initData(map(optData, function (item) {
  327. return item[0];
  328. }), null, dimValueGetter);
  329. toData.initData(map(optData, function (item) {
  330. return item[1];
  331. }), null, dimValueGetter);
  332. lineData.initData(map(optData, function (item) {
  333. return item[2];
  334. }));
  335. lineData.hasItemOption = true;
  336. return {
  337. from: fromData,
  338. to: toData,
  339. line: lineData
  340. };
  341. }
  342. export default MarkLineView;