SeriesData.js 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217
  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. /* global Int32Array */
  41. import * as zrUtil from 'zrender/lib/core/util';
  42. import Model from '../model/Model';
  43. import DataDiffer from './DataDiffer';
  44. import { DefaultDataProvider } from './helper/dataProvider';
  45. import { summarizeDimensions } from './helper/dimensionHelper';
  46. import SeriesDimensionDefine from './SeriesDimensionDefine';
  47. import { SOURCE_FORMAT_TYPED_ARRAY, SOURCE_FORMAT_ORIGINAL } from '../util/types';
  48. import { convertOptionIdName, isDataItemOption } from '../util/model';
  49. import { setCommonECData } from '../util/innerStore';
  50. import { isSourceInstance } from './Source';
  51. import DataStore from './DataStore';
  52. import { isSeriesDataSchema } from './helper/SeriesDataSchema';
  53. var isObject = zrUtil.isObject;
  54. var map = zrUtil.map;
  55. var CtorInt32Array = typeof Int32Array === 'undefined' ? Array : Int32Array; // Use prefix to avoid index to be the same as otherIdList[idx],
  56. // which will cause weird udpate animation.
  57. var ID_PREFIX = 'e\0\0';
  58. var INDEX_NOT_FOUND = -1; // type SeriesDimensionIndex = DimensionIndex;
  59. var TRANSFERABLE_PROPERTIES = ['hasItemOption', '_nameList', '_idList', '_invertedIndicesMap', '_dimSummary', 'userOutput', '_rawData', '_dimValueGetter', '_nameDimIdx', '_idDimIdx', '_nameRepeatCount'];
  60. var CLONE_PROPERTIES = ['_approximateExtent']; // -----------------------------
  61. // Internal method declarations:
  62. // -----------------------------
  63. var prepareInvertedIndex;
  64. var getId;
  65. var getIdNameFromStore;
  66. var normalizeDimensions;
  67. var transferProperties;
  68. var cloneListForMapAndSample;
  69. var makeIdFromName;
  70. var SeriesData =
  71. /** @class */
  72. function () {
  73. /**
  74. * @param dimensionsInput.dimensions
  75. * For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...].
  76. * Dimensions should be concrete names like x, y, z, lng, lat, angle, radius
  77. */
  78. function SeriesData(dimensionsInput, hostModel) {
  79. this.type = 'list';
  80. this._dimOmitted = false;
  81. this._nameList = [];
  82. this._idList = []; // Models of data option is stored sparse for optimizing memory cost
  83. // Never used yet (not used yet).
  84. // private _optionModels: Model[] = [];
  85. // Global visual properties after visual coding
  86. this._visual = {}; // Globel layout properties.
  87. this._layout = {}; // Item visual properties after visual coding
  88. this._itemVisuals = []; // Item layout properties after layout
  89. this._itemLayouts = []; // Graphic elemnents
  90. this._graphicEls = []; // key: dim, value: extent
  91. this._approximateExtent = {};
  92. this._calculationInfo = {}; // Having detected that there is data item is non primitive type
  93. // (in type `OptionDataItemObject`).
  94. // Like `data: [ { value: xx, itemStyle: {...} }, ...]`
  95. // At present it only happen in `SOURCE_FORMAT_ORIGINAL`.
  96. this.hasItemOption = false; // Methods that create a new list based on this list should be listed here.
  97. // Notice that those method should `RETURN` the new list.
  98. this.TRANSFERABLE_METHODS = ['cloneShallow', 'downSample', 'lttbDownSample', 'map']; // Methods that change indices of this list should be listed here.
  99. this.CHANGABLE_METHODS = ['filterSelf', 'selectRange'];
  100. this.DOWNSAMPLE_METHODS = ['downSample', 'lttbDownSample'];
  101. var dimensions;
  102. var assignStoreDimIdx = false;
  103. if (isSeriesDataSchema(dimensionsInput)) {
  104. dimensions = dimensionsInput.dimensions;
  105. this._dimOmitted = dimensionsInput.isDimensionOmitted();
  106. this._schema = dimensionsInput;
  107. } else {
  108. assignStoreDimIdx = true;
  109. dimensions = dimensionsInput;
  110. }
  111. dimensions = dimensions || ['x', 'y'];
  112. var dimensionInfos = {};
  113. var dimensionNames = [];
  114. var invertedIndicesMap = {};
  115. var needsHasOwn = false;
  116. var emptyObj = {};
  117. for (var i = 0; i < dimensions.length; i++) {
  118. // Use the original dimensions[i], where other flag props may exists.
  119. var dimInfoInput = dimensions[i];
  120. var dimensionInfo = zrUtil.isString(dimInfoInput) ? new SeriesDimensionDefine({
  121. name: dimInfoInput
  122. }) : !(dimInfoInput instanceof SeriesDimensionDefine) ? new SeriesDimensionDefine(dimInfoInput) : dimInfoInput;
  123. var dimensionName = dimensionInfo.name;
  124. dimensionInfo.type = dimensionInfo.type || 'float';
  125. if (!dimensionInfo.coordDim) {
  126. dimensionInfo.coordDim = dimensionName;
  127. dimensionInfo.coordDimIndex = 0;
  128. }
  129. var otherDims = dimensionInfo.otherDims = dimensionInfo.otherDims || {};
  130. dimensionNames.push(dimensionName);
  131. dimensionInfos[dimensionName] = dimensionInfo;
  132. if (emptyObj[dimensionName] != null) {
  133. needsHasOwn = true;
  134. }
  135. if (dimensionInfo.createInvertedIndices) {
  136. invertedIndicesMap[dimensionName] = [];
  137. }
  138. if (otherDims.itemName === 0) {
  139. this._nameDimIdx = i;
  140. }
  141. if (otherDims.itemId === 0) {
  142. this._idDimIdx = i;
  143. }
  144. if (process.env.NODE_ENV !== 'production') {
  145. zrUtil.assert(assignStoreDimIdx || dimensionInfo.storeDimIndex >= 0);
  146. }
  147. if (assignStoreDimIdx) {
  148. dimensionInfo.storeDimIndex = i;
  149. }
  150. }
  151. this.dimensions = dimensionNames;
  152. this._dimInfos = dimensionInfos;
  153. this._initGetDimensionInfo(needsHasOwn);
  154. this.hostModel = hostModel;
  155. this._invertedIndicesMap = invertedIndicesMap;
  156. if (this._dimOmitted) {
  157. var dimIdxToName_1 = this._dimIdxToName = zrUtil.createHashMap();
  158. zrUtil.each(dimensionNames, function (dimName) {
  159. dimIdxToName_1.set(dimensionInfos[dimName].storeDimIndex, dimName);
  160. });
  161. }
  162. }
  163. /**
  164. *
  165. * Get concrete dimension name by dimension name or dimension index.
  166. * If input a dimension name, do not validate whether the dimension name exits.
  167. *
  168. * @caution
  169. * @param dim Must make sure the dimension is `SeriesDimensionLoose`.
  170. * Because only those dimensions will have auto-generated dimension names if not
  171. * have a user-specified name, and other dimensions will get a return of null/undefined.
  172. *
  173. * @notice Becuause of this reason, should better use `getDimensionIndex` instead, for examples:
  174. * ```js
  175. * const val = data.getStore().get(data.getDimensionIndex(dim), dataIdx);
  176. * ```
  177. *
  178. * @return Concrete dim name.
  179. */
  180. SeriesData.prototype.getDimension = function (dim) {
  181. var dimIdx = this._recognizeDimIndex(dim);
  182. if (dimIdx == null) {
  183. return dim;
  184. }
  185. dimIdx = dim;
  186. if (!this._dimOmitted) {
  187. return this.dimensions[dimIdx];
  188. } // Retrieve from series dimension definition becuase it probably contains
  189. // generated dimension name (like 'x', 'y').
  190. var dimName = this._dimIdxToName.get(dimIdx);
  191. if (dimName != null) {
  192. return dimName;
  193. }
  194. var sourceDimDef = this._schema.getSourceDimension(dimIdx);
  195. if (sourceDimDef) {
  196. return sourceDimDef.name;
  197. }
  198. };
  199. /**
  200. * Get dimension index in data store. Return -1 if not found.
  201. * Can be used to index value from getRawValue.
  202. */
  203. SeriesData.prototype.getDimensionIndex = function (dim) {
  204. var dimIdx = this._recognizeDimIndex(dim);
  205. if (dimIdx != null) {
  206. return dimIdx;
  207. }
  208. if (dim == null) {
  209. return -1;
  210. }
  211. var dimInfo = this._getDimInfo(dim);
  212. return dimInfo ? dimInfo.storeDimIndex : this._dimOmitted ? this._schema.getSourceDimensionIndex(dim) : -1;
  213. };
  214. /**
  215. * The meanings of the input parameter `dim`:
  216. *
  217. * + If dim is a number (e.g., `1`), it means the index of the dimension.
  218. * For example, `getDimension(0)` will return 'x' or 'lng' or 'radius'.
  219. * + If dim is a number-like string (e.g., `"1"`):
  220. * + If there is the same concrete dim name defined in `series.dimensions` or `dataset.dimensions`,
  221. * it means that concrete name.
  222. * + If not, it will be converted to a number, which means the index of the dimension.
  223. * (why? because of the backward compatbility. We have been tolerating number-like string in
  224. * dimension setting, although now it seems that it is not a good idea.)
  225. * For example, `visualMap[i].dimension: "1"` is the same meaning as `visualMap[i].dimension: 1`,
  226. * if no dimension name is defined as `"1"`.
  227. * + If dim is a not-number-like string, it means the concrete dim name.
  228. * For example, it can be be default name `"x"`, `"y"`, `"z"`, `"lng"`, `"lat"`, `"angle"`, `"radius"`,
  229. * or customized in `dimensions` property of option like `"age"`.
  230. *
  231. * @return recogonized `DimensionIndex`. Otherwise return null/undefined (means that dim is `DimensionName`).
  232. */
  233. SeriesData.prototype._recognizeDimIndex = function (dim) {
  234. if (typeof dim === 'number' // If being a number-like string but not being defined as a dimension name.
  235. || dim != null && !isNaN(dim) && !this._getDimInfo(dim) && (!this._dimOmitted || this._schema.getSourceDimensionIndex(dim) < 0)) {
  236. return +dim;
  237. }
  238. };
  239. SeriesData.prototype._getStoreDimIndex = function (dim) {
  240. var dimIdx = this.getDimensionIndex(dim);
  241. if (process.env.NODE_ENV !== 'production') {
  242. if (dimIdx == null) {
  243. throw new Error('Unkown dimension ' + dim);
  244. }
  245. }
  246. return dimIdx;
  247. };
  248. /**
  249. * Get type and calculation info of particular dimension
  250. * @param dim
  251. * Dimension can be concrete names like x, y, z, lng, lat, angle, radius
  252. * Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius'
  253. */
  254. SeriesData.prototype.getDimensionInfo = function (dim) {
  255. // Do not clone, because there may be categories in dimInfo.
  256. return this._getDimInfo(this.getDimension(dim));
  257. };
  258. SeriesData.prototype._initGetDimensionInfo = function (needsHasOwn) {
  259. var dimensionInfos = this._dimInfos;
  260. this._getDimInfo = needsHasOwn ? function (dimName) {
  261. return dimensionInfos.hasOwnProperty(dimName) ? dimensionInfos[dimName] : undefined;
  262. } : function (dimName) {
  263. return dimensionInfos[dimName];
  264. };
  265. };
  266. /**
  267. * concrete dimension name list on coord.
  268. */
  269. SeriesData.prototype.getDimensionsOnCoord = function () {
  270. return this._dimSummary.dataDimsOnCoord.slice();
  271. };
  272. SeriesData.prototype.mapDimension = function (coordDim, idx) {
  273. var dimensionsSummary = this._dimSummary;
  274. if (idx == null) {
  275. return dimensionsSummary.encodeFirstDimNotExtra[coordDim];
  276. }
  277. var dims = dimensionsSummary.encode[coordDim];
  278. return dims ? dims[idx] : null;
  279. };
  280. SeriesData.prototype.mapDimensionsAll = function (coordDim) {
  281. var dimensionsSummary = this._dimSummary;
  282. var dims = dimensionsSummary.encode[coordDim];
  283. return (dims || []).slice();
  284. };
  285. SeriesData.prototype.getStore = function () {
  286. return this._store;
  287. };
  288. /**
  289. * Initialize from data
  290. * @param data source or data or data store.
  291. * @param nameList The name of a datum is used on data diff and
  292. * default label/tooltip.
  293. * A name can be specified in encode.itemName,
  294. * or dataItem.name (only for series option data),
  295. * or provided in nameList from outside.
  296. */
  297. SeriesData.prototype.initData = function (data, nameList, dimValueGetter) {
  298. var _this = this;
  299. var store;
  300. if (data instanceof DataStore) {
  301. store = data;
  302. }
  303. if (!store) {
  304. var dimensions = this.dimensions;
  305. var provider = isSourceInstance(data) || zrUtil.isArrayLike(data) ? new DefaultDataProvider(data, dimensions.length) : data;
  306. store = new DataStore();
  307. var dimensionInfos = map(dimensions, function (dimName) {
  308. return {
  309. type: _this._dimInfos[dimName].type,
  310. property: dimName
  311. };
  312. });
  313. store.initData(provider, dimensionInfos, dimValueGetter);
  314. }
  315. this._store = store; // Reset
  316. this._nameList = (nameList || []).slice();
  317. this._idList = [];
  318. this._nameRepeatCount = {};
  319. this._doInit(0, store.count()); // Cache summary info for fast visit. See "dimensionHelper".
  320. // Needs to be initialized after store is prepared.
  321. this._dimSummary = summarizeDimensions(this, this._schema);
  322. this.userOutput = this._dimSummary.userOutput;
  323. };
  324. /**
  325. * Caution: Can be only called on raw data (before `this._indices` created).
  326. */
  327. SeriesData.prototype.appendData = function (data) {
  328. var range = this._store.appendData(data);
  329. this._doInit(range[0], range[1]);
  330. };
  331. /**
  332. * Caution: Can be only called on raw data (before `this._indices` created).
  333. * This method does not modify `rawData` (`dataProvider`), but only
  334. * add values to store.
  335. *
  336. * The final count will be increased by `Math.max(values.length, names.length)`.
  337. *
  338. * @param values That is the SourceType: 'arrayRows', like
  339. * [
  340. * [12, 33, 44],
  341. * [NaN, 43, 1],
  342. * ['-', 'asdf', 0]
  343. * ]
  344. * Each item is exaclty cooresponding to a dimension.
  345. */
  346. SeriesData.prototype.appendValues = function (values, names) {
  347. var _a = this._store.appendValues(values, names.length),
  348. start = _a.start,
  349. end = _a.end;
  350. var shouldMakeIdFromName = this._shouldMakeIdFromName();
  351. this._updateOrdinalMeta();
  352. if (names) {
  353. for (var idx = start; idx < end; idx++) {
  354. var sourceIdx = idx - start;
  355. this._nameList[idx] = names[sourceIdx];
  356. if (shouldMakeIdFromName) {
  357. makeIdFromName(this, idx);
  358. }
  359. }
  360. }
  361. };
  362. SeriesData.prototype._updateOrdinalMeta = function () {
  363. var store = this._store;
  364. var dimensions = this.dimensions;
  365. for (var i = 0; i < dimensions.length; i++) {
  366. var dimInfo = this._dimInfos[dimensions[i]];
  367. if (dimInfo.ordinalMeta) {
  368. store.collectOrdinalMeta(dimInfo.storeDimIndex, dimInfo.ordinalMeta);
  369. }
  370. }
  371. };
  372. SeriesData.prototype._shouldMakeIdFromName = function () {
  373. var provider = this._store.getProvider();
  374. return this._idDimIdx == null && provider.getSource().sourceFormat !== SOURCE_FORMAT_TYPED_ARRAY && !provider.fillStorage;
  375. };
  376. SeriesData.prototype._doInit = function (start, end) {
  377. if (start >= end) {
  378. return;
  379. }
  380. var store = this._store;
  381. var provider = store.getProvider();
  382. this._updateOrdinalMeta();
  383. var nameList = this._nameList;
  384. var idList = this._idList;
  385. var sourceFormat = provider.getSource().sourceFormat;
  386. var isFormatOriginal = sourceFormat === SOURCE_FORMAT_ORIGINAL; // Each data item is value
  387. // [1, 2]
  388. // 2
  389. // Bar chart, line chart which uses category axis
  390. // only gives the 'y' value. 'x' value is the indices of category
  391. // Use a tempValue to normalize the value to be a (x, y) value
  392. // If dataItem is {name: ...} or {id: ...}, it has highest priority.
  393. // This kind of ids and names are always stored `_nameList` and `_idList`.
  394. if (isFormatOriginal && !provider.pure) {
  395. var sharedDataItem = [];
  396. for (var idx = start; idx < end; idx++) {
  397. // NOTICE: Try not to write things into dataItem
  398. var dataItem = provider.getItem(idx, sharedDataItem);
  399. if (!this.hasItemOption && isDataItemOption(dataItem)) {
  400. this.hasItemOption = true;
  401. }
  402. if (dataItem) {
  403. var itemName = dataItem.name;
  404. if (nameList[idx] == null && itemName != null) {
  405. nameList[idx] = convertOptionIdName(itemName, null);
  406. }
  407. var itemId = dataItem.id;
  408. if (idList[idx] == null && itemId != null) {
  409. idList[idx] = convertOptionIdName(itemId, null);
  410. }
  411. }
  412. }
  413. }
  414. if (this._shouldMakeIdFromName()) {
  415. for (var idx = start; idx < end; idx++) {
  416. makeIdFromName(this, idx);
  417. }
  418. }
  419. prepareInvertedIndex(this);
  420. };
  421. /**
  422. * PENDING: In fact currently this function is only used to short-circuit
  423. * the calling of `scale.unionExtentFromData` when data have been filtered by modules
  424. * like "dataZoom". `scale.unionExtentFromData` is used to calculate data extent for series on
  425. * an axis, but if a "axis related data filter module" is used, the extent of the axis have
  426. * been fixed and no need to calling `scale.unionExtentFromData` actually.
  427. * But if we add "custom data filter" in future, which is not "axis related", this method may
  428. * be still needed.
  429. *
  430. * Optimize for the scenario that data is filtered by a given extent.
  431. * Consider that if data amount is more than hundreds of thousand,
  432. * extent calculation will cost more than 10ms and the cache will
  433. * be erased because of the filtering.
  434. */
  435. SeriesData.prototype.getApproximateExtent = function (dim) {
  436. return this._approximateExtent[dim] || this._store.getDataExtent(this._getStoreDimIndex(dim));
  437. };
  438. /**
  439. * Calculate extent on a filtered data might be time consuming.
  440. * Approximate extent is only used for: calculte extent of filtered data outside.
  441. */
  442. SeriesData.prototype.setApproximateExtent = function (extent, dim) {
  443. dim = this.getDimension(dim);
  444. this._approximateExtent[dim] = extent.slice();
  445. };
  446. SeriesData.prototype.getCalculationInfo = function (key) {
  447. return this._calculationInfo[key];
  448. };
  449. SeriesData.prototype.setCalculationInfo = function (key, value) {
  450. isObject(key) ? zrUtil.extend(this._calculationInfo, key) : this._calculationInfo[key] = value;
  451. };
  452. /**
  453. * @return Never be null/undefined. `number` will be converted to string. Becuase:
  454. * In most cases, name is used in display, where returning a string is more convenient.
  455. * In other cases, name is used in query (see `indexOfName`), where we can keep the
  456. * rule that name `2` equals to name `'2'`.
  457. */
  458. SeriesData.prototype.getName = function (idx) {
  459. var rawIndex = this.getRawIndex(idx);
  460. var name = this._nameList[rawIndex];
  461. if (name == null && this._nameDimIdx != null) {
  462. name = getIdNameFromStore(this, this._nameDimIdx, rawIndex);
  463. }
  464. if (name == null) {
  465. name = '';
  466. }
  467. return name;
  468. };
  469. SeriesData.prototype._getCategory = function (dimIdx, idx) {
  470. var ordinal = this._store.get(dimIdx, idx);
  471. var ordinalMeta = this._store.getOrdinalMeta(dimIdx);
  472. if (ordinalMeta) {
  473. return ordinalMeta.categories[ordinal];
  474. }
  475. return ordinal;
  476. };
  477. /**
  478. * @return Never null/undefined. `number` will be converted to string. Becuase:
  479. * In all cases having encountered at present, id is used in making diff comparison, which
  480. * are usually based on hash map. We can keep the rule that the internal id are always string
  481. * (treat `2` is the same as `'2'`) to make the related logic simple.
  482. */
  483. SeriesData.prototype.getId = function (idx) {
  484. return getId(this, this.getRawIndex(idx));
  485. };
  486. SeriesData.prototype.count = function () {
  487. return this._store.count();
  488. };
  489. /**
  490. * Get value. Return NaN if idx is out of range.
  491. *
  492. * @notice Should better to use `data.getStore().get(dimIndex, dataIdx)` instead.
  493. */
  494. SeriesData.prototype.get = function (dim, idx) {
  495. var store = this._store;
  496. var dimInfo = this._dimInfos[dim];
  497. if (dimInfo) {
  498. return store.get(dimInfo.storeDimIndex, idx);
  499. }
  500. };
  501. /**
  502. * @notice Should better to use `data.getStore().getByRawIndex(dimIndex, dataIdx)` instead.
  503. */
  504. SeriesData.prototype.getByRawIndex = function (dim, rawIdx) {
  505. var store = this._store;
  506. var dimInfo = this._dimInfos[dim];
  507. if (dimInfo) {
  508. return store.getByRawIndex(dimInfo.storeDimIndex, rawIdx);
  509. }
  510. };
  511. SeriesData.prototype.getIndices = function () {
  512. return this._store.getIndices();
  513. };
  514. SeriesData.prototype.getDataExtent = function (dim) {
  515. return this._store.getDataExtent(this._getStoreDimIndex(dim));
  516. };
  517. SeriesData.prototype.getSum = function (dim) {
  518. return this._store.getSum(this._getStoreDimIndex(dim));
  519. };
  520. SeriesData.prototype.getMedian = function (dim) {
  521. return this._store.getMedian(this._getStoreDimIndex(dim));
  522. };
  523. SeriesData.prototype.getValues = function (dimensions, idx) {
  524. var _this = this;
  525. var store = this._store;
  526. return zrUtil.isArray(dimensions) ? store.getValues(map(dimensions, function (dim) {
  527. return _this._getStoreDimIndex(dim);
  528. }), idx) : store.getValues(dimensions);
  529. };
  530. /**
  531. * If value is NaN. Inlcuding '-'
  532. * Only check the coord dimensions.
  533. */
  534. SeriesData.prototype.hasValue = function (idx) {
  535. var dataDimIndicesOnCoord = this._dimSummary.dataDimIndicesOnCoord;
  536. for (var i = 0, len = dataDimIndicesOnCoord.length; i < len; i++) {
  537. // Ordinal type originally can be string or number.
  538. // But when an ordinal type is used on coord, it can
  539. // not be string but only number. So we can also use isNaN.
  540. if (isNaN(this._store.get(dataDimIndicesOnCoord[i], idx))) {
  541. return false;
  542. }
  543. }
  544. return true;
  545. };
  546. /**
  547. * Retreive the index with given name
  548. */
  549. SeriesData.prototype.indexOfName = function (name) {
  550. for (var i = 0, len = this._store.count(); i < len; i++) {
  551. if (this.getName(i) === name) {
  552. return i;
  553. }
  554. }
  555. return -1;
  556. };
  557. SeriesData.prototype.getRawIndex = function (idx) {
  558. return this._store.getRawIndex(idx);
  559. };
  560. SeriesData.prototype.indexOfRawIndex = function (rawIndex) {
  561. return this._store.indexOfRawIndex(rawIndex);
  562. };
  563. /**
  564. * Only support the dimension which inverted index created.
  565. * Do not support other cases until required.
  566. * @param dim concrete dim
  567. * @param value ordinal index
  568. * @return rawIndex
  569. */
  570. SeriesData.prototype.rawIndexOf = function (dim, value) {
  571. var invertedIndices = dim && this._invertedIndicesMap[dim];
  572. if (process.env.NODE_ENV !== 'production') {
  573. if (!invertedIndices) {
  574. throw new Error('Do not supported yet');
  575. }
  576. }
  577. var rawIndex = invertedIndices[value];
  578. if (rawIndex == null || isNaN(rawIndex)) {
  579. return INDEX_NOT_FOUND;
  580. }
  581. return rawIndex;
  582. };
  583. /**
  584. * Retreive the index of nearest value
  585. * @param dim
  586. * @param value
  587. * @param [maxDistance=Infinity]
  588. * @return If and only if multiple indices has
  589. * the same value, they are put to the result.
  590. */
  591. SeriesData.prototype.indicesOfNearest = function (dim, value, maxDistance) {
  592. return this._store.indicesOfNearest(this._getStoreDimIndex(dim), value, maxDistance);
  593. };
  594. SeriesData.prototype.each = function (dims, cb, ctx) {
  595. 'use strict';
  596. if (typeof dims === 'function') {
  597. ctx = cb;
  598. cb = dims;
  599. dims = [];
  600. } // ctxCompat just for compat echarts3
  601. var fCtx = ctx || this;
  602. var dimIndices = map(normalizeDimensions(dims), this._getStoreDimIndex, this);
  603. this._store.each(dimIndices, fCtx ? zrUtil.bind(cb, fCtx) : cb);
  604. };
  605. SeriesData.prototype.filterSelf = function (dims, cb, ctx) {
  606. 'use strict';
  607. if (typeof dims === 'function') {
  608. ctx = cb;
  609. cb = dims;
  610. dims = [];
  611. } // ctxCompat just for compat echarts3
  612. var fCtx = ctx || this;
  613. var dimIndices = map(normalizeDimensions(dims), this._getStoreDimIndex, this);
  614. this._store = this._store.filter(dimIndices, fCtx ? zrUtil.bind(cb, fCtx) : cb);
  615. return this;
  616. };
  617. /**
  618. * Select data in range. (For optimization of filter)
  619. * (Manually inline code, support 5 million data filtering in data zoom.)
  620. */
  621. SeriesData.prototype.selectRange = function (range) {
  622. 'use strict';
  623. var _this = this;
  624. var innerRange = {};
  625. var dims = zrUtil.keys(range);
  626. var dimIndices = [];
  627. zrUtil.each(dims, function (dim) {
  628. var dimIdx = _this._getStoreDimIndex(dim);
  629. innerRange[dimIdx] = range[dim];
  630. dimIndices.push(dimIdx);
  631. });
  632. this._store = this._store.selectRange(innerRange);
  633. return this;
  634. };
  635. /* eslint-enable max-len */
  636. SeriesData.prototype.mapArray = function (dims, cb, ctx) {
  637. 'use strict';
  638. if (typeof dims === 'function') {
  639. ctx = cb;
  640. cb = dims;
  641. dims = [];
  642. } // ctxCompat just for compat echarts3
  643. ctx = ctx || this;
  644. var result = [];
  645. this.each(dims, function () {
  646. result.push(cb && cb.apply(this, arguments));
  647. }, ctx);
  648. return result;
  649. };
  650. SeriesData.prototype.map = function (dims, cb, ctx, ctxCompat) {
  651. 'use strict'; // ctxCompat just for compat echarts3
  652. var fCtx = ctx || ctxCompat || this;
  653. var dimIndices = map(normalizeDimensions(dims), this._getStoreDimIndex, this);
  654. var list = cloneListForMapAndSample(this);
  655. list._store = this._store.map(dimIndices, fCtx ? zrUtil.bind(cb, fCtx) : cb);
  656. return list;
  657. };
  658. SeriesData.prototype.modify = function (dims, cb, ctx, ctxCompat) {
  659. var _this = this; // ctxCompat just for compat echarts3
  660. var fCtx = ctx || ctxCompat || this;
  661. if (process.env.NODE_ENV !== 'production') {
  662. zrUtil.each(normalizeDimensions(dims), function (dim) {
  663. var dimInfo = _this.getDimensionInfo(dim);
  664. if (!dimInfo.isCalculationCoord) {
  665. console.error('Danger: only stack dimension can be modified');
  666. }
  667. });
  668. }
  669. var dimIndices = map(normalizeDimensions(dims), this._getStoreDimIndex, this); // If do shallow clone here, if there are too many stacked series,
  670. // it still cost lots of memory, becuase `_store.dimensions` are not shared.
  671. // We should consider there probably be shallow clone happen in each sereis
  672. // in consequent filter/map.
  673. this._store.modify(dimIndices, fCtx ? zrUtil.bind(cb, fCtx) : cb);
  674. };
  675. /**
  676. * Large data down sampling on given dimension
  677. * @param sampleIndex Sample index for name and id
  678. */
  679. SeriesData.prototype.downSample = function (dimension, rate, sampleValue, sampleIndex) {
  680. var list = cloneListForMapAndSample(this);
  681. list._store = this._store.downSample(this._getStoreDimIndex(dimension), rate, sampleValue, sampleIndex);
  682. return list;
  683. };
  684. /**
  685. * Large data down sampling using largest-triangle-three-buckets
  686. * @param {string} valueDimension
  687. * @param {number} targetCount
  688. */
  689. SeriesData.prototype.lttbDownSample = function (valueDimension, rate) {
  690. var list = cloneListForMapAndSample(this);
  691. list._store = this._store.lttbDownSample(this._getStoreDimIndex(valueDimension), rate);
  692. return list;
  693. };
  694. SeriesData.prototype.getRawDataItem = function (idx) {
  695. return this._store.getRawDataItem(idx);
  696. };
  697. /**
  698. * Get model of one data item.
  699. */
  700. // TODO: Type of data item
  701. SeriesData.prototype.getItemModel = function (idx) {
  702. var hostModel = this.hostModel;
  703. var dataItem = this.getRawDataItem(idx);
  704. return new Model(dataItem, hostModel, hostModel && hostModel.ecModel);
  705. };
  706. /**
  707. * Create a data differ
  708. */
  709. SeriesData.prototype.diff = function (otherList) {
  710. var thisList = this;
  711. return new DataDiffer(otherList ? otherList.getStore().getIndices() : [], this.getStore().getIndices(), function (idx) {
  712. return getId(otherList, idx);
  713. }, function (idx) {
  714. return getId(thisList, idx);
  715. });
  716. };
  717. /**
  718. * Get visual property.
  719. */
  720. SeriesData.prototype.getVisual = function (key) {
  721. var visual = this._visual;
  722. return visual && visual[key];
  723. };
  724. SeriesData.prototype.setVisual = function (kvObj, val) {
  725. this._visual = this._visual || {};
  726. if (isObject(kvObj)) {
  727. zrUtil.extend(this._visual, kvObj);
  728. } else {
  729. this._visual[kvObj] = val;
  730. }
  731. };
  732. /**
  733. * Get visual property of single data item
  734. */
  735. // eslint-disable-next-line
  736. SeriesData.prototype.getItemVisual = function (idx, key) {
  737. var itemVisual = this._itemVisuals[idx];
  738. var val = itemVisual && itemVisual[key];
  739. if (val == null) {
  740. // Use global visual property
  741. return this.getVisual(key);
  742. }
  743. return val;
  744. };
  745. /**
  746. * If exists visual property of single data item
  747. */
  748. SeriesData.prototype.hasItemVisual = function () {
  749. return this._itemVisuals.length > 0;
  750. };
  751. /**
  752. * Make sure itemVisual property is unique
  753. */
  754. // TODO: use key to save visual to reduce memory.
  755. SeriesData.prototype.ensureUniqueItemVisual = function (idx, key) {
  756. var itemVisuals = this._itemVisuals;
  757. var itemVisual = itemVisuals[idx];
  758. if (!itemVisual) {
  759. itemVisual = itemVisuals[idx] = {};
  760. }
  761. var val = itemVisual[key];
  762. if (val == null) {
  763. val = this.getVisual(key); // TODO Performance?
  764. if (zrUtil.isArray(val)) {
  765. val = val.slice();
  766. } else if (isObject(val)) {
  767. val = zrUtil.extend({}, val);
  768. }
  769. itemVisual[key] = val;
  770. }
  771. return val;
  772. }; // eslint-disable-next-line
  773. SeriesData.prototype.setItemVisual = function (idx, key, value) {
  774. var itemVisual = this._itemVisuals[idx] || {};
  775. this._itemVisuals[idx] = itemVisual;
  776. if (isObject(key)) {
  777. zrUtil.extend(itemVisual, key);
  778. } else {
  779. itemVisual[key] = value;
  780. }
  781. };
  782. /**
  783. * Clear itemVisuals and list visual.
  784. */
  785. SeriesData.prototype.clearAllVisual = function () {
  786. this._visual = {};
  787. this._itemVisuals = [];
  788. };
  789. SeriesData.prototype.setLayout = function (key, val) {
  790. if (isObject(key)) {
  791. for (var name_1 in key) {
  792. if (key.hasOwnProperty(name_1)) {
  793. this.setLayout(name_1, key[name_1]);
  794. }
  795. }
  796. return;
  797. }
  798. this._layout[key] = val;
  799. };
  800. /**
  801. * Get layout property.
  802. */
  803. SeriesData.prototype.getLayout = function (key) {
  804. return this._layout[key];
  805. };
  806. /**
  807. * Get layout of single data item
  808. */
  809. SeriesData.prototype.getItemLayout = function (idx) {
  810. return this._itemLayouts[idx];
  811. };
  812. /**
  813. * Set layout of single data item
  814. */
  815. SeriesData.prototype.setItemLayout = function (idx, layout, merge) {
  816. this._itemLayouts[idx] = merge ? zrUtil.extend(this._itemLayouts[idx] || {}, layout) : layout;
  817. };
  818. /**
  819. * Clear all layout of single data item
  820. */
  821. SeriesData.prototype.clearItemLayouts = function () {
  822. this._itemLayouts.length = 0;
  823. };
  824. /**
  825. * Set graphic element relative to data. It can be set as null
  826. */
  827. SeriesData.prototype.setItemGraphicEl = function (idx, el) {
  828. var seriesIndex = this.hostModel && this.hostModel.seriesIndex;
  829. setCommonECData(seriesIndex, this.dataType, idx, el);
  830. this._graphicEls[idx] = el;
  831. };
  832. SeriesData.prototype.getItemGraphicEl = function (idx) {
  833. return this._graphicEls[idx];
  834. };
  835. SeriesData.prototype.eachItemGraphicEl = function (cb, context) {
  836. zrUtil.each(this._graphicEls, function (el, idx) {
  837. if (el) {
  838. cb && cb.call(context, el, idx);
  839. }
  840. });
  841. };
  842. /**
  843. * Shallow clone a new list except visual and layout properties, and graph elements.
  844. * New list only change the indices.
  845. */
  846. SeriesData.prototype.cloneShallow = function (list) {
  847. if (!list) {
  848. list = new SeriesData(this._schema ? this._schema : map(this.dimensions, this._getDimInfo, this), this.hostModel);
  849. }
  850. transferProperties(list, this);
  851. list._store = this._store;
  852. return list;
  853. };
  854. /**
  855. * Wrap some method to add more feature
  856. */
  857. SeriesData.prototype.wrapMethod = function (methodName, injectFunction) {
  858. var originalMethod = this[methodName];
  859. if (typeof originalMethod !== 'function') {
  860. return;
  861. }
  862. this.__wrappedMethods = this.__wrappedMethods || [];
  863. this.__wrappedMethods.push(methodName);
  864. this[methodName] = function () {
  865. var res = originalMethod.apply(this, arguments);
  866. return injectFunction.apply(this, [res].concat(zrUtil.slice(arguments)));
  867. };
  868. }; // ----------------------------------------------------------
  869. // A work around for internal method visiting private member.
  870. // ----------------------------------------------------------
  871. SeriesData.internalField = function () {
  872. prepareInvertedIndex = function (data) {
  873. var invertedIndicesMap = data._invertedIndicesMap;
  874. zrUtil.each(invertedIndicesMap, function (invertedIndices, dim) {
  875. var dimInfo = data._dimInfos[dim]; // Currently, only dimensions that has ordinalMeta can create inverted indices.
  876. var ordinalMeta = dimInfo.ordinalMeta;
  877. var store = data._store;
  878. if (ordinalMeta) {
  879. invertedIndices = invertedIndicesMap[dim] = new CtorInt32Array(ordinalMeta.categories.length); // The default value of TypedArray is 0. To avoid miss
  880. // mapping to 0, we should set it as INDEX_NOT_FOUND.
  881. for (var i = 0; i < invertedIndices.length; i++) {
  882. invertedIndices[i] = INDEX_NOT_FOUND;
  883. }
  884. for (var i = 0; i < store.count(); i++) {
  885. // Only support the case that all values are distinct.
  886. invertedIndices[store.get(dimInfo.storeDimIndex, i)] = i;
  887. }
  888. }
  889. });
  890. };
  891. getIdNameFromStore = function (data, dimIdx, idx) {
  892. return convertOptionIdName(data._getCategory(dimIdx, idx), null);
  893. };
  894. /**
  895. * @see the comment of `List['getId']`.
  896. */
  897. getId = function (data, rawIndex) {
  898. var id = data._idList[rawIndex];
  899. if (id == null && data._idDimIdx != null) {
  900. id = getIdNameFromStore(data, data._idDimIdx, rawIndex);
  901. }
  902. if (id == null) {
  903. id = ID_PREFIX + rawIndex;
  904. }
  905. return id;
  906. };
  907. normalizeDimensions = function (dimensions) {
  908. if (!zrUtil.isArray(dimensions)) {
  909. dimensions = dimensions != null ? [dimensions] : [];
  910. }
  911. return dimensions;
  912. };
  913. /**
  914. * Data in excludeDimensions is copied, otherwise transfered.
  915. */
  916. cloneListForMapAndSample = function (original) {
  917. var list = new SeriesData(original._schema ? original._schema : map(original.dimensions, original._getDimInfo, original), original.hostModel); // FIXME If needs stackedOn, value may already been stacked
  918. transferProperties(list, original);
  919. return list;
  920. };
  921. transferProperties = function (target, source) {
  922. zrUtil.each(TRANSFERABLE_PROPERTIES.concat(source.__wrappedMethods || []), function (propName) {
  923. if (source.hasOwnProperty(propName)) {
  924. target[propName] = source[propName];
  925. }
  926. });
  927. target.__wrappedMethods = source.__wrappedMethods;
  928. zrUtil.each(CLONE_PROPERTIES, function (propName) {
  929. target[propName] = zrUtil.clone(source[propName]);
  930. });
  931. target._calculationInfo = zrUtil.extend({}, source._calculationInfo);
  932. };
  933. makeIdFromName = function (data, idx) {
  934. var nameList = data._nameList;
  935. var idList = data._idList;
  936. var nameDimIdx = data._nameDimIdx;
  937. var idDimIdx = data._idDimIdx;
  938. var name = nameList[idx];
  939. var id = idList[idx];
  940. if (name == null && nameDimIdx != null) {
  941. nameList[idx] = name = getIdNameFromStore(data, nameDimIdx, idx);
  942. }
  943. if (id == null && idDimIdx != null) {
  944. idList[idx] = id = getIdNameFromStore(data, idDimIdx, idx);
  945. }
  946. if (id == null && name != null) {
  947. var nameRepeatCount = data._nameRepeatCount;
  948. var nmCnt = nameRepeatCount[name] = (nameRepeatCount[name] || 0) + 1;
  949. id = name;
  950. if (nmCnt > 1) {
  951. id += '__ec__' + nmCnt;
  952. }
  953. idList[idx] = id;
  954. }
  955. };
  956. }();
  957. return SeriesData;
  958. }();
  959. export default SeriesData;