提交 e24dba70 编写于 作者: P pah100

udpate datazoom, list, action

上级 da4fed1f
......@@ -5,7 +5,7 @@ define(function(require) {
var zrUtil = require('zrender/core/util');
var echartsAPIList = [
'getZr', 'update', 'getCoordinateSystem', 'getWidth', 'getHeight'
'getZr', 'getCoordinateSystem', 'getWidth', 'getHeight', 'dispatch'
];
function ExtensionAPI(echarts) {
......
......@@ -19,7 +19,7 @@ define(function (require) {
var data = seriesModel.getData();
data.diff(this._data)
.add(function (dataItem, idx) {
.add(function (dataItem, dataIndex) {
// 空数据
if (dataItem.getValue() == null) {
return;
......@@ -48,7 +48,7 @@ define(function (require) {
// Animation
rect.animateTo({
shape: layout
}, 1000, 300 * dataItem.dataIndex / data.elements.length, 'cubicOut');
}, 1000, 300 * dataIndex / data.count(), 'cubicOut');
})
.update(function (newData, oldData) {
var el = oldData.__el;
......
......@@ -66,11 +66,13 @@ define(function(require) {
this._polyline = polyline;
}
else {
this._polyline.animateShape()
.when(500, {
points: points
})
.start('cubicOut');
// this._polyline.animateShape()
// .when(500, {
// points: points
// })
// .start('cubicOut');
this._polyline.shape.points = points;
this._polyline.dirty(true);
}
this._data = data;
......
......@@ -5,6 +5,7 @@ define(function (require) {
ecModel.eachSeriesByType('line', function (lineSeries) {
var data = lineSeries.getData();
var coords = lineSeries.coordinateSystem.dataToCoords(data);
data.each(function (dataItem, idx) {
var coord = coords[idx];
var value = dataItem.getValue();
......
......@@ -92,9 +92,7 @@ define(function(require) {
p1[0] = p2[0] = this._axisLinePosition;
}
api.subPixelOptimizeLine(p1, p2, lineWidth);
this.group.add(new api.Line({
this.group.add(new api.Line(api.subPixelOptimizeLine({
shape: {
x1: p1[0],
y1: p1[1],
......@@ -106,7 +104,7 @@ define(function(require) {
}, lineStyleModel.getLineStyle()),
z: axisModel.get('z'),
silent: true
}));
})));
},
/**
......@@ -144,7 +142,7 @@ define(function(require) {
|| i % (tickInterval + 1)
)
) {
continue
continue;
}
var tickCoord = ticksCoords[i];
......@@ -173,16 +171,18 @@ define(function(require) {
var p1 = [x, y];
var p2 = [x + offX, y + offY];
api.subPixelOptimizeLine(p1, p2, tickLineWidth);
// Tick line
tickLines.push(new api.Line({
tickLines.push(new api.Line(api.subPixelOptimizeLine({
shape: {
x1: p1[0],
y1: p1[1],
x2: p2[0],
y2: p2[1]
},
style: {
lineWidth: tickLineWidth
}
}));
})));
}
var tickEl = api.mergePath(tickLines, {
style: lineStyleModel.getLineStyle(),
......@@ -218,7 +218,7 @@ define(function(require) {
var labels;
if (axis.scale.type === 'ordinal') {
labels = zrUtil.map(ticks, zrUtil.bind(axis.scale.getItem, axis.scale));
labels = zrUtil.map(ticks, axis.scale.getItem, axis.scale);
}
else {
labels = ticks.slice();
......@@ -229,8 +229,8 @@ define(function(require) {
for (var i = 0; i < ticks.length; i++) {
// Default is false
showList[i] = false;
needsCheckTextSpace = false;
var tick = ticks[i];
// Only ordinal scale support label interval
if (axis.scale.type === 'ordinal') {
......@@ -239,14 +239,14 @@ define(function(require) {
}
if (isLabelIntervalFunction
&& !labelInterval(tick, axis.scale.getItem(tick))
|| tick % (labelInterval + 1)) {
|| tick % (labelInterval + 1)
) {
continue;
}
}
var x;
var y;
var tick = ticks[i];
var tickCoord = axis.dataToCoord(tick);
var labelTextAlign = 'center';
var labelTextBaseline = 'middle';
......@@ -353,18 +353,20 @@ define(function(require) {
p2[0] = gridRect.x + gridRect.width;
p2[1] = tickCoord;
}
api.subPixelOptimizeLine(p1, p2, lineWidth);
var colorIndex = (lineCount++) % lineColors.length;
splitLines[colorIndex] = splitLines[colorIndex] || [];
splitLines[colorIndex].push(new api.Line({
splitLines[colorIndex].push(new api.Line(api.subPixelOptimizeLine({
shape: {
x1: p1[0],
y1: p1[1],
x2: p2[0],
y2: p2[1]
},
style: {
lineWidth: lineWidth
}
}));
})));
}
// Simple optimization
......
......@@ -6,5 +6,6 @@ define(function (require) {
require('./dataZoom/DataZoomModel');
require('./dataZoom/DataZoomView');
require('./dataZoom/dataZoomProcessor');
require('./dataZoom/dataZoomAction');
});
\ No newline at end of file
define(function (require) {
var zrUtil = require('zrender/core/util');
var helper = require('./helper');
var retrieveValue = helper.retrieveValue;
var linearMap = require('../../util/number').linearMap;
var round = Math.round;
// Constants
var DEFAULT_LOCATION_EDGE_GAP = 2;
var DEFAULT_FILLER_SIZE = 30;
function DataZoomLayout(dataZoomModel, ecModel, api) {
/**
* @readOnly
*/
this.dataZoomModel = dataZoomModel;
/**
* @readOnly
*/
this.ecModel = ecModel;
/**
* @readOnly
*/
this.api = api;
/**
* @private
*/
this._orient = dataZoomModel.get('orient');
/**
* @readOnly
* @type {Object}
*/
this.layout = {
viewRange: {
// handle1 may less than handle2,
// so we dont naming them as 'start', 'end'
handle1: null,
handle2: null
},
/**
* {
* x: {number},
* y: {number},
* width: {number},
* height: {number}
* }
* @type {Object}
*/
location: {},
filler: {
shape: {}
},
startHandle: {
shape: {}
},
endHandle: {
shape: {}
},
startFrame: {
shape: {}
},
endFrame: {
shape: {}
}
};
}
DataZoomLayout.prototype = {
constructor: DataZoomLayout,
/**
* @public
*/
reset: function () {
this._initLocation();
this._initViewRange();
this.update();
},
/**
* @public
* @param {Object} dataZoomModel
* @param {Object} operation If empty, just re-calculate layout.
* @param {string} [operation.rangeArgs] ['start'] or ['end'] or ['start', 'end']
* @param {number} [operation.dx]
* @param {number} [operation.dy]
*/
update: function (operation) {
operation && this._updateViewRange(operation);
this._orient === 'horizontal'
? this._updateWidgetsLayoutHorizontally()
: this._updateWidgetsLayoutVertically();
},
/**
* @public
* @return {Object} {start, end}
*/
normalizeToRange: function () {
var viewRange = this.layout.viewRange;
var viewExtend = [0, this._getViewTotalLength()];
var percentExtent = [0, 100];
var range = {
start: linearMap(viewRange.handle1, viewExtend, percentExtent, true),
end: linearMap(viewRange.handle2, viewExtend, percentExtent, true)
};
// Auto exchange
if (range.start > range.end) {
range.start = [range.end, range.end = range.start][0];
}
return range;
},
/**
* @private
*/
_initLocation: function () {
var dataZoomModel = this.dataZoomModel;
var x;
var y;
var width;
var height;
// If some of x/y/width/height are not specified, auto-adapt according to target grid.
var gridRect = this._findGridRectForLocating();
if (this._orient === 'horizontal') { // Horizontal layout
width = retrieveValue(dataZoomModel.get('width'), gridRect.width);
height = retrieveValue(dataZoomModel.get('height'), DEFAULT_FILLER_SIZE);
x = retrieveValue(dataZoomModel.get('x'), gridRect.x);
y = retrieveValue(
dataZoomModel.get('y'),
(this.api.getHeight() - height - DEFAULT_LOCATION_EDGE_GAP)
);
}
else { // Vertical layout
width = retrieveValue(dataZoomModel.get('width'), DEFAULT_FILLER_SIZE);
height = retrieveValue(dataZoomModel.get('height'), gridRect.height);
x = retrieveValue(dataZoomModel.get('x'), DEFAULT_LOCATION_EDGE_GAP);
y = retrieveValue(dataZoomModel.get('y'), gridRect.y);
}
this.layout.location = {
x: x, y: y, width: width, height: height
};
},
/**
* @private
*/
_findGridRectForLocating: function () {
// Find the grid coresponding to the first axis referred by dataZoom.
var axisModel;
var dataZoomModel = this.dataZoomModel;
var ecModel = this.ecModel;
helper.eachAxisDim(function (dimNames) {
var axisIndices = dataZoomModel.get(dimNames.axisIndex);
if (!axisModel && axisIndices.length) {
axisModel = ecModel.getComponent(dimNames.axis, axisIndices[0]);
}
});
return ecModel
.getComponent('grid', axisModel.get('gridIndex'))
.coordinateSystem
.getRect();
},
/**
* @private
*/
_initViewRange: function () {
// Based on layout.location.
var range = this.dataZoomModel.getRange();
var viewExtend = [0, this._getViewTotalLength()];
var percentExtent = [0, 100];
this.layout.viewRange = {
handle1: round(linearMap(range.start, percentExtent, viewExtend, true)),
handle2: round(linearMap(range.end, percentExtent, viewExtend, true))
};
},
/**
* @private
* @param {Object} dataZoomModel
* @param {Object} operation
* @param {string} [operation.rangeArgs] ['handle1'] or ['handle2'] or ['handle1', 'handle2']
* @param {number} [operation.dx]
* @param {number} [operation.dy]
*/
_updateViewRange: function (operation) {
var delta = retrieveValue(
this._orient === 'horizontal' ? operation.dx : operation.dy,
0
);
var standardValue = delta > 0 ? Number.MIN_VALUE : Number.MAX_VALUE;
var methods = ['min', 'max'];
var methodIndex = delta > 0 ? 1 : 0;
var edgeValue = delta > 0 ? this._getViewTotalLength() : 0;
zrUtil.each(operation.rangeArgs, function (rangeArg) {
var value = this.layout.viewRange[rangeArg];
standardValue = Math[methods[methodIndex]](standardValue, value);
}, this);
var standardValueResult = Math[methods[1 - methodIndex]](standardValue + delta, edgeValue);
delta = standardValueResult - standardValue;
zrUtil.each(operation.rangeArgs, function (rangeArg) {
this.layout.viewRange[rangeArg] += delta;
}, this);
},
/**
* @private
*/
_getViewTotalLength: function () {
var location = this.layout.location;
return this._orient === 'horizontal' ? location.width : location.height;
},
/**
* @private
*/
_updateWidgetsLayoutHorizontally: function () {
// Based on layout.viewRange and this.layout.location.
var dataZoomModel = this.dataZoomModel;
var layout = this.layout;
var location = layout.location;
var handleSize = dataZoomModel.get('handleSize');
var viewRange = layout.viewRange;
var viewRangeStart = Math.min(viewRange.handle1, viewRange.handle2);
var viewRangeEnd = Math.max(viewRange.handle1, viewRange.handle2);
var fillerStyle = layout.filler.shape = {
x: location.x + viewRangeStart + handleSize,
y: location.y,
width: viewRangeEnd - viewRangeStart - handleSize * 2,
height: location.height
};
var handleBase = {
shape: {
y: location.y,
width: handleSize,
height: location.height
}
};
var handles = [
zrUtil.merge(
{
shape: {x: fillerStyle.x - handleSize}
},
handleBase
),
zrUtil.merge(
{
shape: {x: fillerStyle.x + fillerStyle.width}
},
handleBase
)
];
var handle1Index = viewRange.handle1 > viewRange.handle2 ? 1 : 0;
layout.handle1 = handles[handle1Index];
layout.handle2 = handles[1 - handle1Index];
var startHandleShape = handles[0].shape;
var endHandleShape = handles[1].shape;
layout.startFrame = {
shape: {
x: location.x,
y: location.y,
width: startHandleShape.x - location.x,
height: location.height
}
};
layout.endFrame = {
shape: {
x: endHandleShape.x + endHandleShape.width,
y: location.y,
width: location.x + location.width
- (endHandleShape.x + endHandleShape.width),
height: location.height
}
};
},
/**
* @private
*/
_updateWidgetsLayoutVertically: function () {
// Based on layout.viewRange and this.layout.location.
var dataZoomModel = this.dataZoomModel;
var layout = this.layout;
var location = layout.location;
var handleSize = dataZoomModel.get('handleSize');
var viewRange = layout.viewRange;
var viewRangeStart = Math.min(viewRange.handle1, viewRange.handle2);
var viewRangeEnd = Math.max(viewRange.handle1, viewRange.handle2);
var fillerStyle = layout.filler.shape = {
x: location.x,
y: location.y + viewRangeStart + handleSize,
width: location.width,
height: viewRangeEnd - viewRangeStart - handleSize * 2
};
var handleBase = {
shape: {
x: location.x,
width: location.width,
height: handleSize
}
};
var handles = [
zrUtil.merge(
{
shape: {y: fillerStyle.y - handleSize}
},
handleBase
),
layout.endHandle = zrUtil.merge(
{
shape: {y: fillerStyle.y + fillerStyle.height}
},
handleBase
)
];
var handle1Index = viewRange.handle1 > viewRange.handle2 ? 1 : 0;
layout.handle1 = handles[handle1Index];
layout.handle2 = handles[1 - handle1Index];
var startHandleShape = handles[0].shape;
var endHandleShape = handles[1].shape;
layout.startFrame = {
shape: {
x: location.x,
y: location.y,
width: location.width,
height: startHandleShape.y - location.y
}
};
layout.endFrame = {
shape: {
x: location.x,
y: endHandleShape.y + endHandleShape.height,
width: location.width,
height: location.y + location.height
- (endHandleShape.y + endHandleShape.height)
}
};
}
};
return DataZoomLayout;
});
\ No newline at end of file
......@@ -14,12 +14,43 @@ define(function(require) {
dependencies: ['xAxis', 'yAxis', 'series'],
/**
* @protected
*/
defaultOption: {
zlevel: 0, // 一级层叠
z: 4, // 二级层叠
show: false,
orient: 'horizontal', // 布局方式,默认为水平布局,可选为:
// 'horizontal' ¦ 'vertical'
// x: {number}, // 水平安放位置,默认为根据grid参数适配,可选为:
// {number}(x坐标,单位px)
// y: {number}, // 垂直安放位置,默认为根据grid参数适配,可选为:
// {number}(y坐标,单位px)
// width: {number}, // 指定宽度,横向布局时默认为根据grid参数适配
// height: {number}, // 指定高度,纵向布局时默认为根据grid参数适配
backgroundColor: 'rgba(0,0,0,0)', // 背景颜色
dataBackgroundColor: '#eee', // 数据背景颜色
fillerColor: 'rgba(144,197,237,0.2)', // 填充颜色
handleColor: 'rgba(70,130,180,0.8)', // 手柄颜色
handleSize: 10,
showDetail: true,
// xAxisIndex: [], // 默认控制所有横向类目
// yAxisIndex: [], // 默认控制所有横向类目
start: 0, // 默认为0
end: 100, // 默认为全部 100%
start2: 0, // 默认为0
end2: 100, // 默认为全部 100%
realtime: true
// zoomLock: false // 是否锁定选择区域大小
},
/**
* @override
*/
init: function (option, parentModel, ecModel) {
this.mergeDefaultAndTheme(option, ecModel);
this.mergeOption();
this.mergeOption({});
},
/**
......@@ -48,12 +79,12 @@ define(function(require) {
var thisOption = this.option;
var noAxisDefined = true;
helper.eachAxisDim(function (names) {
helper.eachAxisDim(function (dimNames) {
// Overlap these arrays but not merge.
var axisIndices = helper.toArray(helper.retrieveValue(
newOption[names.axisIndex], thisOption[names.axisIndex], []
newOption[dimNames.axisIndex], thisOption[dimNames.axisIndex], []
));
var axisModels = this.dependentModels[names.axis];
var axisModels = this.dependentModels[dimNames.axis];
// If not specified, set default.
if (axisModels.length && !axisIndices.length) {
......@@ -63,7 +94,7 @@ define(function(require) {
}
}
}
thisOption[names.axisIndex] = axisIndices;
thisOption[dimNames.axisIndex] = axisIndices;
if (axisIndices.length) {
noAxisDefined = false;
......@@ -80,9 +111,9 @@ define(function(require) {
// both xAxis and yAxis which type is 'value'.
this.ecModel.eachSeries(function (seriesModel) {
if (this._isSeriesHasAllAxesTypeOf(seriesModel, 'value')) {
helper.eachAxisDim(function (names) {
var axisIndices = thisOption[names.axisIndex];
var axisIndex = seriesModel.get(names.axisIndex);
helper.eachAxisDim(function (dimNames) {
var axisIndices = thisOption[dimNames.axisIndex];
var axisIndex = seriesModel.get(dimNames.axisIndex);
if (zrUtil.indexOf(axisIndices, axisIndex) < 0) {
axisIndices.push(axisIndex);
}
......@@ -98,9 +129,9 @@ define(function(require) {
// 例如series.type === scatter时。
var is = true;
helper.eachAxisDim(function (names) {
var seriesAxisIndex = seriesModel.get(names.axisIndex);
var axisModel = this.dependentModels[names.axis][seriesAxisIndex];
helper.eachAxisDim(function (dimNames) {
var seriesAxisIndex = seriesModel.get(dimNames.axisIndex);
var axisModel = this.dependentModels[dimNames.axis][seriesAxisIndex];
if (!axisModel || axisModel.get('type') !== axisType) {
is = false;
......@@ -122,9 +153,9 @@ define(function(require) {
// When only xAxisIndex or only yAxisIndex is specified, start/end controls them.
// targetDim === false means that both xAxisIndex and yAxisIndex are specified.
var targetDim;
helper.eachAxisDim(function (names) {
if (thisOption[names.axisIndex].length) {
targetDim = targetDim !== false ? false : names.dim;
helper.eachAxisDim(function (dimNames) {
if (thisOption[dimNames.axisIndex].length) {
targetDim = targetDim !== false ? false : dimNames.dim;
}
});
......@@ -136,7 +167,7 @@ define(function(require) {
targetDim2 = targetDim === 'x' ? 'y' : 'x';
}
var optAttrs = [];
var optAttrs = {};
optAttrs[targetDim] = {start: 'start', end: 'end'};
targetDim2 && (optAttrs[targetDim2] = {start: 'start2', end: 'end2'});
......@@ -156,13 +187,45 @@ define(function(require) {
});
thisOption[dimItem.start] = startValue;
thisOption[dimItem.end] = endValue;
});
}, this);
if (!targetDim2) {
thisOption.start2 = thisOption.end2 = null;
}
},
/**
* @public
* @param {Function} callback param: axisModel, dimNames, axisIndex, dataZoomModel, ecModel
*/
eachTargetAxis: function (callback, context) {
var ecModel = this.ecModel;
helper.eachAxisDim(function (dimNames) {
zrUtil.each(
this.get(dimNames.axisIndex),
function (axisIndex) {
callback.call(context, dimNames, axisIndex, this, ecModel);
},
this
);
}, this);
},
/**
* @public
* @param {string} dimName 'x', 'y', 'z'
* @param {number} axisIndex
*/
getTargetSeriesModels: function (dimName, axisIndex) {
var seriesModels = [];
this.ecModel.eachSeries(function (seriesModel) {
if (axisIndex === seriesModel.get(dimName + 'AxisIndex')) {
seriesModels.push(seriesModel);
}
});
return seriesModels;
},
/**
* @public
* @param {Object} param
......@@ -193,37 +256,6 @@ define(function(require) {
star2: thisOption.star2,
end2: thisOption.end2
};
},
/**
* @protected
*/
defaultOption: {
zlevel: 0, // 一级层叠
z: 4, // 二级层叠
show: false,
orient: 'horizontal', // 布局方式,默认为水平布局,可选为:
// 'horizontal' ¦ 'vertical'
// x: {number}, // 水平安放位置,默认为根据grid参数适配,可选为:
// {number}(x坐标,单位px)
// y: {number}, // 垂直安放位置,默认为根据grid参数适配,可选为:
// {number}(y坐标,单位px)
// width: {number}, // 指定宽度,横向布局时默认为根据grid参数适配
// height: {number}, // 指定高度,纵向布局时默认为根据grid参数适配
backgroundColor: 'rgba(0,0,0,0)', // 背景颜色
dataBackgroundColor: '#eee', // 数据背景颜色
fillerColor: 'rgba(144,197,237,0.2)', // 填充颜色
handleColor: 'rgba(70,130,180,0.8)', // 手柄颜色
handleSize: 8,
showDetail: true,
// xAxisIndex: [], // 默认控制所有横向类目
// yAxisIndex: [], // 默认控制所有横向类目
start: 0, // 默认为0
end: 100, // 默认为全部 100%
start2: 0, // 默认为0
end2: 100, // 默认为全部 100%
realtime: true
// zoomLock: false // 是否锁定选择区域大小
}
});
......
......@@ -2,19 +2,35 @@ define(function (require) {
var echarts = require('../../echarts');
var zrUtil = require('zrender/core/util');
var helper = require('./helper');
var retrieveValue = helper.retrieveValue;
var DataZoomLayout = require('./DataZoomLayout');
var graphic = require('../../util/graphic');
// Constants
var DEFAULT_LOCATION_EDGE_GAP = 2;
var DEFAULT_FILLER_SIZE = 30;
var DEFAULT_FRAME_BORDER_WIDTH = 1;
var DEFAULT_HANDLE_INNER_COLOR = '#fff';
return echarts.extendComponentView({
type: 'dataZoom',
init: function (echarts) {
this._location;
/**
* @private
* @type {Object}
*/
this._updatableShapes = {};
/**
* @private
* @type {module:echarts/component/dataZoom/DataZoomLayout}
*/
this._layout;
/**
* @private
* @type {string}
*/
this._orient;
},
render: function (dataZoomModel, ecModel, api, event) {
......@@ -22,9 +38,10 @@ define(function (require) {
// 需要区别用户事件在本component上触发的render和其他render。
// 后者不重新构造shape。否则难于实现拖拽。
this._dataZoomModel = dataZoomModel;
this._ecModel = ecModel;
this._api = api;
this.dataZoomModel = dataZoomModel;
this.ecModel = ecModel;
this.api = api;
this._orient = dataZoomModel.get('orient');
if (!event || event.type !== 'dataZoom' || event.from !== this.uid) {
......@@ -35,288 +52,198 @@ define(function (require) {
}
// Layout
this._updateLocation();
this._updateSliderRange({init: true});
this._updateWidgetSize();
this._layout = new DataZoomLayout(dataZoomModel, ecModel, api);
this._layout.reset();
// Render
this._renderBackground();
this._renderDataShadow();
this._renderFrame();
this._renderFiller();
this._renderHandle();
}
},
/**
* 根据选项计算实体的位置坐标
*/
_updateLocation: function () {
var dataZoomModel = this._dataZoomModel;
var x;
var y;
var width;
var height;
// If some of x/y/width/height are not specified, auto-adapt according to target grid.
var gridRect = this._findGridRectForLocating();
if (this._orient === 'horizontal') { // Horizontal layout
width = retrieveValue(dataZoomModel.get('width'), gridRect.width);
height = retrieveValue(dataZoomModel.get('height'), DEFAULT_FILLER_SIZE);
x = retrieveValue(dataZoomModel.get('x'), gridRect.x);
y = retrieveValue(
dataZoomModel.get('y'), (api.getHeight() - height - DEFAULT_LOCATION_EDGE_GAP)
);
}
else { // Vertical layout
width = retrieveValue(dataZoomModel.get('width'), DEFAULT_FILLER_SIZE);
height = retrieveValue(dataZoomModel.get('height'), gridRect.height);
x = retrieveValue(dataZoomModel.get('x'), DEFAULT_LOCATION_EDGE_GAP);
y = retrieveValue(dataZoomModel.get('y'), gridRect.y);
}
this._location = {
x: x, y: y, width: width, height: height
};
},
/**
* @private
* @param {Object} dataZoomModel
* @param {Object} operation
* @param {boolean} [operation.init]
* @param {string} [operation.rangeArg] 'start' or 'end'
* @param {number} [operation.dx]
* @param {number} [operation.dy]
*/
_updateSliderRange: function (operation) {
// Based on this._location.
if (operation.init) {
var dataZoomModel = this._dataZoomModel;
var range = dataZoomModel.getRange();
var sliderTotalLength = this._getSliderTotalLength();
this._sliderRange = {
start: Math.round(range.start * 100 / sliderTotalLength),
end: Math.round(range.end * 100 / sliderTotalLength)
};
}
if (operation.rangeArg) {
this._sliderRange[operation.rangeArg] += this._getSliderDelta(operation);
}
},
_getSliderTotalLength: function () {
var location = this._location;
return this._orient === 'horizontal' ? location.width : location.height;
},
_getSliderDelta: function (operation) {
return retrieveValue(
this._orient === 'horizontal' ? operation.dx : operation.dy,
0
);
},
_normalizeToRange: function () {
var sliderTotalLength = this._getSliderTotalLength();
var sliderRange = this._sliderRange;
return {
start: sliderRange.start / sliderTotalLength * 100,
end: sliderRange.end / sliderTotalLength * 100
};
},
_updateWidgetSize: function () {
// Based on this._sliderRange and this._location.
var dataZoomModel = this._dataZoomModel;
var sliderRange = this._sliderRange;
var location = this._location;
var handleSize = dataZoomModel.get('handleSize');
var widgetSize = this._widgetSize = {};
if (dataZoomModel.get('orient') === 'horizontal') {
widgetSize.filler = {
x: location.x + sliderRange.start + handleSize,
y: location.y,
width: sliderRange.end - sliderRange.start - handleSize * 2,
height: location.height
};
}
else { // 'vertical'
widgetSize.filler = {
x: location.x,
y: location.y + sliderRange.start + handleSize,
width: location.width,
height: sliderRange.end - sliderRange.start - handleSize * 2
};
}
},
_findGridRectForLocating: function () {
// Find the grid coresponding to the first axis referred by dataZoom.
var axisModel;
var dataZoomModel = this._dataZoomModel;
var ecModel = this._ecModel;
helper.eachAxisDim(function (dimNames) {
var axisIndices = dataZoomModel.get(dimNames.axisIndex);
if (!axisModel && axisIndices.length) {
axisModel = ecModel.get(dimNames.axis)[axisIndices[0]];
}
});
return ecModel.getComponent('grid', axisModel.get('gridIndex')).getRect();
},
_renderBackground : function () {
var dataZoomModel = this._dataZoomModel;
var location = this._location;
var dataZoomModel = this.dataZoomModel;
var location = this._layout.layout.location;
this.group.push(new api.Rect({
this.group.add(new this.api.Rect({
// FIXME
// zlevel: this.getZlevelBase(),
// z: this.getZBase(),
hoverable:false,
style: {
shape: {
x: location.x,
y: location.y,
width: location.width,
height: location.height,
color: dataZoomModel.get('backgroundColor')
height: location.height
},
style: {
fill: dataZoomModel.get('backgroundColor')
}
}));
},
_renderFrame: function () {
var updatableShapes = this._updatableShapes;
var layout = this._layout.layout;
var baseFrame = {
// FIXME
// zlevel: this.getZlevelBase(),
// z: this.getZBase(),
hoverable: false,
style: {
stroke: this.dataZoomModel.get('handleColor'),
lineWidth: DEFAULT_FRAME_BORDER_WIDTH,
fill: 'rgba(0,0,0,0)'
}
};
this.group
.add(updatableShapes.startFrame = new this.api.Rect(zrUtil.mergeAll(
{},
baseFrame,
layout.startFrame
)))
.add(updatableShapes.endFrame = new this.api.Rect(zrUtil.mergeAll(
{},
baseFrame,
layout.endFrame
)));
},
_renderDataShadow: function () {
// Data shadow
// TODO
},
_renderFiller: function () {
var dataZoomModel = this._dataZoomModel;
var orient = dataZoomModel.get('orient');
this._fillerShape = new api.Rect({
// FIXME
// zlevel: this.getZlevelBase(),
// z: this.getZBase(),
draggable: true,
ondrift: zrUtil.bind(this._onDrift, this, 'both'),
ondragend: zrUtil.bind(this._onDragEnd, this),
style: zrUtil.merge(
this.group.add(
this._updatableShapes.filler = new this.api.Rect(zrUtil.merge(
{
color: dataZoomModel.get('fillerColor'),
text: orient === 'horizontal' ? ':::' : '::',
textPosition : 'inside'
// FIXME
// zlevel: this.getZlevelBase(),
// z: this.getZBase(),
draggable: this._orient,
drift: zrUtil.bind(this._onDrift, this, this._getUpdateArgs()),
ondragend: zrUtil.bind(this._onDragEnd, this),
style: {
fill: this.dataZoomModel.get('fillerColor'),
text: this._orient === 'horizontal' ? ':::' : '::',
textPosition : 'inside'
}
// FIXME
// highlightStyle: {
// brushType: 'fill',
// color: 'rgba(0,0,0,0)'
// }
},
this._widgetSize
),
highlightStyle: {
brushType: 'fill',
color: 'rgba(0,0,0,0)'
}
});
this.group.push(this._fillerShape);
this._layout.layout.filler
))
);
},
_renderHandle : function () {
var detail = this.zoomOption.showDetail ? this._getDetail() : {start: '',end: ''};
this._startShape = {
zlevel: this.getZlevelBase(),
z: this.getZBase(),
draggable : true,
style : {
iconType: 'rectangle',
x: this._location.x,
y: this._location.y,
width: this._handleSize,
height: this._handleSize,
color: this.zoomOption.handleColor,
_renderHandle: function () {
var dataZoomModel = this.dataZoomModel;
var layout = this._layout.layout;
var updatableShapes = this._updatableShapes;
// FIXME
// var detailInfo = this.zoomOption.showDetail ? this._getDetail() : {start: '',end: ''};
var baseHandle = {
// FIXME
// zlevel: this.getZlevelBase(),
// z: this.getZBase(),
draggable: this._orient,
style: {
fill: dataZoomModel.get('handleColor'),
textColor: DEFAULT_HANDLE_INNER_COLOR,
text: '=',
textPosition: 'inside'
},
highlightStyle: {
text: detail.start,
brushType: 'fill',
textPosition: 'left'
},
ondrift: this._ondrift,
ondragend: this._ondragend
}
// FIXME
// highlightStyle: {
// text: detail.start,
// brushType: 'fill',
// textPosition: 'left'
// },
};
if (this.zoomOption.orient === 'horizontal') {
this._startShape.style.height = this._location.height;
this._endShape = zrUtil.clone(this._startShape);
this.group
.add(updatableShapes.handle1 = new this.api.Rect(zrUtil.mergeAll(
{
drift: zrUtil.bind(this._onDrift, this, this._getUpdateArgs('handle1')),
ondragend: zrUtil.bind(this._onDragEnd, this)
},
baseHandle,
layout.handle1
)))
.add(updatableShapes.handle2 = new this.api.Rect(zrUtil.mergeAll(
{
drift: zrUtil.bind(this._onDrift, this, this._getUpdateArgs('handle2')),
ondragend: zrUtil.bind(this._onDragEnd, this)
},
baseHandle,
layout.handle2
)));
},
this._startShape.style.x = this._fillerShae.style.x - this._handleSize,
this._endShape.style.x = this._fillerShae.style.x + this._fillerShae.style.width;
this._endShape.highlightStyle.text = detail.end;
this._endShape.highlightStyle.textPosition = 'right';
_updateView: function () {
// Only shape can be modified.
// So only update shape for convenience and performance.
zrUtil.each(this._updatableShapes, function (shape, name) {
shape.attr('shape', subPixelOptimize(this._layout.layout[name].shape, name));
}, this);
function subPixelOptimize(shape, name) {
var subPixelOptimizeLineWidth = {
startFrame: DEFAULT_FRAME_BORDER_WIDTH,
endFrame: DEFAULT_FRAME_BORDER_WIDTH
};
if (subPixelOptimizeLineWidth.hasOwnProperty(name)) {
shape = graphic.subPixelOptimizeRect({
shape: shape,
style: {lineWidth: subPixelOptimizeLineWidth[name]}
}).shape;
}
return shape;
}
else {
this._startShape.style.width = this._location.width;
this._endShape = zrUtil.clone(this._startShape);
this._startShape.style.y = this._fillerShae.style.y + this._fillerShae.style.height;
this._startShape.highlightStyle.textPosition = 'bottom';
},
this._endShape.style.y = this._fillerShae.style.y - this._handleSize;
this._endShape.highlightStyle.text = detail.end;
this._endShape.highlightStyle.textPosition = 'top';
}
this._startShape = new IconShape(this._startShape);
this._endShape = new IconShape(this._endShape);
this.shapeList.push(this._startShape);
this.shapeList.push(this._endShape);
_getUpdateArgs: function (arg) {
return (!arg || this.dataZoomModel.get('zoomLock'))
? ['handle1', 'handle2']
: [arg];
},
_onDrift : function (rangeArg, dx, dy) {
var dataZoomModel = this._dataZoomModel;
_onDrift: function (rangeArgs, dx, dy) {
var dataZoomModel = this.dataZoomModel;
if (rangeArg === 'both' || dataZoomModel.get('zoomLock')) {
this._updateSliderRange({rangeArg: 'start', dx: dx, dy: dy});
this._updateSliderRange({rangeArg: 'end', dx: dx, dy: dy});
}
else { // rangeArg === 'start' or 'end'
this._updateSliderRange({rangeArg: rangeArg, dx: dx, dy: dy});
}
this._layout.update({rangeArgs: rangeArgs, dx: dx, dy: dy});
// FIXME
// refresh shape location
this._updateView();
// FIXME
if (dataZoomModel.get('realtime')) {
// this._syncData();
}
// FIXME
if (this.zoomOption.showDetail) {
// var detail = this._getDetail();
// this._startShape.style.text = this._startShape.highlightStyle.text = detail.start;
// this._endShape.style.text = this._endShape.highlightStyle.text = detail.end;
// this._startShape.style.textPosition = this._startShape.highlightStyle.textPosition;
// this._endShape.style.textPosition = this._endShape.highlightStyle.textPosition;
// FIXME
// if (this.zoomOption.showDetail) {
// }
this.api.dispatch({
type: 'dataZoom',
from: this.uid,
dataZoomRange: this._layout.normalizeToRange(),
dataZoomModel: this.dataZoomModel
});
}
this._api.dispatch({
type: 'dataZoom',
from: this.uid,
param: this._normalizeToRange(),
targetModel: this._dataZoomModel
});
// FIXME
return true;
},
_onDragEnd : function () {
// FIXME
// if (this.zoomOption.showDetail) {
// this._startShape.style.text = this._endShape.style.text = '=';
// this._startShape.style.textPosition = this._endShape.style.textPosition = 'inside';
// this.zr.modShape(this._startShape.id);
// this.zr.modShape(this._endShape.id);
// this.zr.refreshNextFrame();
// }
// this.isDragend = true;
},
}
});
});
\ No newline at end of file
......@@ -9,24 +9,23 @@ define(function(require) {
var helper = require('./helper');
echarts.registerAction('dataZoom', function (event, ecModel) {
var sourceDataZoomModel = event.targetModel;
ecModel.eachComponent('dataZoom', zrUtil.curry(processSingleDataZoom, event, ecModel));
});
var linkSet = helper.findLinkSet(
zrUtil.bind(ecModel.eachComponent, ecModel, 'dataZoom'),
function (model, dimNames) {
return model.get(dimNames.axisIndex);
},
event.dataZoomModel
);
function processSingleDataZoom(event, ecModel, dataZoomModel) {
helper.eachAxisDim(function (dimNames) {
zrUtil.each(
dataZoomModel.get(dimNames.axisIndex),
zrUtil.curry(processSingleAxis, ecModel, dataZoomModel, dimNames)
);
var dataZoomRange = event.dataZoomRange;
zrUtil.each(linkSet.models, function (dataZoomModel) {
dataZoomModel.setRange({
start: dataZoomRange.start,
end: dataZoomRange.end,
start2: dataZoomRange.start2,
end2: dataZoomRange.end2
});
});
}
function processSingleAxis(ecModel, dataZoomModel, dimNames, axisIndex) {
}
function isSharingAxis(dataZoomModel0, dataZoomModel1) {
}
});
});
\ No newline at end of file
......@@ -4,11 +4,13 @@
define(function (require) {
var echarts = require('../../echarts');
var helper = require('./helper');
var zrUtil = require('zrender/core/util');
var linearMap = require('../../util/number').linearMap;
echarts.registerProcessor(function (ecModel) {
ecModel.eachComponent('dataZoom', zrUtil.curry(processSingleDataZoom, ecModel));
ecModel.eachComponent('dataZoom', function (dataZoomModel) {
dataZoomModel.eachTargetAxis(processSingleAxis);
});
});
// FIXME
......@@ -23,66 +25,54 @@ define(function (require) {
// TODO
// undo redo
function processSingleDataZoom(ecModel, dataZoomModel) {
helper.eachAxisDim(function (dimNames) {
zrUtil.each(
dataZoomModel.get(dimNames.axisIndex),
zrUtil.curry(processSingleAxis, ecModel, dataZoomModel, dimNames)
);
});
}
function processSingleAxis(dimNames, axisIndex, dataZoomModel, ecModel) {
function processSingleAxis(ecModel, dataZoomModel, dimNames, axisIndex) {
// TODO
// backup axis data
// Process axis data
var axisModel = ecModel.getComponent(dimNames.axis, axisIndex);
var axisData = axisModel.get('data');
if (axisData) {
var dataLength = axisData.length;
var start = Math.floor(axisModel.get('dataZoomStart') / 100 * dataLength);
var end = Math.ceil(axisModel.get('dataZoomEnd') / 100 * dataLength);
var percentExtent = [0, 100];
var dataZoomStart = axisModel.get('dataZoomStart');
var dataZoomEnd = axisModel.get('dataZoomEnd');
var axisData = axisModel.getData();
if (axisData) {
var axisDataExtent = [0, axisData.length];
var axisStart = Math.floor(linearMap(dataZoomStart, percentExtent, axisDataExtent, true));
var axisEnd = Math.ceil(linearMap(dataZoomEnd, percentExtent, axisDataExtent, true));
// Only category axis has property 'data's.
axisData = axisData.slice(start, end);
// FIXME
// setter?
axisData = axisModel.option.data = axisData.slice(axisStart, axisEnd);
}
var seriesModels = getTargetSeriesModelsByAxis(
ecModel, dataZoomModel, axisIndex, dimNames
);
zrUtil.each(seriesModels, function (seriesModel) {
// FIXME
// data的backup
// Process series data
var seriesModels = dataZoomModel.getTargetSeriesModels(dimNames.dim, axisIndex);
zrUtil.each(seriesModels, function (seriesModel) {
// FIXME
// 如何filter,
// 是根据data自己存的信息(如dimension)来判断(这比较直接,但是现在list里存的信息没清楚),
// 还是根据axis type来判断(比较枚举不太好)
// var axisType = axisModel.get('type');
// FIXME
// 如何filter,
// 是根据data自己存的信息(如dimension)来判断(这比较直接,但是现在list里存的信息没清楚),
// 还是根据axis type来判断(比较枚举不太好)
// var axisType = axisModel.get('type');
// FIXME
// 这里仅仅处理了list类型
var seriesData = seriesModel.getData();
seriesModel.setData(
seriesData['filter' + dimNames.dim.toUpperCase()](function (value) {
return value >= start && value <= end;
})
);
// FIXME
// 这里仅仅处理了list类型
var seriesData = seriesModel.getData();
if (seriesData) {
// FIXME
// 对于数值轴,还要考虑log等情况.
// FIXME
// 对于时间河流图,还要考虑是否须整块移除。
});
}
}
function getTargetSeriesModelsByAxis(ecModel, dataZoomModel, axisIndex, dimNames) {
var seriesModels = [];
ecModel.eachSeries(function (seriesModel) {
if (axisIndex === seriesModel.get(dimNames.axisIndex)) {
seriesModels.push(seriesModel);
var seriesDataExtent = [0, seriesData.count()];
var seriesStart = Math.floor(linearMap(dataZoomStart, percentExtent, seriesDataExtent, true));
var seriesEnd = Math.ceil(linearMap(dataZoomEnd, percentExtent, seriesDataExtent, true));
seriesData.filterSelf(function (entry) {
var value = entry['get' + dimNames.dim.toUpperCase()]();
return value >= seriesStart && value <= seriesEnd;
});
}
// FIXME
// 对于数值轴,还要考虑log等情况.
// FIXME
// 对于时间河流图,还要考虑是否须整块移除。
});
return seriesModels;
}
});
......@@ -11,14 +11,14 @@ define(function(require) {
// FIXME
// 公用?
helper.eachAxisDim = function (callback, scope) {
helper.eachAxisDim = function (callback, context) {
zrUtil.each(AXIS_DIMS, function (axisDim) {
var names = {
axisIndex: axisDim + 'AxisIndex',
axis: axisDim + 'Axis',
dim: axisDim
};
callback.call(scope, names);
callback.call(context, names);
});
};
......
......@@ -4,6 +4,7 @@
define(function (require) {
require('./legend/LegendModel');
require('./legend/legendAction');
require('./legend/LegendView');
var echarts = require('../echarts');
......
......@@ -68,9 +68,13 @@ define(function (require) {
group.add(text);
legendSymbol.on('click', function () {
legendModel.toggleSelected(seriesName);
api.update();
});
api.dispatch({
type: 'legendSelected',
from: this.uid,
legendModel: legendModel,
seriesName: seriesName
});
}, this);
}, this);
var groupRect = group.getBoundingRect();
......@@ -80,9 +84,9 @@ define(function (require) {
_createSymbol: function (seriesModel, x, y, width, height, api) {
// Using rect symbol defaultly
var legendSymbolType = seriesModel.getVisual('legendSymbol')
var legendSymbolType = seriesModel && seriesModel.getVisual('legendSymbol')
|| 'roundRect';
var symbolType = seriesModel.getVisual('symbol');
var symbolType = seriesModel && seriesModel.getVisual('symbol');
var legendSymbolShape = symbolCreator.createSymbol(legendSymbolType, x, y, width, height);
......
/**
* @file Legend action
*/
define(function(require) {
var echarts = require('../../echarts');
echarts.registerAction('legendSelected', function (event, ecModel) {
event.legendModel.toggleSelected(event.seriesName);
});
});
\ No newline at end of file
......@@ -84,7 +84,6 @@ define(function (require) {
if (data == null || data === '-') {
return NaN;
}
data = this.scale.normalize(data);
var extent = this.getExtent();
......
......@@ -2,6 +2,7 @@ define(function(require) {
'use strict';
var ComponentModel = require('../../model/Component');
var defaultOption = require('../axisDefault');
var zrUtil = require('zrender/core/util');
......@@ -13,7 +14,8 @@ define(function(require) {
zrUtil.merge(axisOption, defaultOption[axisType]);
}
var AxisModel = require('../../model/Component').extend({
var AxisModel = ComponentModel.extend({
type: 'cartesian2dAxis',
/**
......@@ -21,6 +23,32 @@ define(function(require) {
*/
axis: null,
/**
* @override
*/
init: function () {
ComponentModel.prototype.init.call(this);
var data = this.getData();
if (data) {
// FIXME
// clone?
/**
* @type {Array}
* @private
*/
this._dataBeforeProcessing = data.slice();
}
},
/**
* @public
* @return {Array=} data Can be null
*/
getData: function () {
return this.get('data');
},
/**
* @public
* @param {number} start 0-100, null means remain current value.
......@@ -30,6 +58,17 @@ define(function(require) {
var option = this.option;
start != null && (option.dataZoomStart = start);
end != null && (option.dataZoomEnd = end);
},
/**
* @override
*/
restoreData: function () {
// FIXME
// clone?
if (this._dataBeforeProcessing) {
this.option.data = this._dataBeforeProcessing.slice();
}
}
});
......@@ -42,6 +81,8 @@ define(function(require) {
type: 'xAxis',
init: function (axisOption, parentModel, ecModel) {
AxisModel.prototype.init.call(this);
axisOption.type = axisOption.type || 'category';
axisOption.position = axisOption.position || 'bottom';
......@@ -58,6 +99,8 @@ define(function(require) {
type: 'yAxis',
init: function (axisOption, parentModel, ecModel) {
AxisModel.prototype.init.call(this);
axisOption.type = axisOption.type || 'value';
axisOption.position = axisOption.position || 'left';
......
......@@ -26,10 +26,10 @@ define(function(require, factory) {
var axisType = axisModel.get('type');
if (axisType) {
return axisType === 'category'
? new OrdinalScale(axisModel.get('data'))
? new OrdinalScale(axisModel.getData())
: new IntervalScale();
}
};
}
/**
* Check if the axis is used in the specified grid
......@@ -232,7 +232,7 @@ define(function(require, factory) {
this._axesList.push(axisY);
this._axesMap['y' + idx] = axisY;
xAxesMap[idx] = axisY;
yAxesMap[idx] = axisY;
yAxesCount++;
}, this);
......@@ -253,18 +253,6 @@ define(function(require, factory) {
cartesian.addAxis(xAxis);
cartesian.addAxis(yAxis);
});
});
ecModel.eachComponent('xAxis', function (xAxisModel, i) {
ecModel.eachComponent('yAxis', function (yAxisModel, j) {
var key = 'x' + i + 'y' + j;
var cartesian = new Cartesian2D(key);
this._coordsMap[key] = cartesian;
this._coordsList.push(cartesian);
cartesian.addAxis(xAxisModel.axis);
cartesian.addAxis(yAxisModel.axis);
}, this);
}, this);
......@@ -319,7 +307,7 @@ define(function(require, factory) {
else {
data.eachValue(function (value) {
if (value != null) {
axisData[categoryAxis.dim == 'y' ? 'x' : 'y'].push(value);
axisData[categoryAxis.dim === 'y' ? 'x' : 'y'].push(value);
}
});
}
......@@ -371,7 +359,7 @@ define(function(require, factory) {
});
return grids;
}
};
require('../../CoordinateSystem').register('grid', Grid);
......
......@@ -40,12 +40,14 @@ define(function(require) {
var oldDataMap = {};
var newDataMap = {};
var newDataIndexMap = {};
var i;
for (i = 0; i < oldArr.length; i++) {
oldDataMap[oldArr[i].name] = oldArr[i];
}
for (i = 0; i < newArr.length; i++) {
newDataMap[newArr[i].name] = newArr[i];
newDataIndexMap[newArr[i].name] = i;
}
for (i = 0; i < oldArr.length; i++) {
......@@ -61,8 +63,8 @@ define(function(require) {
for (i = 0; i < newArr.length; i++) {
var newData = newArr[i];
if (! oldDataMap[newData.name]) {
this._add && this._add(newData);
if (!oldDataMap[newData.name]) {
this._add && this._add(newData, newDataIndexMap[newData.name]);
}
}
}
......
......@@ -25,9 +25,11 @@ define(function(require) {
array[i] = eachAxis(item, depth);
}
}
}
};
}
var dimensions = ['x', 'y', 'z', 'value', 'radius', 'angle']
var dimensions = ['x', 'y', 'z', 'value', 'radius', 'angle'];
/**
* @name echarts/data/List~Entry
* @extends {module:echarts/model/Model}
......@@ -78,7 +80,7 @@ define(function(require) {
*/
valueIndex: 1,
init: function (option, parentModel, dataIndex, independentVar, dependentVar) {
init: function (option, parentModel, rawDataIndex, independentVar, dependentVar) {
/**
* @type {string}
......@@ -87,12 +89,27 @@ define(function(require) {
*/
this.name = option.name || '';
/**
* this.option **MUST NOT** be modified in List!
* Different lists might share this option instance.
*
* @readOnly
* @type {*}
*/
this.option = option;
var value = option.value == null ? option : option.value;
if (typeof value === 'number') {
value = [dataIndex, value];
value = [rawDataIndex, value];
/**
* If dataIndex is persistent in entry, it should be udpated when modifying list.
* So use this.dataIndexIndex to mark that.
*
* @readOnly
* @type {number}
*/
this.dataIndexIndex = 0;
}
if (independentVar) {
......@@ -105,6 +122,10 @@ define(function(require) {
}
/**
* All of the content **MUST NOT** be modified,
* (because they are the same instance with option.value)
* except this._value[this.dataIndexIndex].
*
* @type {Array.<number>}
* @memeberOf module:echarts/data/List~Entry
* @private
......@@ -112,10 +133,11 @@ define(function(require) {
this._value = value;
/**
* @private
* Data index before modifying list (filterSelf).
*
* @readOnly
*/
this.dataIndex = dataIndex;
this.rawDataIndex = rawDataIndex;
},
/**
......@@ -129,10 +151,11 @@ define(function(require) {
},
clone: function () {
var entry = new Entry(
this.option, this.parentModel, this.dataIndex
);
var entry = new Entry(this.option, this.parentModel);
entry.name = this.name;
entry.dataIndexIndex = this.dataIndexIndex;
entry._value = entry.dataIndexIndex != null
? this._value.slice() : this._value;
for (var i = 0; i < dimensions.length; i++) {
var key = dimensions[i] + 'Index';
......@@ -150,16 +173,20 @@ define(function(require) {
if (index >= 0) {
return this._value[index];
}
}
};
Entry.prototype['set' + capitalized] = function (val) {
var index = this[indexKey];
if (index >= 0) {
this._value[indexKey] = val;
}
}
};
});
function List() {
/**
* @readOnly
* @type {Array}
*/
this.elements = [];
}
......@@ -169,9 +196,12 @@ define(function(require) {
type: 'list',
count: function () {
return this.elements.length;
},
each: function (cb, context) {
context = context || this;
zrUtil.each(this.elements, cb, context);
zrUtil.each(this.elements, cb, context || this);
},
/**
......@@ -180,16 +210,34 @@ define(function(require) {
*/
map: function (cb, context) {
var ret = [];
context = context || this;
this.each(function (item, idx) {
ret.push(cb && cb.call(context || this, item));
ret.push(cb && cb.call(context, item));
}, context);
return ret;
},
filter: function (cb, context) {
var list = new List();
context = context || this;
list.elements = zrUtil.filter(this.elements, cb, context);
filterSelf: function (cb, context) {
this.elements = zrUtil.filter(this.elements, cb, context || this);
var dataIndexDirty = false;
this.elements = zrUtil.filter(this.elements, function (entry) {
var result = cb.apply(this, arguments);
if (result && entry.dataIndexIndex != null) {
dataIndexDirty = true;
}
return result;
}, context || this);
dataIndexDirty && this.refreshDataIndex();
},
refreshDataIndex: function () {
this.each(function (entry, dataIndex) {
if (entry.dataIndexIndex != null) {
entry._value[entry.dataIndexIndex] = dataIndex;
}
}, this);
},
/**
......@@ -227,8 +275,6 @@ define(function(require) {
for (var i = 0; i < elements.length; i++) {
list.elements.push(elements[i].clone());
}
list.depth = this.depth;
list.properties = this.properties;
return list;
}
};
......@@ -247,18 +293,6 @@ define(function(require) {
}, context);
return ret;
};
List.prototype['filter' + name] = function (cb, context) {
var newList = this.clone();
var elements = []
newList.each(function (item) {
if (cb.call(context || newList, item['get' + name]())) {
elements.push(item);
}
}, context);
newList.elements = elements;
return newList;
};
});
List.fromArray = function (data, seriesModel, ecModel) {
......@@ -295,7 +329,7 @@ define(function(require) {
else if (coordinateSystem === 'polar') {
function axisFinder(axisModel) {
return axisModel.get('polarIndex') === polarIndex;
};
}
var polarIndex = seriesModel.get('polarIndex') || 0;
var angleAxisModel = ecModel.findComponent('angleAxis', axisFinder);
var radiusAxisModel = ecModel.findComponent('radiusAxis', axisFinder);
......
......@@ -154,22 +154,26 @@ define(function (require) {
this._needsUpdate = true;
},
updateImmediately: function () {
updateImmediately: function (event) {
// console.time('update');
var ecModel = this._model;
ecModel.restoreData();
// TODO
// Save total ecModel here for undo/redo (after restoring data and before processing data).
// Undo (restoration of total ecModel) can be carried out in 'action' or outside API call.
this._processData(ecModel);
this._coordinateSystem.update(ecModel, this._extensionAPI);
this._doVisualCoding(ecModel);
this._doLayout(ecModel);
this._doLayout(ecModel, event);
this._doRender(ecModel);
this._doRender(ecModel, event);
this._needsUpdate = false;
......@@ -190,6 +194,20 @@ define(function (require) {
this.updateImmediately();
},
/**
* @pubilc
* @param {Object} event
* @param {string} [event.type] Event type
* @param {number} [event.from] From uid
*/
dispatch: function (event) {
var action = actions[event.type];
if (action) {
action(event, this._model);
this.updateImmediately(event);
}
},
_prepareCharts: function (ecModel) {
var chartsList = this._chartsList;
......@@ -299,12 +317,12 @@ define(function (require) {
* @param {module:echarts/model/Global} ecModel
* @private
*/
_doLayout: function (ecModel) {
_doLayout: function (ecModel, event) {
zrUtil.each(this._layouts, function (layout) {
layout(ecModel);
layout(ecModel, event);
});
zrUtil.each(layoutFuncs, function (layout) {
layout(ecModel);
layout(ecModel, event);
});
},
......@@ -323,23 +341,25 @@ define(function (require) {
/**
* Render each chart and component
*/
_doRender: function (ecModel) {
_doRender: function (ecModel, event) {
var api = this._extensionAPI;
// Render all components
zrUtil.each(this._componentsList, function (component) {
component.render(component.__model, ecModel, api);
component.render(component.__model, ecModel, api, event);
}, this);
// Remove groups of charts
zrUtil.each(this._chartsList, function (chart) {
chart.__keepAlive = false;
}, this);
// Render all charts
ecModel.eachSeries(function (seriesModel, idx) {
var id = getSeriesId(seriesModel.option, idx);
var chart = this._chartsMap[id];
chart.__keepAlive = true;
chart.render(seriesModel, ecModel, api);
chart.render(seriesModel, ecModel, api, event);
}, this);
// Remove groups of charts
zrUtil.each(this._chartsList, function (chart) {
if (!chart.__keepAlive) {
......@@ -363,6 +383,8 @@ define(function (require) {
var dataProcessorFuncs = [];
var actions = [];
var layoutClasses = [];
var layoutFuncs = [];
......@@ -387,6 +409,15 @@ define(function (require) {
}
},
/**
* @param {Function}
*/
registerAction: function (actionName, action) {
if (!actions[actionName]) {
actions[actionName] = action;
}
},
/**
* @param {string} type
* @param {*} CoordinateSystem
......@@ -429,6 +460,13 @@ define(function (require) {
return ComponentModel.extend(opts);
},
/**
* @param {Object} opts
*/
extendSeriesModel: function (opts) {
return SeriesModel.extend(opts);
},
/**
* @param {Object} opts
*/
......
......@@ -77,6 +77,7 @@ define(function (require) {
max = Math.max(data[i], max);
min = Math.min(data[i], min);
}
this.setExtent(min, max);
},
......
......@@ -4,7 +4,7 @@ define(function(require) {
var pathTool = require('zrender/tool/path');
var matrix = require('zrender/core/matrix');
var round = Math.round;
var Path = require('zrender/graphic/Path');
var graphic = {
......@@ -77,27 +77,81 @@ define(function(require) {
},
/**
* @param {Array.<number>} p1
* @param {Array.<number>} p2
* @param {number} lineWidth
* Sub pixel optimize line for canvas
*
* @param {Object} param
* @param {Object} [param.shape]
* @param {number} [param.shape.x1]
* @param {number} [param.shape.y1]
* @param {number} [param.shape.x2]
* @param {number} [param.shape.y2]
* @param {Object} [param.style]
* @param {number} [param.style.lineWidth]
* @return {Object} Modified param
*/
subPixelOptimizeLine: function (p1, p2, lineWidth) {
var round = Math.round;
// Sub pixel optimize
var offset = lineWidth % 2 / 2;
var x1 = round(p1[0]);
var y1 = round(p1[1]);
var x2 = round(p2[0]);
var y2 = round(p2[1]);
if (x1 === x2) {
x1 += offset;
x2 += offset;
subPixelOptimizeLine: function (param) {
var subPixelOptimize = graphic.subPixelOptimize;
var shape = param.shape;
var lineWidth = param.style.lineWidth;
if (round(shape.x1 * 2) === round(shape.x2 * 2)) {
shape.x1 = shape.x2 = subPixelOptimize(shape.x1, lineWidth, true);
}
if (y1 === y2) {
y1 += offset;
y2 += offset;
if (round(shape.y1 * 2) === round(shape.y2 * 2)) {
shape.y1 = shape.y2 = subPixelOptimize(shape.y1, lineWidth, true);
}
return param;
},
/**
* Sub pixel optimize rect for canvas
*
* @param {Object} param
* @param {Object} [param.shape]
* @param {number} [param.shape.x]
* @param {number} [param.shape.y]
* @param {number} [param.shape.width]
* @param {number} [param.shape.height]
* @param {Object} [param.style]
* @param {number} [param.style.lineWidth]
* @return {Object} Modified param
*/
subPixelOptimizeRect: function (param) {
var subPixelOptimize = graphic.subPixelOptimize;
var shape = param.shape;
var lineWidth = param.style.lineWidth;
var originX = shape.x;
var originY = shape.y;
var originWidth = shape.width;
var originHeight = shape.height;
shape.x = subPixelOptimize(shape.x, lineWidth, true);
shape.y = subPixelOptimize(shape.y, lineWidth, true);
shape.width = Math.max(
subPixelOptimize(originX + originWidth, lineWidth, false) - shape.x,
originWidth === 0 ? 0 : 1
);
shape.height = Math.max(
subPixelOptimize(originY + originHeight, lineWidth, false) - shape.y,
originHeight === 0 ? 0 : 1
);
return param;
},
/**
* Sub pixel optimize for canvas
*
* @param {number} position Coordinate, such as x, y
* @param {number} lineWidth Should be nonnegative integer.
* @param {boolean=} positiveOrNegative Default false (negative).
* @return {number} Optimized position.
*/
subPixelOptimize: function (position, lineWidth, positiveOrNegative) {
// Assure that (position + lineWidth / 2) is near integer edge,
// otherwise line will be fuzzy in canvas.
var doubledPosition = round(position * 2);
return (doubledPosition + round(lineWidth)) % 2 === 0
? doubledPosition / 2
: (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2;
}
};
......
<html>
<head>
<meta charset="utf-8">
<script src="esl.js"></script>
<script src="config.js"></script>
</head>
<body>
<style>
html, body, #main {
width: 100%;
height: 100%;
}
</style>
<div id="main"></div>
<script>
require([
'echarts',
'echarts/chart/line',
'echarts/component/legend',
'echarts/component/grid',
'echarts/component/axis',
'echarts/component/dataZoom'
], function (echarts) {
var chart = echarts.init(document.getElementById('main'), null, {
renderer: 'canvas'
});
var xAxisData = [];
var data1 = [];
var data2 = [];
var data3 = [];
for (var i = 0; i < 20; i++) {
xAxisData.push('类目' + i);
data1.push(Math.random() * 5);
data2.push(Math.random());
data3.push(Math.random());
}
chart.setOption({
legend: {
data: ['line', 'line2', 'line3']
},
xAxis: {
// data: ['类目1', '类目2', '类目3', '类目4', '类目5',]
data: xAxisData
},
yAxis: {
// scale: true
},
series: [
{
name: 'line',
type: 'line',
data: data1
},
// {
// name: 'line2',
// type: 'line',
// data: data2
// },
// {
// name: 'line3',
// type: 'line',
// data: data3
// }
],
dataZoom: {
show: true
}
});
})
</script>
</body>
</html>
\ No newline at end of file
document.write('<script src="ut/core/utHelper.js"><\/script>');
// Specs ...
document.write('<script src="ut/spec/util/graphic.js"><\/script>');
document.write('<script src="ut/spec/model/Component.js"><\/script>');
document.write('<script src="ut/spec/dataZoom/helper.js"><\/script>');
describe('util/graphic', function() {
var utHelper = window.utHelper;
var graphic;
beforeAll(function (done) { // jshint ignore:line
utHelper.resetPackageLoader(function () {
window.require(['echarts/util/graphic'], function (g) {
graphic = g;
done();
});
});
});
describe('subPixelOptimize', function () {
it('subPixelOptimize_base', function (done) {
expect(graphic.subPixelOptimize(5, 1)).toEqual(4.5);
expect(graphic.subPixelOptimize(5, 2)).toEqual(5);
expect(graphic.subPixelOptimize(5, 43)).toEqual(4.5);
expect(graphic.subPixelOptimize(7.5, 1)).toEqual(7.5);
expect(graphic.subPixelOptimize(7.5, 2)).toEqual(7);
expect(graphic.subPixelOptimize(14, 1, true)).toEqual(14.5);
expect(graphic.subPixelOptimize(14, 2, true)).toEqual(14);
expect(graphic.subPixelOptimize(-11, 1)).toEqual(-11.5);
expect(graphic.subPixelOptimize(-11, 2)).toEqual(-11);
expect(graphic.subPixelOptimize(0, 2)).toEqual(0);
expect(graphic.subPixelOptimize(0, 1)).toEqual(-0.5);
expect(graphic.subPixelOptimize(5, 0)).toEqual(5);
done();
});
it('subPixelOptimize_line', function (done) {
function doSubPixelOptimizeLine(x, y, width, height, lineWidth) {
return graphic.subPixelOptimizeLine(makeParam(x, y, width, height, lineWidth));
}
function makeParam(x1, y1, x2, y2, lineWidth) {
return {
shape: {x1: x1, y1: y1, x2: x2, y2: y2},
style: {lineWidth: lineWidth}
};
}
expect(doSubPixelOptimizeLine(5, 11, 3, 7, 1)).toEqual(makeParam(5, 11, 3, 7, 1));
expect(doSubPixelOptimizeLine(5, 11, 5, 7, 1)).toEqual(makeParam(5.5, 11, 5.5, 7, 1));
expect(doSubPixelOptimizeLine(5, 11, 5, 7, 2)).toEqual(makeParam(5, 11, 5, 7, 2));
expect(doSubPixelOptimizeLine(5, 11, 15, 11, 1)).toEqual(makeParam(5, 11.5, 15, 11.5, 1));
expect(doSubPixelOptimizeLine(5, 11, 15, 11, 2)).toEqual(makeParam(5, 11, 15, 11, 2));
expect(doSubPixelOptimizeLine(5, 11, 15, 11, 3)).toEqual(makeParam(5, 11.5, 15, 11.5, 3));
expect(doSubPixelOptimizeLine(5, 11, 15, 11.5, 3)).toEqual(makeParam(5, 11, 15, 11.5, 3));
expect(doSubPixelOptimizeLine(5, 11.5, 15, 11.5, 3)).toEqual(makeParam(5, 11.5, 15, 11.5, 3));
expect(doSubPixelOptimizeLine(5, 11.5, 15, 11.5, 4)).toEqual(makeParam(5, 12, 15, 12, 4));
done();
});
it('subPixelOptimize_rect', function (done) {
function doSubPixelOptimizeRect(x, y, width, height, lineWidth) {
return graphic.subPixelOptimizeRect(makeParam(x, y, width, height, lineWidth));
}
function makeParam(x, y, width, height, lineWidth) {
return {
shape: {x: x, y: y, width: width, height: height},
style: {lineWidth: lineWidth}
};
}
expect(doSubPixelOptimizeRect(5, 11, 3, 7, 1)).toEqual(makeParam(5.5, 11.5, 2, 6, 1));
expect(doSubPixelOptimizeRect(5, 11, 3, 7, 2)).toEqual(makeParam(5, 11, 3, 7, 2));
expect(doSubPixelOptimizeRect(5, 11, 3, 7, 3)).toEqual(makeParam(5.5, 11.5, 2, 6, 3));
// Boundary value tests
expect(doSubPixelOptimizeRect(5, 11, 1, 7, 1)).toEqual(makeParam(5.5, 11.5, 1, 6, 1));
expect(doSubPixelOptimizeRect(5, 11, 1, 0, 1)).toEqual(makeParam(5.5, 11.5, 1, 0, 1));
done();
});
});
});
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册