PiecewiseModel.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  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 VisualMapModel from './VisualMapModel.js';
  43. import VisualMapping from '../../visual/VisualMapping.js';
  44. import visualDefault from '../../visual/visualDefault.js';
  45. import { reformIntervals } from '../../util/number.js';
  46. import { inheritDefaultOption } from '../../util/component.js';
  47. var PiecewiseModel = /** @class */function (_super) {
  48. __extends(PiecewiseModel, _super);
  49. function PiecewiseModel() {
  50. var _this = _super !== null && _super.apply(this, arguments) || this;
  51. _this.type = PiecewiseModel.type;
  52. /**
  53. * The order is always [low, ..., high].
  54. * [{text: string, interval: Array.<number>}, ...]
  55. */
  56. _this._pieceList = [];
  57. return _this;
  58. }
  59. PiecewiseModel.prototype.optionUpdated = function (newOption, isInit) {
  60. _super.prototype.optionUpdated.apply(this, arguments);
  61. this.resetExtent();
  62. var mode = this._mode = this._determineMode();
  63. this._pieceList = [];
  64. resetMethods[this._mode].call(this, this._pieceList);
  65. this._resetSelected(newOption, isInit);
  66. var categories = this.option.categories;
  67. this.resetVisual(function (mappingOption, state) {
  68. if (mode === 'categories') {
  69. mappingOption.mappingMethod = 'category';
  70. mappingOption.categories = zrUtil.clone(categories);
  71. } else {
  72. mappingOption.dataExtent = this.getExtent();
  73. mappingOption.mappingMethod = 'piecewise';
  74. mappingOption.pieceList = zrUtil.map(this._pieceList, function (piece) {
  75. piece = zrUtil.clone(piece);
  76. if (state !== 'inRange') {
  77. // FIXME
  78. // outOfRange do not support special visual in pieces.
  79. piece.visual = null;
  80. }
  81. return piece;
  82. });
  83. }
  84. });
  85. };
  86. /**
  87. * @protected
  88. * @override
  89. */
  90. PiecewiseModel.prototype.completeVisualOption = function () {
  91. // Consider this case:
  92. // visualMap: {
  93. // pieces: [{symbol: 'circle', lt: 0}, {symbol: 'rect', gte: 0}]
  94. // }
  95. // where no inRange/outOfRange set but only pieces. So we should make
  96. // default inRange/outOfRange for this case, otherwise visuals that only
  97. // appear in `pieces` will not be taken into account in visual encoding.
  98. var option = this.option;
  99. var visualTypesInPieces = {};
  100. var visualTypes = VisualMapping.listVisualTypes();
  101. var isCategory = this.isCategory();
  102. zrUtil.each(option.pieces, function (piece) {
  103. zrUtil.each(visualTypes, function (visualType) {
  104. if (piece.hasOwnProperty(visualType)) {
  105. visualTypesInPieces[visualType] = 1;
  106. }
  107. });
  108. });
  109. zrUtil.each(visualTypesInPieces, function (v, visualType) {
  110. var exists = false;
  111. zrUtil.each(this.stateList, function (state) {
  112. exists = exists || has(option, state, visualType) || has(option.target, state, visualType);
  113. }, this);
  114. !exists && zrUtil.each(this.stateList, function (state) {
  115. (option[state] || (option[state] = {}))[visualType] = visualDefault.get(visualType, state === 'inRange' ? 'active' : 'inactive', isCategory);
  116. });
  117. }, this);
  118. function has(obj, state, visualType) {
  119. return obj && obj[state] && obj[state].hasOwnProperty(visualType);
  120. }
  121. _super.prototype.completeVisualOption.apply(this, arguments);
  122. };
  123. PiecewiseModel.prototype._resetSelected = function (newOption, isInit) {
  124. var thisOption = this.option;
  125. var pieceList = this._pieceList;
  126. // Selected do not merge but all override.
  127. var selected = (isInit ? thisOption : newOption).selected || {};
  128. thisOption.selected = selected;
  129. // Consider 'not specified' means true.
  130. zrUtil.each(pieceList, function (piece, index) {
  131. var key = this.getSelectedMapKey(piece);
  132. if (!selected.hasOwnProperty(key)) {
  133. selected[key] = true;
  134. }
  135. }, this);
  136. if (thisOption.selectedMode === 'single') {
  137. // Ensure there is only one selected.
  138. var hasSel_1 = false;
  139. zrUtil.each(pieceList, function (piece, index) {
  140. var key = this.getSelectedMapKey(piece);
  141. if (selected[key]) {
  142. hasSel_1 ? selected[key] = false : hasSel_1 = true;
  143. }
  144. }, this);
  145. }
  146. // thisOption.selectedMode === 'multiple', default: all selected.
  147. };
  148. /**
  149. * @public
  150. */
  151. PiecewiseModel.prototype.getItemSymbol = function () {
  152. return this.get('itemSymbol');
  153. };
  154. /**
  155. * @public
  156. */
  157. PiecewiseModel.prototype.getSelectedMapKey = function (piece) {
  158. return this._mode === 'categories' ? piece.value + '' : piece.index + '';
  159. };
  160. /**
  161. * @public
  162. */
  163. PiecewiseModel.prototype.getPieceList = function () {
  164. return this._pieceList;
  165. };
  166. /**
  167. * @return {string}
  168. */
  169. PiecewiseModel.prototype._determineMode = function () {
  170. var option = this.option;
  171. return option.pieces && option.pieces.length > 0 ? 'pieces' : this.option.categories ? 'categories' : 'splitNumber';
  172. };
  173. /**
  174. * @override
  175. */
  176. PiecewiseModel.prototype.setSelected = function (selected) {
  177. this.option.selected = zrUtil.clone(selected);
  178. };
  179. /**
  180. * @override
  181. */
  182. PiecewiseModel.prototype.getValueState = function (value) {
  183. var index = VisualMapping.findPieceIndex(value, this._pieceList);
  184. return index != null ? this.option.selected[this.getSelectedMapKey(this._pieceList[index])] ? 'inRange' : 'outOfRange' : 'outOfRange';
  185. };
  186. /**
  187. * @public
  188. * @param pieceIndex piece index in visualMapModel.getPieceList()
  189. */
  190. PiecewiseModel.prototype.findTargetDataIndices = function (pieceIndex) {
  191. var result = [];
  192. var pieceList = this._pieceList;
  193. this.eachTargetSeries(function (seriesModel) {
  194. var dataIndices = [];
  195. var data = seriesModel.getData();
  196. data.each(this.getDataDimensionIndex(data), function (value, dataIndex) {
  197. // Should always base on model pieceList, because it is order sensitive.
  198. var pIdx = VisualMapping.findPieceIndex(value, pieceList);
  199. pIdx === pieceIndex && dataIndices.push(dataIndex);
  200. }, this);
  201. result.push({
  202. seriesId: seriesModel.id,
  203. dataIndex: dataIndices
  204. });
  205. }, this);
  206. return result;
  207. };
  208. /**
  209. * @private
  210. * @param piece piece.value or piece.interval is required.
  211. * @return Can be Infinity or -Infinity
  212. */
  213. PiecewiseModel.prototype.getRepresentValue = function (piece) {
  214. var representValue;
  215. if (this.isCategory()) {
  216. representValue = piece.value;
  217. } else {
  218. if (piece.value != null) {
  219. representValue = piece.value;
  220. } else {
  221. var pieceInterval = piece.interval || [];
  222. representValue = pieceInterval[0] === -Infinity && pieceInterval[1] === Infinity ? 0 : (pieceInterval[0] + pieceInterval[1]) / 2;
  223. }
  224. }
  225. return representValue;
  226. };
  227. PiecewiseModel.prototype.getVisualMeta = function (getColorVisual) {
  228. // Do not support category. (category axis is ordinal, numerical)
  229. if (this.isCategory()) {
  230. return;
  231. }
  232. var stops = [];
  233. var outerColors = ['', ''];
  234. var visualMapModel = this;
  235. function setStop(interval, valueState) {
  236. var representValue = visualMapModel.getRepresentValue({
  237. interval: interval
  238. }); // Not category
  239. if (!valueState) {
  240. valueState = visualMapModel.getValueState(representValue);
  241. }
  242. var color = getColorVisual(representValue, valueState);
  243. if (interval[0] === -Infinity) {
  244. outerColors[0] = color;
  245. } else if (interval[1] === Infinity) {
  246. outerColors[1] = color;
  247. } else {
  248. stops.push({
  249. value: interval[0],
  250. color: color
  251. }, {
  252. value: interval[1],
  253. color: color
  254. });
  255. }
  256. }
  257. // Suplement
  258. var pieceList = this._pieceList.slice();
  259. if (!pieceList.length) {
  260. pieceList.push({
  261. interval: [-Infinity, Infinity]
  262. });
  263. } else {
  264. var edge = pieceList[0].interval[0];
  265. edge !== -Infinity && pieceList.unshift({
  266. interval: [-Infinity, edge]
  267. });
  268. edge = pieceList[pieceList.length - 1].interval[1];
  269. edge !== Infinity && pieceList.push({
  270. interval: [edge, Infinity]
  271. });
  272. }
  273. var curr = -Infinity;
  274. zrUtil.each(pieceList, function (piece) {
  275. var interval = piece.interval;
  276. if (interval) {
  277. // Fulfill gap.
  278. interval[0] > curr && setStop([curr, interval[0]], 'outOfRange');
  279. setStop(interval.slice());
  280. curr = interval[1];
  281. }
  282. }, this);
  283. return {
  284. stops: stops,
  285. outerColors: outerColors
  286. };
  287. };
  288. PiecewiseModel.type = 'visualMap.piecewise';
  289. PiecewiseModel.defaultOption = inheritDefaultOption(VisualMapModel.defaultOption, {
  290. selected: null,
  291. minOpen: false,
  292. maxOpen: false,
  293. align: 'auto',
  294. itemWidth: 20,
  295. itemHeight: 14,
  296. itemSymbol: 'roundRect',
  297. pieces: null,
  298. categories: null,
  299. splitNumber: 5,
  300. selectedMode: 'multiple',
  301. itemGap: 10,
  302. hoverLink: true // Enable hover highlight.
  303. });
  304. return PiecewiseModel;
  305. }(VisualMapModel);
  306. ;
  307. /**
  308. * Key is this._mode
  309. * @type {Object}
  310. * @this {module:echarts/component/viusalMap/PiecewiseMode}
  311. */
  312. var resetMethods = {
  313. splitNumber: function (outPieceList) {
  314. var thisOption = this.option;
  315. var precision = Math.min(thisOption.precision, 20);
  316. var dataExtent = this.getExtent();
  317. var splitNumber = thisOption.splitNumber;
  318. splitNumber = Math.max(parseInt(splitNumber, 10), 1);
  319. thisOption.splitNumber = splitNumber;
  320. var splitStep = (dataExtent[1] - dataExtent[0]) / splitNumber;
  321. // Precision auto-adaption
  322. while (+splitStep.toFixed(precision) !== splitStep && precision < 5) {
  323. precision++;
  324. }
  325. thisOption.precision = precision;
  326. splitStep = +splitStep.toFixed(precision);
  327. if (thisOption.minOpen) {
  328. outPieceList.push({
  329. interval: [-Infinity, dataExtent[0]],
  330. close: [0, 0]
  331. });
  332. }
  333. for (var index = 0, curr = dataExtent[0]; index < splitNumber; curr += splitStep, index++) {
  334. var max = index === splitNumber - 1 ? dataExtent[1] : curr + splitStep;
  335. outPieceList.push({
  336. interval: [curr, max],
  337. close: [1, 1]
  338. });
  339. }
  340. if (thisOption.maxOpen) {
  341. outPieceList.push({
  342. interval: [dataExtent[1], Infinity],
  343. close: [0, 0]
  344. });
  345. }
  346. reformIntervals(outPieceList);
  347. zrUtil.each(outPieceList, function (piece, index) {
  348. piece.index = index;
  349. piece.text = this.formatValueText(piece.interval);
  350. }, this);
  351. },
  352. categories: function (outPieceList) {
  353. var thisOption = this.option;
  354. zrUtil.each(thisOption.categories, function (cate) {
  355. // FIXME category模式也使用pieceList,但在visualMapping中不是使用pieceList。
  356. // 是否改一致。
  357. outPieceList.push({
  358. text: this.formatValueText(cate, true),
  359. value: cate
  360. });
  361. }, this);
  362. // See "Order Rule".
  363. normalizeReverse(thisOption, outPieceList);
  364. },
  365. pieces: function (outPieceList) {
  366. var thisOption = this.option;
  367. zrUtil.each(thisOption.pieces, function (pieceListItem, index) {
  368. if (!zrUtil.isObject(pieceListItem)) {
  369. pieceListItem = {
  370. value: pieceListItem
  371. };
  372. }
  373. var item = {
  374. text: '',
  375. index: index
  376. };
  377. if (pieceListItem.label != null) {
  378. item.text = pieceListItem.label;
  379. }
  380. if (pieceListItem.hasOwnProperty('value')) {
  381. var value = item.value = pieceListItem.value;
  382. item.interval = [value, value];
  383. item.close = [1, 1];
  384. } else {
  385. // `min` `max` is legacy option.
  386. // `lt` `gt` `lte` `gte` is recommended.
  387. var interval = item.interval = [];
  388. var close_1 = item.close = [0, 0];
  389. var closeList = [1, 0, 1];
  390. var infinityList = [-Infinity, Infinity];
  391. var useMinMax = [];
  392. for (var lg = 0; lg < 2; lg++) {
  393. var names = [['gte', 'gt', 'min'], ['lte', 'lt', 'max']][lg];
  394. for (var i = 0; i < 3 && interval[lg] == null; i++) {
  395. interval[lg] = pieceListItem[names[i]];
  396. close_1[lg] = closeList[i];
  397. useMinMax[lg] = i === 2;
  398. }
  399. interval[lg] == null && (interval[lg] = infinityList[lg]);
  400. }
  401. useMinMax[0] && interval[1] === Infinity && (close_1[0] = 0);
  402. useMinMax[1] && interval[0] === -Infinity && (close_1[1] = 0);
  403. if (process.env.NODE_ENV !== 'production') {
  404. if (interval[0] > interval[1]) {
  405. console.warn('Piece ' + index + 'is illegal: ' + interval + ' lower bound should not greater then uppper bound.');
  406. }
  407. }
  408. if (interval[0] === interval[1] && close_1[0] && close_1[1]) {
  409. // Consider: [{min: 5, max: 5, visual: {...}}, {min: 0, max: 5}],
  410. // we use value to lift the priority when min === max
  411. item.value = interval[0];
  412. }
  413. }
  414. item.visual = VisualMapping.retrieveVisuals(pieceListItem);
  415. outPieceList.push(item);
  416. }, this);
  417. // See "Order Rule".
  418. normalizeReverse(thisOption, outPieceList);
  419. // Only pieces
  420. reformIntervals(outPieceList);
  421. zrUtil.each(outPieceList, function (piece) {
  422. var close = piece.close;
  423. var edgeSymbols = [['<', '≤'][close[1]], ['>', '≥'][close[0]]];
  424. piece.text = piece.text || this.formatValueText(piece.value != null ? piece.value : piece.interval, false, edgeSymbols);
  425. }, this);
  426. }
  427. };
  428. function normalizeReverse(thisOption, pieceList) {
  429. var inverse = thisOption.inverse;
  430. if (thisOption.orient === 'vertical' ? !inverse : inverse) {
  431. pieceList.reverse();
  432. }
  433. }
  434. export default PiecewiseModel;