提交 ac7cd8ba 编写于 作者: L lang

Rewrite List

上级 b855c467
......@@ -12,8 +12,9 @@ define(function (require) {
require('../echarts').registerLayout(zrUtil.curry(barLayoutGrid, 'bar'));
// Visual coding for legend
require('../echarts').registerVisualCoding(function (ecModel) {
ecModel.eachSeriesByType('bar', function (seriesSymbol) {
seriesSymbol.setVisual('legendSymbol', 'roundRect');
ecModel.eachSeriesByType('bar', function (seriesModel) {
var data = seriesModel.getData();
data.setVisual('legendSymbol', 'roundRect');
});
});
});
\ No newline at end of file
......@@ -21,15 +21,17 @@ define(function (require) {
_renderCartesian: function (seriesModel, ecModel, api) {
var group = this.group;
var data = seriesModel.getData();
var oldData = this._data;
data.diff(this._data)
.add(function (dataItem, dataIndex) {
data.diff(oldData)
.add(function (dataIndex) {
// 空数据
if (dataItem.getValue() == null) {
if (! data.hasValue(dataIndex)) {
return;
}
var layout = dataItem.layout;
var layout = data.getItemLayout(dataIndex);
var itemModel = data.getItemModel(dataIndex);
var rect = new api.Rect({
shape: {
x: layout.x,
......@@ -37,18 +39,15 @@ define(function (require) {
width: layout.width
},
style: zrUtil.extend(
dataItem.getModel('itemStyle.normal').getItemStyle(),
itemModel.getModel('itemStyle.normal').getItemStyle(),
{
fill: dataItem.getVisual('color')
fill: data.getItemVisual(dataIndex, 'color')
}
)
});
dataItem.__el = rect;
rect.__data = dataItem;
// Attach data on the el
rect.data = dataItem;
data.setItemGraphicEl(dataIndex, rect);
rect.dataIndex = dataIndex;
group.add(rect);
......@@ -57,24 +56,25 @@ define(function (require) {
shape: layout
}, 1000, 300 * dataIndex / data.count(), 'cubicOut');
})
.update(function (newData, oldData) {
var rect = oldData.__el;
.update(function (newIndex, oldIndex) {
var rect = oldData.getItemGraphicEl(oldIndex);
// 空数据
if (newData.getValue() == null) {
if (! data.hasValue(newIndex)) {
group.remove(rect);
return;
}
rect.animateTo({
shape: newData.layout
shape: data.getItemLayout(newIndex)
}, 500, 'cubicOut');
newData.__el = rect;
data.setItemGraphicEl(newIndex, rect);
rect.dataIndex = newIndex;
// Add back
group.add(rect);
})
.remove(function (dataItem, idx) {
var el = dataItem.__el;
.remove(function (idx) {
var el = oldData.getItemGraphicEl(idx);
el.animateTo({
shape: {
width: 0
......@@ -92,8 +92,7 @@ define(function (require) {
remove: function () {
if (this._data) {
var group = this.group;
this._data.each(function (dataItem) {
var el = dataItem.__el;
this._data.eachItemGraphicEl(function (el) {
el.animateTo({
shape: {
width: 0
......
......@@ -8,15 +8,18 @@ define(function (require) {
return dataItem.__symbolEl;
}
function createSymbol(dataItem, enableAnimation) {
var layout = dataItem.layout;
var color = dataItem.getVisual('color');
function createSymbol(data, idx, enableAnimation) {
var point = data.getItemLayout(idx);
var color = data.getItemVisual(idx, 'color');
var symbolSize = dataItem.getVisual('symbolSize');
var symbolType = dataItem.getVisual('symbol') || 'circle';
var symbolEl = symbolCreators.createSymbol(symbolType, -0.5, -0.5, 1, 1, color);
var symbolSize = data.getItemVisual(idx, 'symbolSize');
var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
symbolEl.position = [layout.x, layout.y];
var symbolEl = symbolCreators.createSymbol(
symbolType, -0.5, -0.5, 1, 1, color
);
symbolEl.position = point;
if (enableAnimation) {
......@@ -67,33 +70,33 @@ define(function (require) {
updateData: function (data, enableAnimation) {
var group = this.group;
var oldData = this._data;
data.diff(this._data)
.add(function (dataItem) {
data.diff(oldData)
.add(function (newIdx) {
// 空数据
// TODO
if (dataItem.getValue() == null) {
if (!data.hasValue(newIdx)) {
return;
}
var symbolShape = createSymbol(dataItem, enableAnimation);
var symbolEl = createSymbol(data, newIdx, enableAnimation);
dataItem.__symbolEl = symbolShape;
data.setItemGraphicEl(newIdx, symbolEl);
// Attach data on the el
symbolShape.data = dataItem;
symbolEl.dataIndex = newIdx;
group.add(symbolShape);
group.add(symbolEl);
})
.update(function (newData, oldData) {
var symbolSize = newData.getVisual('symbolSize');
var layout = newData.layout;
var el = oldData.__symbolEl;
.update(function (newIdx, oldIdx) {
var symbolSize = data.getItemVisual(newIdx, 'symbolSize');
var point = data.getItemLayout(newIdx);
var el = oldData.getItemGraphicEl(oldIdx);
// 空数据
// TODO
if (newData.getValue() == null) {
group.remove(el);
if (!data.hasValue(newIdx)) {
return;
}
......@@ -101,49 +104,47 @@ define(function (require) {
if (enableAnimation) {
el.animateTo({
scale: [symbolSize, symbolSize],
position: [layout.x, layout.y]
position: point
}, 300, 'cubicOut');
}
else {
el.attr({
scale: [symbolSize, symbolSize],
position: [layout.x, layout.y]
position: point
});
}
newData.__symbolEl = el;
data.setItemGraphicEl(newIdx, el);
data.dataIndex = newIdx;
// Add back
group.add(el);
})
.remove(function (dataItem) {
var el = dataItem.__symbolEl;
if (el) {
if (enableAnimation) {
el.animateTo({
scale: [0, 0]
}, 200, 'cubicOut', function () {
group.remove(el);
});
}
else {
.remove(function (oldIdx) {
var el = oldData.getItemGraphicEl(oldIdx);
if (enableAnimation) {
el.animateTo({
scale: [0, 0]
}, 200, 'cubicOut', function () {
group.remove(el);
}
});
}
else {
group.remove(el);
}
})
.execute();
// Update common properties
data.each(function (dataItem) {
var el = dataItem.__symbolEl;
data.eachItemGraphicEl(function (el, idx) {
el.z = this.z;
zrUtil.extend(
el.style,
dataItem.getModel('itemStyle.normal').getItemStyle()
data.getItemModel(idx).getModel('itemStyle.normal').getItemStyle()
);
var symbolSize = dataItem.getVisual('symbolSize');
var symbolSize = data.getItemVisual(idx, 'symbolSize');
// Adjust the line width
el.__lineWidth = el.__lineWidth || el.style.lineWidth;
el.style.lineWidth = el.__lineWidth / symbolSize;
......@@ -155,14 +156,18 @@ define(function (require) {
remove: function (enableAnimation) {
if (this._data) {
var group = this.group;
this._data.each(function (dataItem) {
var el = dataItem.__symbolEl;
el.animateTo({
scale: [0, 0]
}, 200, 'cubicOut', function () {
group.remove(el);
if (enableAnimation) {
this._data.eachItemGraphicEl(function (el) {
el.animateTo({
scale: [0, 0]
}, 200, 'cubicOut', function () {
group.remove(el);
});
});
});
}
else {
group.removeAll();
}
}
}
}
......
......@@ -37,12 +37,7 @@ define(function(require) {
var data = seriesModel.getData();
var lineStyleNormalModel = seriesModel.getModel('itemStyle.normal.lineStyle');
var points = data.map(function (dataItem) {
var layout = dataItem.layout;
if (layout) {
return [layout.x, layout.y];
}
});
var points = data.map(data.getItemLayout, true);
var pointsWithName = data.map(function (dataItem, idx) {
return {
name: dataItem.name,
......@@ -78,7 +73,7 @@ define(function(require) {
style: zrUtil.extend(
lineStyleNormalModel.getLineStyle(),
{
stroke: seriesModel.getVisual('color'),
stroke: data.getVisual('color'),
lineJoin: 'bevel'
}
)
......
......@@ -12,7 +12,12 @@ define(function (require) {
dependencies: ['grid', 'polar'],
getInitialData: function (option, ecModel) {
return List.fromArray(option.data, this, ecModel);
var list = List.fromArray(option.data, this, ecModel);
// Not holding the data anymore so it can be removed in momory
// PENDING
// option.data = null;
return list;
},
defaultOption: {
......
......@@ -12,7 +12,9 @@ define(function (require) {
},
render: function (seriesModel, ecModel, api) {
this._dataSymbol.updateData(seriesModel.getData(), true);
this._dataSymbol.updateData(
seriesModel.getData(), ecModel.get('animation')
);
},
remove: function () {
......
......@@ -25,7 +25,7 @@ define(function(require) {
type: 'angleAxis',
render: function (angleAxisModel, ecModel, api) {
this.group.clear();
this.group.removeAll();
var polarModel = ecModel.getComponent('polar', angleAxisModel.get('polarIndex'));
var angleAxis = angleAxisModel.axis;
......
......@@ -2,6 +2,7 @@
// Axis tick interval
// Axis name
// boundaryGap
// Custom label itemStyle
define(function(require) {
'use strict';
......@@ -22,7 +23,7 @@ define(function(require) {
render: function (axisModel, ecModel, api) {
this.group.clear();
this.group.removeAll();
var gridModel = ecModel.getComponent('grid', axisModel.get('gridIndex'));
......
......@@ -45,7 +45,7 @@ define(function (require) {
this._orient = dataZoomModel.get('orient');
if (!event || event.type !== 'dataZoom' || event.from !== this.uid) {
this.group.clear();
this.group.removeAll();
if (this.dataZoomModel.get('show') === false) {
return;
......
......@@ -34,12 +34,12 @@ define(function (require) {
var dataExtent = calculateDataExtent(dimNames, axisModel, seriesModels);
var dataWindow = calculateDataWindow(axisModel, dataZoomModel, dataExtent, isCategoryFilter);
if (isCategoryFilter) {
var axisData = axisModel.getData();
// if (isCategoryFilter) {
// var axisData = axisModel.getData();
// FIXME
// setter?
axisData = axisModel.option.data = axisData.slice(dataWindow[0], dataWindow[1] + 1);
}
// axisData = axisModel.option.data = axisData.slice(dataWindow[0], dataWindow[1] + 1);
// }
// Process series data
zrUtil.each(seriesModels, function (seriesModel) {
......@@ -50,22 +50,25 @@ define(function (require) {
return;
}
if (isCategoryFilter) {
seriesData.filterSelf(function (entry) {
var dataIndex = entry[dimNames.getter]();
var reserve = dataIndex >= dataWindow[0] && dataIndex <= dataWindow[1];
if (reserve) {
entry.setDataIndex(dataIndex - dataWindow[0]);
}
return reserve;
});
}
else {
seriesData.filterSelf(function (entry) {
var value = entry[dimNames.getter]();
return value >= dataWindow[0] && value <= dataWindow[1];
});
}
// if (isCategoryFilter) {
// seriesData.filterSelf(function (entry) {
// var dataIndex = entry[dimNames.getter]();
// var reserve = dataIndex >= dataWindow[0] && dataIndex <= dataWindow[1];
// if (reserve) {
// entry.setDataIndex(dataIndex - dataWindow[0]);
// }
// return reserve;
// });
// }
// else {
// seriesData.filterSelf(function (entry) {
// var value = entry[dimNames.getter]();
// return value >= dataWindow[0] && value <= dataWindow[1];
// });
// }
seriesData.filterSelf(dimNames.dim, function (value) {
return value >= dataWindow[0] && value <= dataWindow[1];
});
// FIXME
// 对于value轴的过滤(另一个轴是category),效果有问题,现在简单去除节点不行。
......@@ -88,7 +91,7 @@ define(function (require) {
zrUtil.each(seriesModels, function (seriesModel) {
var seriesData = seriesModel.getData();
if (seriesData) {
var seriesExtent = seriesData[dimNames.extentGetter]();
var seriesExtent = seriesData.getDataExtent(dimNames.dim);
seriesExtent[0] < dataExtent[0] && (dataExtent[0] = seriesExtent[0]);
seriesExtent[1] > dataExtent[1] && (dataExtent[1] = seriesExtent[1]);
}
......
......@@ -19,9 +19,7 @@ define(function(require) {
axis: axisDim + 'Axis',
dim: axisDim,
capital: capital,
index: axisDim + 'Index',
getter: 'get' + capital,
extentGetter: 'getExtent' + capital
index: axisDim + 'Index'
};
callback.call(context, names);
});
......
......@@ -11,7 +11,7 @@ define(function(require) {
type: 'grid',
render: function (gridModel, ecModel, api) {
this.group.clear();
this.group.removeAll();
if (gridModel.get('show')) {
this.group.add(new api.Rect({
shape:gridModel.coordinateSystem.getRect(),
......
......@@ -2,8 +2,8 @@ define(function(require) {
'use strict';
var List = require('../../data/List');
var zrUtil = require('zrender/core/util');
var Model = require('../../model/Model');
return require('../../echarts').extendComponentModel({
......@@ -16,15 +16,14 @@ define(function(require) {
option.selected = option.selected || {};
var list = new List();
zrUtil.each(option.data, function (dataItem) {
this._data = zrUtil.map(option.data, function (dataItem) {
if (typeof dataItem === 'string') {
dataItem = {
name: dataItem
};
}
list.add(dataItem, this);
});
return new Model(dataItem, this);
}, this);
/**
* @type {Array.<string>}
......@@ -34,11 +33,10 @@ define(function(require) {
return series.name;
});
this._data = list;
},
/**
* @return {module:echarts/data/List}
* @return {Array.<module:echarts/model/Model>}
*/
getData: function () {
return this._data;
......
......@@ -25,7 +25,7 @@ define(function (require) {
var orient = legendModel.get('orient');
var group = this.group;
group.clear();
group.removeAll();
group.position = [
numberUtil.parsePercent(
......@@ -42,20 +42,21 @@ define(function (require) {
var width = 20;
var height = 10;
legendModel.getData().each(function (dataItem) {
var seriesName = dataItem.name;
zrUtil.each(legendModel.getData(), function (itemModel) {
var seriesName = itemModel.get('name');
var seriesModel = ecModel.getSeriesByName(seriesName, true);
var data = seriesModel.getData();
var color = legendModel.isSelected(seriesName)
? seriesModel.getVisual('color')
? data.getVisual('color')
: '#ccc';
var legendSymbol = this._createSymbol(
seriesModel, x, y, width, height, color, api
data, x, y, width, height, color, api
);
var text = new api.Text({
style: {
text: dataItem.name,
text: seriesName,
x: x + width + 5,
y: y,
fill: '#000',
......@@ -84,13 +85,13 @@ define(function (require) {
group.position[0] -= groupRect.width / 2;
},
_createSymbol: function (seriesModel, x, y, width, height, color, api) {
_createSymbol: function (data, x, y, width, height, color, api) {
var group = new api.Group();
// Using rect symbol defaultly
var legendSymbolType = seriesModel && seriesModel.getVisual('legendSymbol')
var legendSymbolType = data && data.getVisual('legendSymbol')
|| 'roundRect';
var symbolType = seriesModel && seriesModel.getVisual('symbol');
var symbolType = data && data.getVisual('symbol');
group.add(symbolCreator.createSymbol(
legendSymbolType, x, y, width, height, color
......
......@@ -13,7 +13,7 @@ define(function(require) {
type: 'radiusAxis',
render: function (radiusAxisModel, ecModel, api) {
this.group.clear();
this.group.removeAll();
var polarModel = ecModel.getComponent('polar', radiusAxisModel.get('polarIndex'));
var radiusAxis = radiusAxisModel.axis;
......@@ -107,8 +107,8 @@ define(function(require) {
var len = vector.dist(end, start);
var direction = [
start[1] - end[1],
end[0] - start[0]
end[1] - start[1],
start[0] - end[0]
];
vector.normalize(direction, direction);
......@@ -127,7 +127,7 @@ define(function(require) {
y: p[1],
text: labels[i],
textAlign: 'center',
textBaseline: 'top',
textBaseline: 'bottom',
font: textStyleModel.getFont()
},
silent: true
......
......@@ -53,7 +53,7 @@ define(function (require) {
render: function (tooltipModel, ecModel, api) {
// Reset
this.group.clear();
this.group.removeAll();
this._axisPointers = {};
this._tooltipModel = tooltipModel;
......
......@@ -90,10 +90,6 @@ define(function (require) {
* @return {number}
*/
dataToCoord: function (data, clamp) {
// PENDING
if (data == null || data === '-') {
return NaN;
}
data = this.scale.normalize(data);
var extent = this.getExtent();
......@@ -163,7 +159,7 @@ define(function (require) {
/**
* Get bands.
*
*
* If axis has labels [1, 2, 3, 4]. Bands on the axis are
* |---1---|---2---|---3---|---4---|.
*
......
......@@ -25,15 +25,15 @@ define(function(require) {
/**
* Convert series data to a list of points
* @param {module:echarts/data/List} data
* @param {boolean} stack
* @return {Array}
* Return list of coordinates. For example:
* `[[10, 10], [20, 20], [30, 30]]`
*/
dataToPoints: function (data) {
return data.map(function (dataItem) {
// PENDGING `MUST` Stack ?
return this.dataToPoint([dataItem.getX(true), dataItem.getY(true)]);
}, this);
dataToPoints: function (data, stack) {
return data.map(['x', 'y'], function (x, y) {
return this.dataToPoint([x, y]);
}, stack, this);
},
/**
......
......@@ -24,7 +24,8 @@ define(function(require, factory) {
var axisType = axisModel.get('type');
if (axisType) {
return axisType === 'category'
? new OrdinalScale(axisModel.getData())
// Give [Infinity, -Infinity] extent to make the unionExtent is right
? new OrdinalScale(axisModel.getData(), [Infinity, -Infinity])
: new IntervalScale();
}
}
......@@ -250,8 +251,6 @@ define(function(require, factory) {
* @private
*/
_updateCartesianFromSeries: function (ecModel, gridModel) {
var axisDataMap = {};
ecModel.eachSeries(function (seriesModel) {
if (seriesModel.get('coordinateSystem') === 'cartesian2d') {
var xAxisIndex = seriesModel.get('xAxisIndex');
......@@ -267,68 +266,31 @@ define(function(require, factory) {
}
var cartesian = this.getCartesian(xAxisIndex, yAxisIndex);
var axisData = axisDataMap[cartesian.name];
if (! axisData) {
axisData = axisDataMap[cartesian.name] = {
x: [],
y: [],
cartesian: cartesian,
xModel: xAxisModel,
yModel: yAxisModel
};
}
var data = seriesModel.getData();
if (data.type === 'list') {
var categoryAxis = cartesian.getAxesByScale('ordinal')[0];
if (! categoryAxis) {
data.eachY(function (value) {
axisData.y.push(value);
});
data.eachX(function (value) {
axisData.x.push(value);
});
}
else {
data.eachValue(function (value) {
if (value != null) {
axisData[categoryAxis.dim === 'y' ? 'x' : 'y'].push(value);
}
}, true);
}
var xAxis = cartesian.getAxis('x');
var yAxis = cartesian.getAxis('y');
xAxis.scale.unionExtent(
data.getDataExtent('x', xAxis.scale.type !== 'ordinal')
);
yAxis.scale.unionExtent(
data.getDataExtent('y', yAxis.scale.type !== 'ordinal')
);
niceScaleExent(xAxis, xAxisModel);
niceScaleExent(yAxis, yAxisModel);
}
}
}, this);
zrUtil.each(axisDataMap, function (axisData) {
var cartesian = axisData.cartesian;
var xAxis = cartesian.getAxis('x');
var yAxis = cartesian.getAxis('y');
if (axisData.x.length) {
var xModel = axisData.xModel;
if (xModel.get('scale')) {
axisData.x.push(0);
}
xAxis.scale.setExtentFromData(axisData.x);
niceScaleExent(xAxis, xModel);
}
if (axisData.y.length) {
var yModel = axisData.yModel;
if (yModel.get('scale')) {
axisData.y.push(0);
}
yAxis.scale.setExtentFromData(axisData.y);
niceScaleExent(yAxis, yModel);
}
});
function niceScaleExent(axis, model) {
if (axis.scale.type === 'ordinal') {
return;
}
var min = model.get('min');
var max = model.get('max');
axis.scale.setExtent(min, max);
axis.scale.niceExtent(model.get('splitNumber'), !!min, !!max);
}
}
......
......@@ -89,8 +89,8 @@ define(function(require) {
* `[[10, 10], [20, 20], [30, 30]]`
*/
dataToPoints: function (data) {
return data.map(function (dataItem) {
return this.dataToPoint([dataItem.getRadius(true), dataItem.getAngle(true)]);
return data.map(['radius', 'angle'], function (radius, angle) {
return this.dataToPoint([radius, angle]);
}, this);
},
......
......@@ -66,7 +66,7 @@ define(function (require) {
if (axisType) {
return axisType === 'value'
? new IntervalScale()
: new OrdinalScale(axisModel.get('data'));
: new OrdinalScale(axisModel.get('data'), [Infinity, -Infinity]);
}
};
......@@ -104,19 +104,14 @@ define(function (require) {
var radiusAxis = polar.getRadiusAxis();
var angleAxis = polar.getAngleAxis();
var isRadiusCategory = radiusAxis.type === 'category';
var isAngleCategory = angleAxis.type === 'category';
var data = seriesModel.getData();
var valueMapper = function (a) {
return a;
}
if (! isRadiusCategory) {
radiusAxis.scale.setExtentFromData(data.mapRadius(valueMapper, true), true);
}
if (! isAngleCategory) {
angleAxis.scale.setExtentFromData(data.mapAngle(valueMapper, true), true);
}
radiusAxis.scale.unionExtent(
data.getDataExtent('radius', radiusAxis.type !== 'category')
);
angleAxis.scale.unionExtent(
data.getDataExtent('angle', angleAxis.type !== 'category')
);
}
});
......
define(function(require) {
'use strict';
function DataDiffer(oldArr, newArr) {
function defaultKeyGetter(item) {
return item;
}
function DataDiffer(oldArr, newArr, keyGetter) {
this._old = oldArr;
this._new = newArr;
this._keyGetter = keyGetter || defaultKeyGetter;
};
DataDiffer.prototype = {
......@@ -37,34 +43,31 @@ define(function(require) {
execute: function () {
var oldArr = this._old;
var newArr = this._new;
var keyGetter = this._keyGetter;
var oldDataMap = {};
var newDataMap = {};
var oldDataIndexMap = {};
var newDataIndexMap = {};
var i;
for (i = 0; i < oldArr.length; i++) {
oldDataMap[oldArr[i].name] = oldArr[i];
oldDataIndexMap[keyGetter(oldArr[i])] = i;
}
for (i = 0; i < newArr.length; i++) {
newDataMap[newArr[i].name] = newArr[i];
newDataIndexMap[newArr[i].name] = i;
newDataIndexMap[keyGetter(newArr[i])] = i;
}
for (i = 0; i < oldArr.length; i++) {
var oldData = oldArr[i];
var newData = newDataMap[oldData.name];
if (newData) {
this._update && this._update(newData, oldData);
var newDataIndex = newDataIndexMap[keyGetter(oldArr[i])];
if (newDataIndex != null) {
this._update && this._update(newDataIndex, i);
}
else {
this._remove && this._remove(oldData);
this._remove && this._remove(i);
}
}
for (i = 0; i < newArr.length; i++) {
var newData = newArr[i];
if (!oldDataMap[newData.name]) {
this._add && this._add(newData, newDataIndexMap[newData.name]);
if (oldDataIndexMap[keyGetter(newArr[i])] == null) {
this._add && this._add(i);
}
}
}
......
/**
* List for data storage
*/
define(function (require) {
var UNDEFINED = 'undefined';
var global = window;
var Float32Array = typeof global.Float32Array === UNDEFINED
? Array : global.Float32Array;
var Int32Array = typeof global.Int32Array === UNDEFINED
? Array : global.Int32Array;
var Model = require('../model/Model');
var List = function (dimensions, seriesModel) {
/**
* @readOnly
* @type {Array.<string>}
*/
this.dimensions = dimensions || ['x', 'y'];
/**
* @type {module:echarts/model/Model}
*/
this.seriesModel = seriesModel;
/**
* Data storage
* @type {Object.<key, Array.<number>>}
* @private
*/
this._storage = {};
/**
* Indices stores the indices of data subset after filtered.
* This data subset will be used by chart.
* @type {Array.<number>}
* @private
*/
this._indices = [];
/**
* 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;
}
var listProto = List.prototype;
/**
* Initialize from data
*/
listProto.initData = function (data) {
// Clear
var optionModels = this._optionModels = [];
var storage = this._storage = {};
var indices = this._indices = [];
var dimensions = this.dimensions;
var size = data.length;
// Init storage
for (var i = 0; i < dimensions.length; i++) {
storage[dimensions[i]] = new Float32Array(size);
}
storage[this.value] = new Float32Array(size);
// Special storage of indices of option model
// It is used for indexing the model in List#_optionModels
var optionModelIndices = storage.$optionModelIndices = new Int32Array(size);
var tempValue = [];
for (var idx = 0; idx < data.length; idx++) {
var value = data[idx];
// Each data item contains value and option
if (data[idx] != null && data[idx].hasOwnProperty('value')) {
value = data[idx].value;
var model = new Model(data[idx], this.seriesModel);
var modelIdx = optionModels.length;
optionModelIndices[idx] = modelIdx;
optionModels.push(model);
}
else {
// Reference to the undefined
optionModelIndices[idx] = -1;
}
// Bar chart, line chart which uses category axis
// only gives the 'y' value. 'x' value is the indices of cateogry
if (typeof (value) === 'number') {
// Use a tempValue to normalize the value to be a (x, y) value
tempValue[0] = idx;
tempValue[1] = value;
value = tempValue;
}
// Store the data by dimensions
for (var k = 0; k < dimensions.length; k++) {
var dim = dimensions[k];
var dimStorage = storage[dim];
var dimValue = value[k];
// PENDING NULL is empty or zero
if (dimValue == null || dimValue === '-') {
dimValue = NaN;
}
dimStorage[idx] = dimValue;
}
indices.push(idx);
}
};
/**
* @return {number}
*/
listProto.count = function () {
return this._indices.length;
};
/**
* Get value
*/
listProto.get = function (dim, idx, stack) {
var storage = this._storage;
var dataIndex = this._indices[idx];
var value = storage[dim] && storage[dim][dataIndex];
if (stack && this.stackedOn) {
var stackedValue = this.stackedOn.get(dim, idx, stack);
// Ignore the empty data
if (!isNaN(stackedValue)) {
if (value >= 0 && stackedValue > 0 // Positive stack
|| (value <= 0 && stackedValue < 0) // Negative stack
) {
value += stackedValue;
}
}
}
return value;
};
/**
* Get raw data index
*/
listProto.getDataIndex = function (idx) {
return this._indices[idx];
};
function normalizeDimensions(dimensions) {
if (typeof (dimensions) === 'number') {
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) {});
* list.each(['x', 'y'], function (x, y) {});
*/
listProto.each = function (dimensions, cb, stack, context) {
dimensions = normalizeDimensions(dimensions);
var value = [];
var dimSize = dimensions.length;
var indices = this._indices;
context = context || this;
for (var i = 0; i < indices.length; i++) {
// Simple optimization
if (dimSize === 1) {
cb && 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);
}
// 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) {
dimensions = normalizeDimensions(dimensions);
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 === 1) {
keep = cb && 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;
return this;
};
/**
* Data mapping
* @param {string|Array.<string>}
* @param {Function} cb
* @param {boolean} [stack=false]
* @param {*} [context=this]
*/
listProto.map = function (dimensions, cb, stack, context) {
var result = [];
this.each(dimensions, function () {
result.push(cb && cb.apply(this, arguments));
}, stack, context);
return result;
};
/**
* Get model of one data item.
* It will create a temporary model if value on idx is not an option.
*/
listProto.getDataModel = function (idx) {
var storage = this._storage;
var optionModelIndices = storage.$optionModelIndices;
var modelIndex = optionModelIndices && optionModelIndices[idx];
var model = this._optionModels[modelIndex];
if (! model) {
// Create a temporary model if value on idx is not an option.
model = new Model(null, this.seriesModel);
}
return model;
};
/**
* Shallow clone a new list.
* New list only change the _indices.
*/
listProto.cloneShallow = function () {
var list = new List(this.dimensions, this.seriesModel);
list.stackedOn = this.stackedOn;
list._storage = this._storage;
list._indices = this._indices.slice();
list._optionModels = this._optionModels;
return list;
};
/**
* Helper function to create a list from option data
*/
List.fromArray = function (data, seriesModel, ecModel) {
var coordinateSystem = seriesModel.get('coordinateSystem');
var dimensions;
var categoryAxisModel;
// FIXME
// 这里 List 跟几个坐标系和坐标系 Model 耦合了
if (coordinateSystem === 'cartesian2d') {
var xAxisModel = ecModel.getComponent('xAxis', seriesModel.get('xAxisIndex'));
var yAxisModel = ecModel.getComponent('yAxis', seriesModel.get('yAxisIndex'));
if (xAxisModel.get('type') === 'category') {
dimensions = ['x', 'y'];
categoryAxisModel = xAxisModel;
}
else if (yAxisModel.get('type') === 'category') {
dimensions = ['y', 'x'];
categoryAxisModel = yAxisModel;
}
else {
// PENDING
var dimSize = data[0] && data[0].length;
if (dimSize === 2) {
dimensions = ['x', 'y'];
}
else if (dimSize === 3) {
dimensions = ['x', 'y', 'z'];
}
}
}
else if (coordinateSystem === 'polar') {
var axisFinder = function (axisModel) {
return axisModel.get('polarIndex') === polarIndex;
}
var polarIndex = seriesModel.get('polarIndex') || 0;
var angleAxisModel = ecModel.findComponent('angleAxis', axisFinder);
var radiusAxisModel = ecModel.findComponent('radiusAxis', axisFinder);
if (angleAxisModel.get('type') === 'category') {
dimensions = ['angle', 'radius'];
categoryAxisModel = angleAxisModel;
}
else if (radiusAxisModel.get('type') === 'category') {
dimensions = ['radius', 'angle'];
categoryAxisModel = radiusAxisModel;
}
else {
// PENDING
var dimSize = data[0] && data[0].length;
if (dimSize === 2) {
dimensions = ['radius', 'angle'];
}
else if (dimSize === 3) {
dimensions = ['radius', 'angle', 'value'];
}
}
}
var list = new List(dimensions, seriesModel);
list.initData(data);
};
return List;
});
\ No newline at end of file
此差异已折叠。
......@@ -121,6 +121,7 @@ define(function (require) {
},
setOption: function (option, notMerge) {
// PENDING
option = zrUtil.clone(option, true);
var ecModel = this._model;
......@@ -332,12 +333,10 @@ define(function (require) {
ecModel.eachSeries(function (series) {
var stack = series.get('stack');
var data = series.getData();
if (stack && data.type === 'list' && data.dimensions.length === 1) {
if (stack && data.type === 'list') {
var previousStack = stackedDataMap[stack];
if (previousStack) {
data.each(function (dataItem, idx) {
dataItem.stackedOn = previousStack.at(idx);
});
data.stackedOn = previousStack;
}
stackedDataMap[stack] = data;
}
......
......@@ -148,19 +148,17 @@ define(function(require) {
if (data.type === 'list') {
var valueAxisStart = valueAxis.getExtent()[0];
var coords = cartesian.dataToPoints(data);
var coords = cartesian.dataToPoints(data, true);
lastStackCoords[stackId] = lastStackCoords[stackId] || [];
data.each(function (dataItem, dataIndex) {
var value = dataItem.getValue(true);
data.each(valueAxis.dim, function (value, idx) {
// 空数据
if (value == null) {
if (isNaN(value)) {
return;
}
var coord = coords[dataIndex];
var lastCoord = lastStackCoords[stackId][dataIndex] || valueAxisStart;
var coord = coords[idx];
var lastCoord = lastStackCoords[stackId][idx] || valueAxisStart;
var x, y, width, height;
if (valueAxis.isHorizontal()) {
x = Math.min(lastCoord, coord[0]);
......@@ -176,15 +174,15 @@ define(function(require) {
height = Math.abs(coord[1] - lastCoord);
lastCoord += coord[1] - lastCoord;
}
lastStackCoords[stackId][dataIndex] = lastCoord;
lastStackCoords[stackId][idx] = lastCoord;
dataItem.layout = {
data.setItemLayout(idx, {
x: x,
y: y,
width: width,
height: height
};
});
});
}, true);
}
}, this);
}
......
define(function (require) {
return function (seriesType, ecModel, api) {
ecModel.eachSeriesByType(seriesType, function (lineSeries) {
var data = lineSeries.getData();
var coords = lineSeries.coordinateSystem.dataToPoints(data);
data.each(function (dataItem, idx) {
var coord = coords[idx];
var value = dataItem.getValue();
var coordSys = lineSeries.coordinateSystem;
if (value != null) {
dataItem.layout = {
x: coord[0],
y: coord[1]
};
var dims = coordSys.type === 'cartesian2d' ? ['x', 'y'] : ['radius', 'angle'];
data.each(dims, function (x, y, idx) {
if (!isNaN(y) && !isNaN(x)) {
var point = coordSys.dataToPoint([x, y]);
data.setItemLayout(idx, point);
}
});
}, true);
});
}
});
\ No newline at end of file
......@@ -30,13 +30,6 @@ define(function (require) {
constructor: Model,
/**
* visual properties after visual coding
* @type {Object}
* @private
*/
_visual: null,
/**
* Model 的初始化函数
* @param {Object} option
......@@ -52,9 +45,10 @@ define(function (require) {
/**
* @param {string} path
* @param {boolean} [ignoreParent=false]
* @return {*}
*/
get: function (path) {
get: function (path, ignoreParent) {
if (! path) {
return this.option;
}
......@@ -70,7 +64,7 @@ define(function (require) {
break;
}
}
if (obj == null && this.parentModel) {
if (obj == null && this.parentModel && !ignoreParent) {
return this.parentModel.get(path);
}
return obj;
......@@ -86,45 +80,6 @@ define(function (require) {
return new Model(obj, parentModel && parentModel.getModel(path));
},
/**
* Get visual property.
*/
getVisual: function (key) {
var visual = this._visual;
var val = visual && visual[key];
var parentModel = this.parentModel;
if (val == null && parentModel) {
return parentModel.getVisual(key);
}
return val;
},
/**
* Set visual property
*
* @example
* setVisual('color', color);
* setVisual({
* 'color': color
* });
*/
setVisual: function (key, val) {
if (typeof (key) === 'object') {
for (var name in key) {
if (key.hasOwnProperty(name)) {
this.setVisual(name, key[name]);
}
}
return;
}
this._visual = this._visual || {};
this._visual[key] = val;
},
clearVisual: function () {
this._visual = null;
},
restoreData: function () {},
// Pending
......
......@@ -53,6 +53,9 @@ define(function(require) {
this._data = this.getInitialData(option, ecModel);
this._dataBeforeProcessing = this._data.cloneShallow();
this._itemVisuals = [];
this._itemLayouts = [];
},
mergeDefaultAndTheme: function (option, ecModel) {
......@@ -77,6 +80,9 @@ define(function(require) {
*/
getInitialData: function () {},
/**
* @return {module:echarts/data/List|module:echarts/data/Graph|module:echarts/data/Tree}
*/
getData: function () {
return this._data;
},
......@@ -87,7 +93,7 @@ define(function(require) {
* @param {module:echarts/model/Model} dataItem
*/
formatTooltipHTML: function (dataItem) {
var value = dataItem.get('value');
var value = dataItem.getRawValue();
var formattedValue = zrUtil.isArray(value)
? zrUtil.map(value, addCommas) : addCommas(value);
......@@ -97,10 +103,6 @@ define(function(require) {
},
restoreData: function () {
// PENDING
// Legend may have wrong symbol if visual is cleared
// this.clearVisual();
this._data = this._dataBeforeProcessing.cloneShallow();
}
});
......
......@@ -3,10 +3,15 @@ define({
backgroundColor: 'rgba(0,0,0,0)',
// 默认色板
color: ['#ff7f50','#87cefa','#da70d6','#32cd32','#6495ed',
'#ff69b4','#ba55d3','#cd5c5c','#ffa500','#40e0d0',
'#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',
'#6699FF','#ff6666','#3cb371','#b8860b','#30e0e0'],
// color: ['#ff7f50','#87cefa','#da70d6','#32cd32','#6495ed',
// '#ff69b4','#ba55d3','#cd5c5c','#ffa500','#40e0d0',
// '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',
// '#6699FF','#ff6666','#3cb371','#b8860b','#30e0e0'],
// https://dribbble.com/shots/1065960-Infographic-Pie-chart-visualization
color: ['#5793f3', '#5578c2', '#d4df5a', '#fd9c35', '#fec42c',
'#dd4444', '#bd3b47', '#bd3b47', '#cd4870'],
// 默认需要 Grid 配置项
grid: {},
......
......@@ -16,7 +16,7 @@ define(function (require) {
* @param {Array.<number>} data
* @constructor
*/
var IntervalScale = function (data) {
var IntervalScale = function () {
/**
* Extent
......@@ -25,10 +25,6 @@ define(function (require) {
*/
this._extent = [Infinity, -Infinity];
if (data) {
this.setExtentFromData(data);
}
/**
* Step is calculated in adjustExtent
* @type {Array.<number>}
......@@ -74,22 +70,12 @@ define(function (require) {
/**
* Set extent from data
* @param {Array.<number>} data
* @param {boolean} union If union with current extent
* @param {Array.<number>} other
*/
setExtentFromData: function (data, union) {
unionExtent: function (other) {
var extent = this._extent;
var max = union ? extent[1] : -Infinity;
var min = union ? extent[0] : Infinity;
for (var i = 0; i < data.length; i++) {
if (data[i] != null) {
data[i] > max && (max = data[i]);
data[i] < min && (min = data[i]);
}
}
this.setExtent(min, max);
other[0] < extent[0] && (extent[0] = other[0]);
other[1] > extent[1] && (extent[1] = other[1]);
},
/**
......
......@@ -10,20 +10,17 @@ define(function (require) {
/**
* @alias module:echarts/coord/scale/Ordinal
* @param {Array} list
* @param {Array} data
* @param {Array.<number>} extent
*/
var OrdinalScale = function (list) {
this._list = [];
var OrdinalScale = function (data, extent) {
this._data = data;
/**
* Extent of ordianl is the extent of rank
* Default is 0...len(list)-1
* Extent of ordinal is the extent of rank
* Default is 0...len(data)-1
* @type {Array.<number>}
*/
this._extent = [0, 0];
if (list) {
this.setExtentFromData(list);
}
this._extent = extent || [0, data.length - 1];
};
OrdinalScale.prototype = {
......@@ -38,7 +35,7 @@ define(function (require) {
*/
contain: function (rank) {
var extent = this._extent;
return rank >= extent[0] && rank <= extent[1] && this._list[rank] != null;
return rank >= extent[0] && rank <= extent[1] && this._data[rank] != null;
},
/**
......@@ -66,10 +63,14 @@ define(function (require) {
/**
* Set extent from data
* @param {Array.<number>} other
*/
setExtentFromData: function (list) {
this._list = list;
this._extent = [0, list.length - 1];
unionExtent: function (other) {
var extent = this._extent;
other[0] < extent[0] && (extent[0] = other[0]);
other[1] > extent[1] && (extent[1] = other[1]);
this.setExtent(extent[0], extent[1]);
},
/**
......@@ -81,14 +82,18 @@ define(function (require) {
},
/**
* Set extent. Given extent will intersect with default extent 0...len(list)-1
* Set extent. Given extent will intersect with default extent 0...len(data)-1
* @param {number} start
* @param {number} end
*/
setExtent: function (start, end) {
var thisExtent = this._extent;
thisExtent[0] = Math.max(start, 0);
thisExtent[1] = Math.min(end, this._list.length - 1);
if (start != null) {
thisExtent[0] = Math.max(start, 0);
}
if (end != null) {
thisExtent[1] = Math.min(end, this._data.length - 1);
}
},
/**
......@@ -116,7 +121,7 @@ define(function (require) {
var rank = extent[0];
while (rank <= extent[1]) {
labels.push(this._list[rank]);
labels.push(this._data[rank]);
rank++;
}
return labels;
......@@ -133,7 +138,7 @@ define(function (require) {
* Get item on rank n
*/
getLabel: function (n) {
return this._list[n];
return this._data[n];
},
// Do nothing
......
......@@ -28,7 +28,7 @@ define(function (require) {
render: function (seriesModel, ecModel, api) {},
remove: function () {
this.group.clear();
this.group.removeAll();
},
dispose: function () {}
......
......@@ -3,9 +3,8 @@ define(function (require) {
return function (ecModel) {
ecModel.eachSeries(function (seriesModel) {
var colorList = ecModel.get('color');
seriesModel.setVisual(
'color', colorList[seriesModel.seriesIndex]
);
var data = seriesModel.getData();
data.setVisual('color', colorList[seriesModel.seriesIndex]);
});
}
});
\ No newline at end of file
define(function (require) {
return function (seriesType, defaultSymbolType, legendSymbol, ecModel, api) {
ecModel.eachSeriesByType(seriesType, function (scatterSeries) {
var symbolType = scatterSeries.get('symbol') || defaultSymbolType;
var symbolSize = scatterSeries.get('symbolSize');
scatterSeries.setVisual({
ecModel.eachSeriesByType(seriesType, function (seriesModel) {
var data = seriesModel.getData();
var symbolType = seriesModel.get('symbol') || defaultSymbolType;
var symbolSize = seriesModel.get('symbolSize');
data.setVisual({
legendSymbol: legendSymbol || symbolType,
symbol: symbolType,
symbolSize: symbolSize
});
var data = scatterSeries.getData();
data.each(function (dataItem) {
var symbolType = dataItem.get('symbol');
var symbolSize = dataItem.get('symbolSize');
if (typeof symbolSize === 'function') {
var rawValue = dataItem.get('value');
dataItem.setVisual({
symbol: symbolType,
symbolSize: symbolSize(rawValue)
});
}
else if (symbolType && symbolType !== 'none') {
dataItem.setVisual({
symbol: symbolType,
symbolSize: symbolSize
});
if (typeof symbolSize === 'function') {
data.each(function (idx) {
var rawValue = data.getRawValue(idx);
data.setItemVisual(idx, 'symbolSize', symbolSize(rawValue))
});
}
data.each(function (idx) {
var itemModel = data.getItemModel(idx);
var symbolType = itemModel.get('symbol', true);
var symbolSize = itemModel.get('symbolSize', true);
if (symbolType != null && symbolType !== 'none') {
data.setItemVisual(idx, 'symbol', symbolType);
if (symbolSize != null) {
data.setItemVisual(idx, 'symbolSize', symbolSize);
}
}
});
});
......
......@@ -10,7 +10,7 @@ describe('List', function () {
function testCase(name, doTest) {
it(name, function (done) {
window.require(['echarts/data/LargeList'], function () {
window.require(['echarts/data/List'], function () {
doTest.apply(null, arguments);
done();
});
......@@ -46,8 +46,8 @@ describe('List', function () {
value: 2,
somProp: 'foo'
}]);
expect(list.getDataModel(1).get('somProp')).toEqual('foo');
expect(list.getDataModel(0).get('somProp')).toBeNull();
expect(list.getItemModel(1).get('somProp')).toEqual('foo');
expect(list.getItemModel(0).get('somProp')).toBeNull();
});
testCase('Empty data', function (List) {
......@@ -69,6 +69,39 @@ describe('List', function () {
expect(list2.get('y', 3, true)).toEqual(2);
});
testCase('getRawValue', function (List) {
var list = new List(['x', 'y']);
list.initData([1, 2, 3]);
expect(list.getRawValue(1)).toEqual(2);
list.initData([[10, 15], [20, 25], [30, 35]]);
expect(list.getRawValue(1)).toEqual([20, 25]);
});
testCase('getDataExtent', function (List) {
var list = new List(['x', 'y']);
list.initData([1, 2, 3]);
expect(list.getDataExtent('x')).toEqual([0, 2]);
expect(list.getDataExtent('y')).toEqual([1, 3]);
});
testCase('Data types', function (List) {
var list = new List([{
name: 'name',
type: 'string'
}, {
name: 'x',
type: 'int'
}, {
name: 'y',
type: 'float'
}]);
list.initData([['foo', 1.1, 1.1]]);
expect(list.get('name', 0)).toEqual('foo');
expect(list.get('x', 0)).toEqual(1);
expect(list.get('y', 0)).toBeCloseTo(1.1, 5);
});
testCase('map', function (List) {
var list = new List(['x', 'y']);
list.initData([[10, 15], [20, 25], [30, 35]]);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册