PiecewiseModel.js 15 KB

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