| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216 |
- var _config = require("../config");
- var __DEV__ = _config.__DEV__;
- var zrUtil = require("zrender/lib/core/util");
- var Model = require("../model/Model");
- var DataDiffer = require("./DataDiffer");
- var modelUtil = require("../util/model");
- /**
- * List for data storage
- * @module echarts/data/List
- */
- var isObject = zrUtil.isObject;
- var UNDEFINED = 'undefined';
- var globalObj = typeof window === UNDEFINED ? global : window;
- var dataCtors = {
- 'float': typeof globalObj.Float64Array === UNDEFINED ? Array : globalObj.Float64Array,
- 'int': typeof globalObj.Int32Array === UNDEFINED ? Array : globalObj.Int32Array,
- // Ordinal data type can be string or int
- 'ordinal': Array,
- 'number': Array,
- 'time': Array
- };
- var TRANSFERABLE_PROPERTIES = ['stackedOn', 'hasItemOption', '_nameList', '_idList', '_rawData'];
- function transferProperties(a, b) {
- zrUtil.each(TRANSFERABLE_PROPERTIES.concat(b.__wrappedMethods || []), function (propName) {
- if (b.hasOwnProperty(propName)) {
- a[propName] = b[propName];
- }
- });
- a.__wrappedMethods = b.__wrappedMethods;
- }
- function DefaultDataProvider(dataArray) {
- this._array = dataArray || [];
- }
- DefaultDataProvider.prototype.pure = false;
- DefaultDataProvider.prototype.count = function () {
- return this._array.length;
- };
- DefaultDataProvider.prototype.getItem = function (idx) {
- return this._array[idx];
- };
- /**
- * @constructor
- * @alias module:echarts/data/List
- *
- * @param {Array.<string|Object>} dimensions
- * For example, ['someDimName', {name: 'someDimName', type: 'someDimType'}, ...].
- * Dimensions should be concrete names like x, y, z, lng, lat, angle, radius
- * @param {module:echarts/model/Model} hostModel
- */
- var List = function (dimensions, hostModel) {
- dimensions = dimensions || ['x', 'y'];
- var dimensionInfos = {};
- var dimensionNames = [];
- for (var i = 0; i < dimensions.length; i++) {
- var dimensionName;
- var dimensionInfo = {};
- if (typeof dimensions[i] === 'string') {
- dimensionName = dimensions[i];
- dimensionInfo = {
- name: dimensionName,
- coordDim: dimensionName,
- coordDimIndex: 0,
- stackable: false,
- // Type can be 'float', 'int', 'number'
- // Default is number, Precision of float may not enough
- type: 'number'
- };
- } else {
- dimensionInfo = dimensions[i];
- dimensionName = dimensionInfo.name;
- dimensionInfo.type = dimensionInfo.type || 'number';
- if (!dimensionInfo.coordDim) {
- dimensionInfo.coordDim = dimensionName;
- dimensionInfo.coordDimIndex = 0;
- }
- }
- dimensionInfo.otherDims = dimensionInfo.otherDims || {};
- dimensionNames.push(dimensionName);
- dimensionInfos[dimensionName] = dimensionInfo;
- }
- /**
- * @readOnly
- * @type {Array.<string>}
- */
- this.dimensions = dimensionNames;
- /**
- * Infomation of each data dimension, like data type.
- * @type {Object}
- */
- this._dimensionInfos = dimensionInfos;
- /**
- * @type {module:echarts/model/Model}
- */
- this.hostModel = hostModel;
- /**
- * @type {module:echarts/model/Model}
- */
- this.dataType;
- /**
- * Indices stores the indices of data subset after filtered.
- * This data subset will be used in chart.
- * @type {Array.<number>}
- * @readOnly
- */
- this.indices = [];
- /**
- * Data storage
- * @type {Object.<key, TypedArray|Array>}
- * @private
- */
- this._storage = {};
- /**
- * @type {Array.<string>}
- */
- this._nameList = [];
- /**
- * @type {Array.<string>}
- */
- this._idList = [];
- /**
- * Models of data option is stored sparse for optimizing memory cost
- * @type {Array.<module:echarts/model/Model>}
- * @private
- */
- this._optionModels = [];
- /**
- * @param {module:echarts/data/List}
- */
- this.stackedOn = null;
- /**
- * Global visual properties after visual coding
- * @type {Object}
- * @private
- */
- this._visual = {};
- /**
- * Globel layout properties.
- * @type {Object}
- * @private
- */
- this._layout = {};
- /**
- * Item visual properties after visual coding
- * @type {Array.<Object>}
- * @private
- */
- this._itemVisuals = [];
- /**
- * Item layout properties after layout
- * @type {Array.<Object>}
- * @private
- */
- this._itemLayouts = [];
- /**
- * Graphic elemnents
- * @type {Array.<module:zrender/Element>}
- * @private
- */
- this._graphicEls = [];
- /**
- * @type {Array.<Array|Object>}
- * @private
- */
- this._rawData;
- /**
- * @type {Object}
- * @private
- */
- this._extent;
- };
- var listProto = List.prototype;
- listProto.type = 'list';
- /**
- * If each data item has it's own option
- * @type {boolean}
- */
- listProto.hasItemOption = true;
- /**
- * Get dimension name
- * @param {string|number} dim
- * Dimension can be concrete names like x, y, z, lng, lat, angle, radius
- * Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius'
- * @return {string} Concrete dim name.
- */
- listProto.getDimension = function (dim) {
- if (!isNaN(dim)) {
- dim = this.dimensions[dim] || dim;
- }
- return dim;
- };
- /**
- * Get type and stackable info of particular dimension
- * @param {string|number} dim
- * Dimension can be concrete names like x, y, z, lng, lat, angle, radius
- * Or a ordinal number. For example getDimensionInfo(0) will return 'x' or 'lng' or 'radius'
- */
- listProto.getDimensionInfo = function (dim) {
- return zrUtil.clone(this._dimensionInfos[this.getDimension(dim)]);
- };
- /**
- * Initialize from data
- * @param {Array.<Object|number|Array>} data
- * @param {Array.<string>} [nameList]
- * @param {Function} [dimValueGetter] (dataItem, dimName, dataIndex, dimIndex) => number
- */
- listProto.initData = function (data, nameList, dimValueGetter) {
- data = data || [];
- var isDataArray = zrUtil.isArray(data);
- if (isDataArray) {
- data = new DefaultDataProvider(data);
- }
- this._rawData = data; // Clear
- var storage = this._storage = {};
- var indices = this.indices = [];
- var dimensions = this.dimensions;
- var dimensionInfoMap = this._dimensionInfos;
- var size = data.count();
- var idList = [];
- var nameRepeatCount = {};
- var nameDimIdx;
- nameList = nameList || []; // Init storage
- for (var i = 0; i < dimensions.length; i++) {
- var dimInfo = dimensionInfoMap[dimensions[i]];
- dimInfo.otherDims.itemName === 0 && (nameDimIdx = i);
- var DataCtor = dataCtors[dimInfo.type];
- storage[dimensions[i]] = new DataCtor(size);
- }
- var self = this;
- if (!dimValueGetter) {
- self.hasItemOption = false;
- } // Default dim value getter
- dimValueGetter = dimValueGetter || function (dataItem, dimName, dataIndex, dimIndex) {
- var value = modelUtil.getDataItemValue(dataItem); // If any dataItem is like { value: 10 }
- if (modelUtil.isDataItemOption(dataItem)) {
- self.hasItemOption = true;
- }
- return modelUtil.converDataValue(value instanceof Array ? value[dimIndex] // If value is a single number or something else not array.
- : value, dimensionInfoMap[dimName]);
- };
- for (var i = 0; i < size; i++) {
- // NOTICE: Try not to write things into dataItem
- var dataItem = data.getItem(i); // Each data item is value
- // [1, 2]
- // 2
- // Bar chart, line chart which uses category axis
- // only gives the 'y' value. 'x' value is the indices of cateogry
- // Use a tempValue to normalize the value to be a (x, y) value
- // Store the data by dimensions
- for (var k = 0; k < dimensions.length; k++) {
- var dim = dimensions[k];
- var dimStorage = storage[dim]; // PENDING NULL is empty or zero
- dimStorage[i] = dimValueGetter(dataItem, dim, i, k);
- }
- indices.push(i);
- } // Use the name in option and create id
- for (var i = 0; i < size; i++) {
- var dataItem = data.getItem(i);
- if (!nameList[i] && dataItem) {
- if (dataItem.name != null) {
- nameList[i] = dataItem.name;
- } else if (nameDimIdx != null) {
- nameList[i] = storage[dimensions[nameDimIdx]][i];
- }
- }
- var name = nameList[i] || ''; // Try using the id in option
- var id = dataItem && dataItem.id;
- if (!id && name) {
- // Use name as id and add counter to avoid same name
- nameRepeatCount[name] = nameRepeatCount[name] || 0;
- id = name;
- if (nameRepeatCount[name] > 0) {
- id += '__ec__' + nameRepeatCount[name];
- }
- nameRepeatCount[name]++;
- }
- id && (idList[i] = id);
- }
- this._nameList = nameList;
- this._idList = idList;
- };
- /**
- * @return {number}
- */
- listProto.count = function () {
- return this.indices.length;
- };
- /**
- * Get value. Return NaN if idx is out of range.
- * @param {string} dim Dim must be concrete name.
- * @param {number} idx
- * @param {boolean} stack
- * @return {number}
- */
- listProto.get = function (dim, idx, stack) {
- var storage = this._storage;
- var dataIndex = this.indices[idx]; // If value not exists
- if (dataIndex == null || !storage[dim]) {
- return NaN;
- }
- var value = storage[dim][dataIndex]; // FIXME ordinal data type is not stackable
- if (stack) {
- var dimensionInfo = this._dimensionInfos[dim];
- if (dimensionInfo && dimensionInfo.stackable) {
- var stackedOn = this.stackedOn;
- while (stackedOn) {
- // Get no stacked data of stacked on
- var stackedValue = stackedOn.get(dim, idx); // Considering positive stack, negative stack and empty data
- if (value >= 0 && stackedValue > 0 || // Positive stack
- value <= 0 && stackedValue < 0 // Negative stack
- ) {
- value += stackedValue;
- }
- stackedOn = stackedOn.stackedOn;
- }
- }
- }
- return value;
- };
- /**
- * Get value for multi dimensions.
- * @param {Array.<string>} [dimensions] If ignored, using all dimensions.
- * @param {number} idx
- * @param {boolean} stack
- * @return {number}
- */
- listProto.getValues = function (dimensions, idx, stack) {
- var values = [];
- if (!zrUtil.isArray(dimensions)) {
- stack = idx;
- idx = dimensions;
- dimensions = this.dimensions;
- }
- for (var i = 0, len = dimensions.length; i < len; i++) {
- values.push(this.get(dimensions[i], idx, stack));
- }
- return values;
- };
- /**
- * If value is NaN. Inlcuding '-'
- * @param {string} dim
- * @param {number} idx
- * @return {number}
- */
- listProto.hasValue = function (idx) {
- var dimensions = this.dimensions;
- var dimensionInfos = this._dimensionInfos;
- for (var i = 0, len = dimensions.length; i < len; i++) {
- if ( // Ordinal type can be string or number
- dimensionInfos[dimensions[i]].type !== 'ordinal' && isNaN(this.get(dimensions[i], idx))) {
- return false;
- }
- }
- return true;
- };
- /**
- * Get extent of data in one dimension
- * @param {string} dim
- * @param {boolean} stack
- * @param {Function} filter
- */
- listProto.getDataExtent = function (dim, stack, filter) {
- dim = this.getDimension(dim);
- var dimData = this._storage[dim];
- var dimInfo = this.getDimensionInfo(dim);
- stack = dimInfo && dimInfo.stackable && stack;
- var dimExtent = (this._extent || (this._extent = {}))[dim + !!stack];
- var value;
- if (dimExtent) {
- return dimExtent;
- } // var dimInfo = this._dimensionInfos[dim];
- if (dimData) {
- var min = Infinity;
- var max = -Infinity; // var isOrdinal = dimInfo.type === 'ordinal';
- for (var i = 0, len = this.count(); i < len; i++) {
- value = this.get(dim, i, stack); // FIXME
- // if (isOrdinal && typeof value === 'string') {
- // value = zrUtil.indexOf(dimData, value);
- // }
- if (!filter || filter(value, dim, i)) {
- value < min && (min = value);
- value > max && (max = value);
- }
- }
- return this._extent[dim + !!stack] = [min, max];
- } else {
- return [Infinity, -Infinity];
- }
- };
- /**
- * Get sum of data in one dimension
- * @param {string} dim
- * @param {boolean} stack
- */
- listProto.getSum = function (dim, stack) {
- var dimData = this._storage[dim];
- var sum = 0;
- if (dimData) {
- for (var i = 0, len = this.count(); i < len; i++) {
- var value = this.get(dim, i, stack);
- if (!isNaN(value)) {
- sum += value;
- }
- }
- }
- return sum;
- };
- /**
- * Retreive the index with given value
- * @param {number} idx
- * @param {number} value
- * @return {number}
- */
- // FIXME Precision of float value
- listProto.indexOf = function (dim, value) {
- var storage = this._storage;
- var dimData = storage[dim];
- var indices = this.indices;
- if (dimData) {
- for (var i = 0, len = indices.length; i < len; i++) {
- var rawIndex = indices[i];
- if (dimData[rawIndex] === value) {
- return i;
- }
- }
- }
- return -1;
- };
- /**
- * Retreive the index with given name
- * @param {number} idx
- * @param {number} name
- * @return {number}
- */
- listProto.indexOfName = function (name) {
- var indices = this.indices;
- var nameList = this._nameList;
- for (var i = 0, len = indices.length; i < len; i++) {
- var rawIndex = indices[i];
- if (nameList[rawIndex] === name) {
- return i;
- }
- }
- return -1;
- };
- /**
- * Retreive the index with given raw data index
- * @param {number} idx
- * @param {number} name
- * @return {number}
- */
- listProto.indexOfRawIndex = function (rawIndex) {
- // Indices are ascending
- var indices = this.indices; // If rawIndex === dataIndex
- var rawDataIndex = indices[rawIndex];
- if (rawDataIndex != null && rawDataIndex === rawIndex) {
- return rawIndex;
- }
- var left = 0;
- var right = indices.length - 1;
- while (left <= right) {
- var mid = (left + right) / 2 | 0;
- if (indices[mid] < rawIndex) {
- left = mid + 1;
- } else if (indices[mid] > rawIndex) {
- right = mid - 1;
- } else {
- return mid;
- }
- }
- return -1;
- };
- /**
- * Retreive the index of nearest value
- * @param {string} dim
- * @param {number} value
- * @param {boolean} stack If given value is after stacked
- * @param {number} [maxDistance=Infinity]
- * @return {Array.<number>} Considere multiple points has the same value.
- */
- listProto.indicesOfNearest = function (dim, value, stack, maxDistance) {
- var storage = this._storage;
- var dimData = storage[dim];
- var nearestIndices = [];
- if (!dimData) {
- return nearestIndices;
- }
- if (maxDistance == null) {
- maxDistance = Infinity;
- }
- var minDist = Number.MAX_VALUE;
- var minDiff = -1;
- for (var i = 0, len = this.count(); i < len; i++) {
- var diff = value - this.get(dim, i, stack);
- var dist = Math.abs(diff);
- if (diff <= maxDistance && dist <= minDist) {
- // For the case of two data are same on xAxis, which has sequence data.
- // Show the nearest index
- // https://github.com/ecomfe/echarts/issues/2869
- if (dist < minDist || diff >= 0 && minDiff < 0) {
- minDist = dist;
- minDiff = diff;
- nearestIndices.length = 0;
- }
- nearestIndices.push(i);
- }
- }
- return nearestIndices;
- };
- /**
- * Get raw data index
- * @param {number} idx
- * @return {number}
- */
- listProto.getRawIndex = function (idx) {
- var rawIdx = this.indices[idx];
- return rawIdx == null ? -1 : rawIdx;
- };
- /**
- * Get raw data item
- * @param {number} idx
- * @return {number}
- */
- listProto.getRawDataItem = function (idx) {
- return this._rawData.getItem(this.getRawIndex(idx));
- };
- /**
- * @param {number} idx
- * @param {boolean} [notDefaultIdx=false]
- * @return {string}
- */
- listProto.getName = function (idx) {
- return this._nameList[this.indices[idx]] || '';
- };
- /**
- * @param {number} idx
- * @param {boolean} [notDefaultIdx=false]
- * @return {string}
- */
- listProto.getId = function (idx) {
- return this._idList[this.indices[idx]] || this.getRawIndex(idx) + '';
- };
- function normalizeDimensions(dimensions) {
- if (!zrUtil.isArray(dimensions)) {
- dimensions = [dimensions];
- }
- return dimensions;
- }
- /**
- * Data iteration
- * @param {string|Array.<string>}
- * @param {Function} cb
- * @param {boolean} [stack=false]
- * @param {*} [context=this]
- *
- * @example
- * list.each('x', function (x, idx) {});
- * list.each(['x', 'y'], function (x, y, idx) {});
- * list.each(function (idx) {})
- */
- listProto.each = function (dims, cb, stack, context) {
- if (typeof dims === 'function') {
- context = stack;
- stack = cb;
- cb = dims;
- dims = [];
- }
- dims = zrUtil.map(normalizeDimensions(dims), this.getDimension, this);
- var value = [];
- var dimSize = dims.length;
- var indices = this.indices;
- context = context || this;
- for (var i = 0; i < indices.length; i++) {
- // Simple optimization
- switch (dimSize) {
- case 0:
- cb.call(context, i);
- break;
- case 1:
- cb.call(context, this.get(dims[0], i, stack), i);
- break;
- case 2:
- cb.call(context, this.get(dims[0], i, stack), this.get(dims[1], i, stack), i);
- break;
- default:
- for (var k = 0; k < dimSize; k++) {
- value[k] = this.get(dims[k], i, stack);
- } // Index
- value[k] = i;
- cb.apply(context, value);
- }
- }
- };
- /**
- * Data filter
- * @param {string|Array.<string>}
- * @param {Function} cb
- * @param {boolean} [stack=false]
- * @param {*} [context=this]
- */
- listProto.filterSelf = function (dimensions, cb, stack, context) {
- if (typeof dimensions === 'function') {
- context = stack;
- stack = cb;
- cb = dimensions;
- dimensions = [];
- }
- dimensions = zrUtil.map(normalizeDimensions(dimensions), this.getDimension, this);
- var newIndices = [];
- var value = [];
- var dimSize = dimensions.length;
- var indices = this.indices;
- context = context || this;
- for (var i = 0; i < indices.length; i++) {
- var keep; // Simple optimization
- if (!dimSize) {
- keep = cb.call(context, i);
- } else if (dimSize === 1) {
- keep = cb.call(context, this.get(dimensions[0], i, stack), i);
- } else {
- for (var k = 0; k < dimSize; k++) {
- value[k] = this.get(dimensions[k], i, stack);
- }
- value[k] = i;
- keep = cb.apply(context, value);
- }
- if (keep) {
- newIndices.push(indices[i]);
- }
- }
- this.indices = newIndices; // Reset data extent
- this._extent = {};
- return this;
- };
- /**
- * Data mapping to a plain array
- * @param {string|Array.<string>} [dimensions]
- * @param {Function} cb
- * @param {boolean} [stack=false]
- * @param {*} [context=this]
- * @return {Array}
- */
- listProto.mapArray = function (dimensions, cb, stack, context) {
- if (typeof dimensions === 'function') {
- context = stack;
- stack = cb;
- cb = dimensions;
- dimensions = [];
- }
- var result = [];
- this.each(dimensions, function () {
- result.push(cb && cb.apply(this, arguments));
- }, stack, context);
- return result;
- };
- function cloneListForMapAndSample(original, excludeDimensions) {
- var allDimensions = original.dimensions;
- var list = new List(zrUtil.map(allDimensions, original.getDimensionInfo, original), original.hostModel); // FIXME If needs stackedOn, value may already been stacked
- transferProperties(list, original);
- var storage = list._storage = {};
- var originalStorage = original._storage; // Init storage
- for (var i = 0; i < allDimensions.length; i++) {
- var dim = allDimensions[i];
- var dimStore = originalStorage[dim];
- if (zrUtil.indexOf(excludeDimensions, dim) >= 0) {
- storage[dim] = new dimStore.constructor(originalStorage[dim].length);
- } else {
- // Direct reference for other dimensions
- storage[dim] = originalStorage[dim];
- }
- }
- return list;
- }
- /**
- * Data mapping to a new List with given dimensions
- * @param {string|Array.<string>} dimensions
- * @param {Function} cb
- * @param {boolean} [stack=false]
- * @param {*} [context=this]
- * @return {Array}
- */
- listProto.map = function (dimensions, cb, stack, context) {
- dimensions = zrUtil.map(normalizeDimensions(dimensions), this.getDimension, this);
- var list = cloneListForMapAndSample(this, dimensions); // Following properties are all immutable.
- // So we can reference to the same value
- var indices = list.indices = this.indices;
- var storage = list._storage;
- var tmpRetValue = [];
- this.each(dimensions, function () {
- var idx = arguments[arguments.length - 1];
- var retValue = cb && cb.apply(this, arguments);
- if (retValue != null) {
- // a number
- if (typeof retValue === 'number') {
- tmpRetValue[0] = retValue;
- retValue = tmpRetValue;
- }
- for (var i = 0; i < retValue.length; i++) {
- var dim = dimensions[i];
- var dimStore = storage[dim];
- var rawIdx = indices[idx];
- if (dimStore) {
- dimStore[rawIdx] = retValue[i];
- }
- }
- }
- }, stack, context);
- return list;
- };
- /**
- * Large data down sampling on given dimension
- * @param {string} dimension
- * @param {number} rate
- * @param {Function} sampleValue
- * @param {Function} sampleIndex Sample index for name and id
- */
- listProto.downSample = function (dimension, rate, sampleValue, sampleIndex) {
- var list = cloneListForMapAndSample(this, [dimension]);
- var storage = this._storage;
- var targetStorage = list._storage;
- var originalIndices = this.indices;
- var indices = list.indices = [];
- var frameValues = [];
- var frameIndices = [];
- var frameSize = Math.floor(1 / rate);
- var dimStore = targetStorage[dimension];
- var len = this.count(); // Copy data from original data
- for (var i = 0; i < storage[dimension].length; i++) {
- targetStorage[dimension][i] = storage[dimension][i];
- }
- for (var i = 0; i < len; i += frameSize) {
- // Last frame
- if (frameSize > len - i) {
- frameSize = len - i;
- frameValues.length = frameSize;
- }
- for (var k = 0; k < frameSize; k++) {
- var idx = originalIndices[i + k];
- frameValues[k] = dimStore[idx];
- frameIndices[k] = idx;
- }
- var value = sampleValue(frameValues);
- var idx = frameIndices[sampleIndex(frameValues, value) || 0]; // Only write value on the filtered data
- dimStore[idx] = value;
- indices.push(idx);
- }
- return list;
- };
- /**
- * Get model of one data item.
- *
- * @param {number} idx
- */
- // FIXME Model proxy ?
- listProto.getItemModel = function (idx) {
- var hostModel = this.hostModel;
- idx = this.indices[idx];
- return new Model(this._rawData.getItem(idx), hostModel, hostModel && hostModel.ecModel);
- };
- /**
- * Create a data differ
- * @param {module:echarts/data/List} otherList
- * @return {module:echarts/data/DataDiffer}
- */
- listProto.diff = function (otherList) {
- var idList = this._idList;
- var otherIdList = otherList && otherList._idList;
- var val; // Use prefix to avoid index to be the same as otherIdList[idx],
- // which will cause weird udpate animation.
- var prefix = 'e\0\0';
- return new DataDiffer(otherList ? otherList.indices : [], this.indices, function (idx) {
- return (val = otherIdList[idx]) != null ? val : prefix + idx;
- }, function (idx) {
- return (val = idList[idx]) != null ? val : prefix + idx;
- });
- };
- /**
- * Get visual property.
- * @param {string} key
- */
- listProto.getVisual = function (key) {
- var visual = this._visual;
- return visual && visual[key];
- };
- /**
- * Set visual property
- * @param {string|Object} key
- * @param {*} [value]
- *
- * @example
- * setVisual('color', color);
- * setVisual({
- * 'color': color
- * });
- */
- listProto.setVisual = function (key, val) {
- if (isObject(key)) {
- for (var name in key) {
- if (key.hasOwnProperty(name)) {
- this.setVisual(name, key[name]);
- }
- }
- return;
- }
- this._visual = this._visual || {};
- this._visual[key] = val;
- };
- /**
- * Set layout property.
- * @param {string|Object} key
- * @param {*} [val]
- */
- listProto.setLayout = function (key, val) {
- if (isObject(key)) {
- for (var name in key) {
- if (key.hasOwnProperty(name)) {
- this.setLayout(name, key[name]);
- }
- }
- return;
- }
- this._layout[key] = val;
- };
- /**
- * Get layout property.
- * @param {string} key.
- * @return {*}
- */
- listProto.getLayout = function (key) {
- return this._layout[key];
- };
- /**
- * Get layout of single data item
- * @param {number} idx
- */
- listProto.getItemLayout = function (idx) {
- return this._itemLayouts[idx];
- };
- /**
- * Set layout of single data item
- * @param {number} idx
- * @param {Object} layout
- * @param {boolean=} [merge=false]
- */
- listProto.setItemLayout = function (idx, layout, merge) {
- this._itemLayouts[idx] = merge ? zrUtil.extend(this._itemLayouts[idx] || {}, layout) : layout;
- };
- /**
- * Clear all layout of single data item
- */
- listProto.clearItemLayouts = function () {
- this._itemLayouts.length = 0;
- };
- /**
- * Get visual property of single data item
- * @param {number} idx
- * @param {string} key
- * @param {boolean} [ignoreParent=false]
- */
- listProto.getItemVisual = function (idx, key, ignoreParent) {
- var itemVisual = this._itemVisuals[idx];
- var val = itemVisual && itemVisual[key];
- if (val == null && !ignoreParent) {
- // Use global visual property
- return this.getVisual(key);
- }
- return val;
- };
- /**
- * Set visual property of single data item
- *
- * @param {number} idx
- * @param {string|Object} key
- * @param {*} [value]
- *
- * @example
- * setItemVisual(0, 'color', color);
- * setItemVisual(0, {
- * 'color': color
- * });
- */
- listProto.setItemVisual = function (idx, key, value) {
- var itemVisual = this._itemVisuals[idx] || {};
- this._itemVisuals[idx] = itemVisual;
- if (isObject(key)) {
- for (var name in key) {
- if (key.hasOwnProperty(name)) {
- itemVisual[name] = key[name];
- }
- }
- return;
- }
- itemVisual[key] = value;
- };
- /**
- * Clear itemVisuals and list visual.
- */
- listProto.clearAllVisual = function () {
- this._visual = {};
- this._itemVisuals = [];
- };
- var setItemDataAndSeriesIndex = function (child) {
- child.seriesIndex = this.seriesIndex;
- child.dataIndex = this.dataIndex;
- child.dataType = this.dataType;
- };
- /**
- * Set graphic element relative to data. It can be set as null
- * @param {number} idx
- * @param {module:zrender/Element} [el]
- */
- listProto.setItemGraphicEl = function (idx, el) {
- var hostModel = this.hostModel;
- if (el) {
- // Add data index and series index for indexing the data by element
- // Useful in tooltip
- el.dataIndex = idx;
- el.dataType = this.dataType;
- el.seriesIndex = hostModel && hostModel.seriesIndex;
- if (el.type === 'group') {
- el.traverse(setItemDataAndSeriesIndex, el);
- }
- }
- this._graphicEls[idx] = el;
- };
- /**
- * @param {number} idx
- * @return {module:zrender/Element}
- */
- listProto.getItemGraphicEl = function (idx) {
- return this._graphicEls[idx];
- };
- /**
- * @param {Function} cb
- * @param {*} context
- */
- listProto.eachItemGraphicEl = function (cb, context) {
- zrUtil.each(this._graphicEls, function (el, idx) {
- if (el) {
- cb && cb.call(context, el, idx);
- }
- });
- };
- /**
- * Shallow clone a new list except visual and layout properties, and graph elements.
- * New list only change the indices.
- */
- listProto.cloneShallow = function () {
- var dimensionInfoList = zrUtil.map(this.dimensions, this.getDimensionInfo, this);
- var list = new List(dimensionInfoList, this.hostModel); // FIXME
- list._storage = this._storage;
- transferProperties(list, this); // Clone will not change the data extent and indices
- list.indices = this.indices.slice();
- if (this._extent) {
- list._extent = zrUtil.extend({}, this._extent);
- }
- return list;
- };
- /**
- * Wrap some method to add more feature
- * @param {string} methodName
- * @param {Function} injectFunction
- */
- listProto.wrapMethod = function (methodName, injectFunction) {
- var originalMethod = this[methodName];
- if (typeof originalMethod !== 'function') {
- return;
- }
- this.__wrappedMethods = this.__wrappedMethods || [];
- this.__wrappedMethods.push(methodName);
- this[methodName] = function () {
- var res = originalMethod.apply(this, arguments);
- return injectFunction.apply(this, [res].concat(zrUtil.slice(arguments)));
- };
- }; // Methods that create a new list based on this list should be listed here.
- // Notice that those method should `RETURN` the new list.
- listProto.TRANSFERABLE_METHODS = ['cloneShallow', 'downSample', 'map']; // Methods that change indices of this list should be listed here.
- listProto.CHANGABLE_METHODS = ['filterSelf'];
- var _default = List;
- module.exports = _default;
|