MarkAreaView.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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"; // TODO Optimize on polar
  41. import * as colorUtil from 'zrender/lib/tool/color.js';
  42. import SeriesData from '../../data/SeriesData.js';
  43. import * as numberUtil from '../../util/number.js';
  44. import * as graphic from '../../util/graphic.js';
  45. import { toggleHoverEmphasis, setStatesStylesFromModel } from '../../util/states.js';
  46. import * as markerHelper from './markerHelper.js';
  47. import MarkerView from './MarkerView.js';
  48. import { retrieve, mergeAll, map, curry, filter, extend, isString } from 'zrender/lib/core/util.js';
  49. import { isCoordinateSystemType } from '../../coord/CoordinateSystem.js';
  50. import MarkerModel from './MarkerModel.js';
  51. import { makeInner } from '../../util/model.js';
  52. import { getVisualFromData } from '../../visual/helper.js';
  53. import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle.js';
  54. import { getECData } from '../../util/innerStore.js';
  55. import { parseDataValue } from '../../data/helper/dataValueHelper.js';
  56. var inner = makeInner();
  57. var markAreaTransform = function (seriesModel, coordSys, maModel, item) {
  58. // item may be null
  59. var item0 = item[0];
  60. var item1 = item[1];
  61. if (!item0 || !item1) {
  62. return;
  63. }
  64. var lt = markerHelper.dataTransform(seriesModel, item0);
  65. var rb = markerHelper.dataTransform(seriesModel, item1); // FIXME make sure lt is less than rb
  66. var ltCoord = lt.coord;
  67. var rbCoord = rb.coord;
  68. ltCoord[0] = retrieve(ltCoord[0], -Infinity);
  69. ltCoord[1] = retrieve(ltCoord[1], -Infinity);
  70. rbCoord[0] = retrieve(rbCoord[0], Infinity);
  71. rbCoord[1] = retrieve(rbCoord[1], Infinity); // Merge option into one
  72. var result = mergeAll([{}, lt, rb]);
  73. result.coord = [lt.coord, rb.coord];
  74. result.x0 = lt.x;
  75. result.y0 = lt.y;
  76. result.x1 = rb.x;
  77. result.y1 = rb.y;
  78. return result;
  79. };
  80. function isInfinity(val) {
  81. return !isNaN(val) && !isFinite(val);
  82. } // If a markArea has one dim
  83. function ifMarkAreaHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) {
  84. var otherDimIndex = 1 - dimIndex;
  85. return isInfinity(fromCoord[otherDimIndex]) && isInfinity(toCoord[otherDimIndex]);
  86. }
  87. function markAreaFilter(coordSys, item) {
  88. var fromCoord = item.coord[0];
  89. var toCoord = item.coord[1];
  90. var item0 = {
  91. coord: fromCoord,
  92. x: item.x0,
  93. y: item.y0
  94. };
  95. var item1 = {
  96. coord: toCoord,
  97. x: item.x1,
  98. y: item.y1
  99. };
  100. if (isCoordinateSystemType(coordSys, 'cartesian2d')) {
  101. // In case
  102. // {
  103. // markArea: {
  104. // data: [{ yAxis: 2 }]
  105. // }
  106. // }
  107. if (fromCoord && toCoord && (ifMarkAreaHasOnlyDim(1, fromCoord, toCoord, coordSys) || ifMarkAreaHasOnlyDim(0, fromCoord, toCoord, coordSys))) {
  108. return true;
  109. } // Directly returning true may also do the work,
  110. // because markArea will not be shown automatically
  111. // when it's not included in coordinate system.
  112. // But filtering ahead can avoid keeping rendering markArea
  113. // when there are too many of them.
  114. return markerHelper.zoneFilter(coordSys, item0, item1);
  115. }
  116. return markerHelper.dataFilter(coordSys, item0) || markerHelper.dataFilter(coordSys, item1);
  117. } // dims can be ['x0', 'y0'], ['x1', 'y1'], ['x0', 'y1'], ['x1', 'y0']
  118. function getSingleMarkerEndPoint(data, idx, dims, seriesModel, api) {
  119. var coordSys = seriesModel.coordinateSystem;
  120. var itemModel = data.getItemModel(idx);
  121. var point;
  122. var xPx = numberUtil.parsePercent(itemModel.get(dims[0]), api.getWidth());
  123. var yPx = numberUtil.parsePercent(itemModel.get(dims[1]), api.getHeight());
  124. if (!isNaN(xPx) && !isNaN(yPx)) {
  125. point = [xPx, yPx];
  126. } else {
  127. // Chart like bar may have there own marker positioning logic
  128. if (seriesModel.getMarkerPosition) {
  129. // Consider the case that user input the right-bottom point first
  130. // Pick the larger x and y as 'x1' and 'y1'
  131. var pointValue0 = data.getValues(['x0', 'y0'], idx);
  132. var pointValue1 = data.getValues(['x1', 'y1'], idx);
  133. var clampPointValue0 = coordSys.clampData(pointValue0);
  134. var clampPointValue1 = coordSys.clampData(pointValue1);
  135. var pointValue = [];
  136. if (dims[0] === 'x0') {
  137. pointValue[0] = clampPointValue0[0] > clampPointValue1[0] ? pointValue1[0] : pointValue0[0];
  138. } else {
  139. pointValue[0] = clampPointValue0[0] > clampPointValue1[0] ? pointValue0[0] : pointValue1[0];
  140. }
  141. if (dims[1] === 'y0') {
  142. pointValue[1] = clampPointValue0[1] > clampPointValue1[1] ? pointValue1[1] : pointValue0[1];
  143. } else {
  144. pointValue[1] = clampPointValue0[1] > clampPointValue1[1] ? pointValue0[1] : pointValue1[1];
  145. } // Use the getMarkerPosition
  146. point = seriesModel.getMarkerPosition(pointValue, dims, true);
  147. } else {
  148. var x = data.get(dims[0], idx);
  149. var y = data.get(dims[1], idx);
  150. var pt = [x, y];
  151. coordSys.clampData && coordSys.clampData(pt, pt);
  152. point = coordSys.dataToPoint(pt, true);
  153. }
  154. if (isCoordinateSystemType(coordSys, 'cartesian2d')) {
  155. // TODO: TYPE ts@4.1 may still infer it as Axis instead of Axis2D. Not sure if it's a bug
  156. var xAxis = coordSys.getAxis('x');
  157. var yAxis = coordSys.getAxis('y');
  158. var x = data.get(dims[0], idx);
  159. var y = data.get(dims[1], idx);
  160. if (isInfinity(x)) {
  161. point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[dims[0] === 'x0' ? 0 : 1]);
  162. } else if (isInfinity(y)) {
  163. point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[dims[1] === 'y0' ? 0 : 1]);
  164. }
  165. } // Use x, y if has any
  166. if (!isNaN(xPx)) {
  167. point[0] = xPx;
  168. }
  169. if (!isNaN(yPx)) {
  170. point[1] = yPx;
  171. }
  172. }
  173. return point;
  174. }
  175. export var dimPermutations = [['x0', 'y0'], ['x1', 'y0'], ['x1', 'y1'], ['x0', 'y1']];
  176. var MarkAreaView =
  177. /** @class */
  178. function (_super) {
  179. __extends(MarkAreaView, _super);
  180. function MarkAreaView() {
  181. var _this = _super !== null && _super.apply(this, arguments) || this;
  182. _this.type = MarkAreaView.type;
  183. return _this;
  184. }
  185. MarkAreaView.prototype.updateTransform = function (markAreaModel, ecModel, api) {
  186. ecModel.eachSeries(function (seriesModel) {
  187. var maModel = MarkerModel.getMarkerModelFromSeries(seriesModel, 'markArea');
  188. if (maModel) {
  189. var areaData_1 = maModel.getData();
  190. areaData_1.each(function (idx) {
  191. var points = map(dimPermutations, function (dim) {
  192. return getSingleMarkerEndPoint(areaData_1, idx, dim, seriesModel, api);
  193. }); // Layout
  194. areaData_1.setItemLayout(idx, points);
  195. var el = areaData_1.getItemGraphicEl(idx);
  196. el.setShape('points', points);
  197. });
  198. }
  199. }, this);
  200. };
  201. MarkAreaView.prototype.renderSeries = function (seriesModel, maModel, ecModel, api) {
  202. var coordSys = seriesModel.coordinateSystem;
  203. var seriesId = seriesModel.id;
  204. var seriesData = seriesModel.getData();
  205. var areaGroupMap = this.markerGroupMap;
  206. var polygonGroup = areaGroupMap.get(seriesId) || areaGroupMap.set(seriesId, {
  207. group: new graphic.Group()
  208. });
  209. this.group.add(polygonGroup.group);
  210. this.markKeep(polygonGroup);
  211. var areaData = createList(coordSys, seriesModel, maModel); // Line data for tooltip and formatter
  212. maModel.setData(areaData); // Update visual and layout of line
  213. areaData.each(function (idx) {
  214. // Layout
  215. var points = map(dimPermutations, function (dim) {
  216. return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api);
  217. });
  218. var xAxisScale = coordSys.getAxis('x').scale;
  219. var yAxisScale = coordSys.getAxis('y').scale;
  220. var xAxisExtent = xAxisScale.getExtent();
  221. var yAxisExtent = yAxisScale.getExtent();
  222. var xPointExtent = [xAxisScale.parse(areaData.get('x0', idx)), xAxisScale.parse(areaData.get('x1', idx))];
  223. var yPointExtent = [yAxisScale.parse(areaData.get('y0', idx)), yAxisScale.parse(areaData.get('y1', idx))];
  224. numberUtil.asc(xPointExtent);
  225. numberUtil.asc(yPointExtent);
  226. var overlapped = !(xAxisExtent[0] > xPointExtent[1] || xAxisExtent[1] < xPointExtent[0] || yAxisExtent[0] > yPointExtent[1] || yAxisExtent[1] < yPointExtent[0]); // If none of the area is inside coordSys, allClipped is set to be true
  227. // in layout so that label will not be displayed. See #12591
  228. var allClipped = !overlapped;
  229. areaData.setItemLayout(idx, {
  230. points: points,
  231. allClipped: allClipped
  232. });
  233. var style = areaData.getItemModel(idx).getModel('itemStyle').getItemStyle();
  234. var color = getVisualFromData(seriesData, 'color');
  235. if (!style.fill) {
  236. style.fill = color;
  237. if (isString(style.fill)) {
  238. style.fill = colorUtil.modifyAlpha(style.fill, 0.4);
  239. }
  240. }
  241. if (!style.stroke) {
  242. style.stroke = color;
  243. } // Visual
  244. areaData.setItemVisual(idx, 'style', style);
  245. });
  246. areaData.diff(inner(polygonGroup).data).add(function (idx) {
  247. var layout = areaData.getItemLayout(idx);
  248. if (!layout.allClipped) {
  249. var polygon = new graphic.Polygon({
  250. shape: {
  251. points: layout.points
  252. }
  253. });
  254. areaData.setItemGraphicEl(idx, polygon);
  255. polygonGroup.group.add(polygon);
  256. }
  257. }).update(function (newIdx, oldIdx) {
  258. var polygon = inner(polygonGroup).data.getItemGraphicEl(oldIdx);
  259. var layout = areaData.getItemLayout(newIdx);
  260. if (!layout.allClipped) {
  261. if (polygon) {
  262. graphic.updateProps(polygon, {
  263. shape: {
  264. points: layout.points
  265. }
  266. }, maModel, newIdx);
  267. } else {
  268. polygon = new graphic.Polygon({
  269. shape: {
  270. points: layout.points
  271. }
  272. });
  273. }
  274. areaData.setItemGraphicEl(newIdx, polygon);
  275. polygonGroup.group.add(polygon);
  276. } else if (polygon) {
  277. polygonGroup.group.remove(polygon);
  278. }
  279. }).remove(function (idx) {
  280. var polygon = inner(polygonGroup).data.getItemGraphicEl(idx);
  281. polygonGroup.group.remove(polygon);
  282. }).execute();
  283. areaData.eachItemGraphicEl(function (polygon, idx) {
  284. var itemModel = areaData.getItemModel(idx);
  285. var style = areaData.getItemVisual(idx, 'style');
  286. polygon.useStyle(areaData.getItemVisual(idx, 'style'));
  287. setLabelStyle(polygon, getLabelStatesModels(itemModel), {
  288. labelFetcher: maModel,
  289. labelDataIndex: idx,
  290. defaultText: areaData.getName(idx) || '',
  291. inheritColor: isString(style.fill) ? colorUtil.modifyAlpha(style.fill, 1) : '#000'
  292. });
  293. setStatesStylesFromModel(polygon, itemModel);
  294. toggleHoverEmphasis(polygon, null, null, itemModel.get(['emphasis', 'disabled']));
  295. getECData(polygon).dataModel = maModel;
  296. });
  297. inner(polygonGroup).data = areaData;
  298. polygonGroup.group.silent = maModel.get('silent') || seriesModel.get('silent');
  299. };
  300. MarkAreaView.type = 'markArea';
  301. return MarkAreaView;
  302. }(MarkerView);
  303. function createList(coordSys, seriesModel, maModel) {
  304. var areaData;
  305. var dataDims;
  306. var dims = ['x0', 'y0', 'x1', 'y1'];
  307. if (coordSys) {
  308. var coordDimsInfos_1 = map(coordSys && coordSys.dimensions, function (coordDim) {
  309. var data = seriesModel.getData();
  310. var info = data.getDimensionInfo(data.mapDimension(coordDim)) || {}; // In map series data don't have lng and lat dimension. Fallback to same with coordSys
  311. return extend(extend({}, info), {
  312. name: coordDim,
  313. // DON'T use ordinalMeta to parse and collect ordinal.
  314. ordinalMeta: null
  315. });
  316. });
  317. dataDims = map(dims, function (dim, idx) {
  318. return {
  319. name: dim,
  320. type: coordDimsInfos_1[idx % 2].type
  321. };
  322. });
  323. areaData = new SeriesData(dataDims, maModel);
  324. } else {
  325. dataDims = [{
  326. name: 'value',
  327. type: 'float'
  328. }];
  329. areaData = new SeriesData(dataDims, maModel);
  330. }
  331. var optData = map(maModel.get('data'), curry(markAreaTransform, seriesModel, coordSys, maModel));
  332. if (coordSys) {
  333. optData = filter(optData, curry(markAreaFilter, coordSys));
  334. }
  335. var dimValueGetter = coordSys ? function (item, dimName, dataIndex, dimIndex) {
  336. // TODO should convert to ParsedValue?
  337. var rawVal = item.coord[Math.floor(dimIndex / 2)][dimIndex % 2];
  338. return parseDataValue(rawVal, dataDims[dimIndex]);
  339. } : function (item, dimName, dataIndex, dimIndex) {
  340. return parseDataValue(item.value, dataDims[dimIndex]);
  341. };
  342. areaData.initData(optData, null, dimValueGetter);
  343. areaData.hasItemOption = true;
  344. return areaData;
  345. }
  346. export default MarkAreaView;