提交 97e0f4e0 编写于 作者: P pah100

datazoom support startValue and endValue.

上级 0e908040
......@@ -6,6 +6,7 @@ define(function(require) {
var zrUtil = require('zrender/core/util');
var numberUtil = require('../../util/number');
var each = zrUtil.each;
var asc = numberUtil.asc;
/**
* Operate single axis.
......@@ -39,7 +40,19 @@ define(function(require) {
* @private
* @type {Array.<number>}
*/
this._dataWindow;
this._valueWindow;
/**
* @private
* @type {Array.<number>}
*/
this._percentWindow;
/**
* @private
* @type {Array.<number>}
*/
this._dataExtent;
/**
* @readOnly
......@@ -84,10 +97,24 @@ define(function(require) {
},
/**
* @param {boolean} crossZero
* @return {Array.<number>}
*/
getDataWindow: function () {
return this._dataWindow;
getDataExtent: function () {
return this._dataExtent.slice();
},
/**
* @return {Array.<number>}
*/
getDataValueWindow: function () {
return this._valueWindow.slice();
},
/**
* @return {Array.<number>}
*/
getDataPercentWindow: function () {
return this._percentWindow.slice();
},
/**
......@@ -107,20 +134,10 @@ define(function(require) {
return seriesModels;
},
/**
* Return range in its host model.
*
* @public
* @return {Array.<number>} [min, max]
*/
getRange: function () {
return this._model.getRange();
},
/**
* @param {module: echarts/component/dataZoom/DataZoomModel} model
*/
filterData: function (model) {
reset: function (model) {
if (model !== this._model) {
return;
}
......@@ -130,19 +147,31 @@ define(function(require) {
var axisModel = this.ecModel.getComponent(axisDim + 'Axis', this._axisIndex);
var isCategoryFilter = axisModel.get('type') === 'category';
var seriesModels = this.getTargetSeriesModels();
var dataZoomModel = this._model;
var filterMode = dataZoomModel.get('filterMode');
var dataExtent = calculateDataExtent(axisDim, seriesModels);
var dataWindow = calculateDataWindow(dataZoomModel, dataExtent, isCategoryFilter);
var dataWindow = calculateDataWindow(model, dataExtent, isCategoryFilter);
// Record data window and data extent.
this._dataExtent = dataExtent.slice();
this._valueWindow = dataWindow.valueWindow.slice();
this._percentWindow = dataWindow.percentWindow.slice();
},
/**
* @param {module: echarts/component/dataZoom/DataZoomModel} model
*/
filterData: function (model) {
if (model !== this._model) {
return;
}
// Record data window.
this._dataWindow = dataWindow.slice();
var axisDim = this._dimName;
var seriesModels = this.getTargetSeriesModels();
var filterMode = model.get('filterMode');
var valueWindow = this._valueWindow;
// Process series data
each(seriesModels, function (seriesModel) {
// FIXME
// 这里仅仅处理了list类型
var seriesData = seriesModel.getData();
if (!seriesData) {
return;
......@@ -163,7 +192,7 @@ define(function(require) {
});
function isInWindow(value) {
return value >= dataWindow[0] && value <= dataWindow[1];
return value >= valueWindow[0] && value <= valueWindow[1];
}
}
};
......@@ -186,13 +215,54 @@ define(function(require) {
}
function calculateDataWindow(dataZoomModel, dataExtent, isCategoryFilter) {
var result = numberUtil.linearMap(dataZoomModel.getRange(), [0, 100], dataExtent, true);
if (isCategoryFilter) {
result = [Math.floor(result[0]), Math.ceil(result[1])];
}
var percentExtent = [0, 100];
var modelOption = dataZoomModel.option;
var percentWindow = [
modelOption.start,
modelOption.end
];
var valueWindow = [
modelOption.startValue,
modelOption.endValue
];
var mathFn = ['floor', 'ceil'];
// Normalize bound.
each([0, 1], function (idx) {
var boundValue = valueWindow[idx];
var boundPercent;
var calcuPercent = true;
if (isInvalidNumber(boundValue)) {
boundPercent = percentWindow[idx];
if (isInvalidNumber(boundPercent)) {
boundPercent = percentExtent[idx];
}
boundValue = numberUtil.linearMap(
boundPercent, percentExtent, dataExtent, true
);
calcuPercent = false;
}
if (isCategoryFilter) {
boundValue = Math[mathFn[idx]](boundValue);
}
if (calcuPercent) {
boundPercent = numberUtil.linearMap(
boundValue, dataExtent, percentExtent, true
);
}
valueWindow[idx] = boundValue;
percentWindow[idx] = boundPercent;
});
return {
valueWindow: asc(valueWindow),
percentWindow: asc(percentWindow)
};
}
return result;
function isInvalidNumber(val) {
return isNaN(val) || val == null;
}
return AxisProxy;
......
......@@ -10,6 +10,7 @@ define(function(require) {
var numberUtil = require('../../util/number');
var AxisProxy = require('./AxisProxy');
var asc = numberUtil.asc;
var each = zrUtil.each;
var eachAxisDim = modelUtil.eachAxisDim;
return echarts.extendComponentModel({
......@@ -38,8 +39,10 @@ define(function(require) {
// that there are some data items out of window.
throttle: 100, // Dispatch action by the fixed rate, avoid frequency.
// default 100. Do not throttle when use null/undefined.
start: 0, // 默认为0
end: 100 // 默认为全部 100%
start: 0, // Start percent. 0 ~ 100
end: 100, // End percent. 0 ~ 100
startValue: null, // Start value. If startValue specified, start is ignored.
endValue: null // End value. If endValue specified, end is ignored.
},
/**
......@@ -102,10 +105,6 @@ define(function(require) {
this._giveAxisProxies();
this._backup();
this._resetRange();
this._setToAxisModel();
},
/**
......@@ -305,63 +304,6 @@ define(function(require) {
}, this);
},
/**
* @private
*/
_resetRange: function () {
var thisOption = this.option;
var axisProxies = this._axisProxies;
// Sync range with other dataZoomModel.
// Consider this case: dataZoomModel1 and dataZoomModel2 control the same axis,
// and the range settings are different. That will bring some problem when using
// dataZoomModel.getRange before aciton ever dispatched.
// (We encounter this problem in toolbox data zoom.)
var notHostAnyAxis = true;
var firstAxisProxy;
zrUtil.each(axisProxies, function (proxy) {
firstAxisProxy = proxy;
if (proxy.hostedBy(this)) {
notHostAnyAxis = false;
}
}, this);
if (notHostAnyAxis && firstAxisProxy) {
var range = firstAxisProxy.getRange();
thisOption.start = range[0];
thisOption.end = range[1];
}
else {
var startValue = thisOption.start;
var endValue = thisOption.end;
// Auto reverse when start > end
if (startValue > endValue) {
startValue = [endValue, endValue = startValue][0];
}
thisOption.start = startValue;
thisOption.end = endValue;
}
},
/**
* @private
*/
_setToAxisModel: function () {
var range = this.getRange();
// Set "needsCrossZero" to axes
this.eachTargetAxis(function (dimNames, axisIndex, dataZoomModel, ecModel) {
var axisModel = ecModel.getComponent(dimNames.axis, axisIndex);
axisModel.setNeedsCrossZero && axisModel.setNeedsCrossZero(
(range[0] === 0 && range[1] === 100)
? this.getAxisProxy(dimNames.name, axisIndex).getCrossZero()
: false
);
}, this);
},
/**
* @public
*/
......@@ -386,7 +328,7 @@ define(function(require) {
eachTargetAxis: function (callback, context) {
var ecModel = this.ecModel;
eachAxisDim(function (dimNames) {
zrUtil.each(
each(
this.get(dimNames.axisIndex),
function (axisIndex) {
callback.call(context, dimNames, axisIndex, this, ecModel);
......@@ -401,47 +343,44 @@ define(function(require) {
},
/**
* If not specified, set to undefined.
*
* @public
* @param {Array} param [start, end]
* @param {Object} opt
* @param {number} [opt.start]
* @param {number} [opt.end]
* @param {number} [opt.startValue]
* @param {number} [opt.endValue]
*/
setRange: function (param) {
// FIXME
// 接口改变
var thisOption = this.option;
param[0] != null && (thisOption.start = param[0]);
param[1] != null && (thisOption.end = param[1]);
this._resetRange();
setRawRange: function (opt) {
each(['start', 'end', 'startValue', 'endValue'], function (name) {
this.option[name] = opt[name];
}, this);
},
/**
* @public
* @return {Array.<number>}
*/
getRange: function () {
var thisOption = this.option;
var range = [thisOption.start, thisOption.end];
return this.fixRange(range);
},
getPercentRange: function () {
// Find the first hosted axisProxy
var axisProxies = this._axisProxies;
for (var key in axisProxies) {
if (axisProxies.hasOwnProperty(key) && axisProxies[key].hostedBy(this)) {
return axisProxies[key].getDataPercentWindow();
}
}
/**
* @protected
*/
fixRange: function (range, bound) {
bound = bound || [0, 100];
// Make sure range[0] <= range[1]
var range = asc(range);
// Clamp, using !(<= or >=) to handle NaN.
// jshint ignore:start
!(range[0] <= bound[1]) && (range[0] = bound[1]);
!(range[1] <= bound[1]) && (range[1] = bound[1]);
!(range[0] >= bound[0]) && (range[0] = bound[0]);
!(range[1] >= bound[0]) && (range[1] = bound[0]);
// jshint ignore:end
return range;
// If no hosted axis find not hosted axisProxy.
// Consider this case: dataZoomModel1 and dataZoomModel2 control the same axis,
// and the option.start or option.end settings are different. The percentRange
// show follow axisProxy.
// (We encounter this problem in toolbox data zoom.)
for (var key in axisProxies) {
if (axisProxies.hasOwnProperty(key) && !axisProxies[key].hostedBy(this)) {
return axisProxies[key].getDataPercentWindow();
}
}
}
});
......
......@@ -48,7 +48,7 @@ define(function (require) {
// is 'dataZoom', origin this._range should be maintained, otherwise 'pan'
// or 'zoom' info will be missed because of 'throttle' of this.dispatchAction,
if (!payload || payload.type !== 'dataZoom' || payload.from !== this.uid) {
this._range = dataZoomModel.getRange();
this._range = dataZoomModel.getPercentRange();
}
this._resetController(api);
......@@ -139,7 +139,8 @@ define(function (require) {
type: 'dataZoom',
from: this.uid,
dataZoomId: this.dataZoomModel.id,
range: range.slice()
start: range[0],
end: range[1]
});
}
......@@ -188,7 +189,10 @@ define(function (require) {
range[0] = (range[0] - percentPoint) * scale + percentPoint;
range[1] = (range[1] - percentPoint) * scale + percentPoint;
return dataZoomModel.fixRange(range);
// FIXME
// 改为基于绝对值的方式?
return fixRange(range);
}
function getDirectionInfo(xy, axisModel, controller) {
......@@ -212,4 +216,16 @@ define(function (require) {
return ret;
}
function fixRange(range) {
// Clamp, using !(<= or >=) to handle NaN.
// jshint ignore:start
var bound = [0, 100];
!(range[0] <= bound[1]) && (range[0] = bound[1]);
!(range[1] <= bound[1]) && (range[1] = bound[1]);
!(range[0] >= bound[0]) && (range[0] = bound[0]);
!(range[1] >= bound[0]) && (range[1] = bound[0]);
// jshint ignore:end
return range;
}
});
\ No newline at end of file
......@@ -429,7 +429,7 @@ define(function (require) {
* @private
*/
_resetInterval: function () {
var range = this._range = this.dataZoomModel.getRange();
var range = this._range = this.dataZoomModel.getPercentRange();
this._handleEnds = linearMap(range, [0, 100], this._getViewExtent(), true);
},
......@@ -511,7 +511,7 @@ define(function (require) {
if (!dataInterval) {
dataInterval = dataZoomModel
.getAxisProxy(dimNames.name, axisIndex)
.getDataWindow();
.getDataValueWindow();
axis = this.ecModel.getComponent(dimNames.axis, axisIndex).axis;
}
}, this);
......@@ -618,11 +618,14 @@ define(function (require) {
* @private
*/
_dispatchZoomAction: function () {
var range = this._range;
this.api.dispatchAction({
type: 'dataZoom',
from: this.uid,
dataZoomId: this.dataZoomModel.id,
range: this._range.slice()
start: range[0],
end: range[1]
});
},
......
......@@ -31,7 +31,14 @@ define(function(require) {
);
zrUtil.each(effectedModels, function (dataZoomModel, index) {
dataZoomModel.setRange(payloadInfoList[index].range);
var payloadInfo = payloadInfoList[index];
dataZoomModel.setRawRange({
start: payloadInfo.start,
end: payloadInfo.end,
startValue: payloadInfo.startValue,
endValue: payloadInfo.endValue
});
});
function distinctPush(effectedModels, source, payloadInfo) {
......
......@@ -6,15 +6,33 @@ define(function (require) {
var echarts = require('../../echarts');
echarts.registerProcessor('filter', function (ecModel) {
ecModel.eachComponent('dataZoom', function (dataZoomModel) {
dataZoomModel.eachTargetAxis(resetSingleAxis);
});
ecModel.eachComponent('dataZoom', function (dataZoomModel) {
dataZoomModel.eachTargetAxis(processSingleAxis);
dataZoomModel.eachTargetAxis(filterSingleAxis);
});
});
// TODO
// undo redo
function resetSingleAxis(dimNames, axisIndex, dataZoomModel, ecModel) {
var dimName = dimNames.name;
var axisProxy = dataZoomModel.getAxisProxy(dimName, axisIndex);
axisProxy.reset(dataZoomModel);
var percentRange = axisProxy.getDataPercentWindow();
var axisModel = ecModel.getComponent(dimNames.axis, axisIndex);
axisModel.setNeedsCrossZero && axisModel.setNeedsCrossZero(
(percentRange[0] === 0 && percentRange[1] === 100)
? axisProxy.getCrossZero()
: false
);
}
function processSingleAxis(dimNames, axisIndex, dataZoomModel, ecModel) {
function filterSingleAxis(dimNames, axisIndex, dataZoomModel, ecModel) {
dataZoomModel.getAxisProxy(dimNames.name, axisIndex).filterData(dataZoomModel);
}
......
......@@ -2,10 +2,13 @@ define(function(require) {
'use strict';
var zrUtil = require('zrender/core/util');
var numberUtil = require('../../../util/number');
var SelectController = require('../../helper/SelectController');
var BoundingRect = require('zrender/core/BoundingRect');
var Group = require('zrender/container/Group');
var each = zrUtil.each;
var asc = numberUtil.asc;
// Use dataZoomSelect
require('../../dataZoomSelect');
......@@ -154,8 +157,8 @@ define(function(require) {
// Default use the first axis.
// FIXME
var coordInfo = [
{axisModel: grid.getAxis('x').model}, // x
{axisModel: grid.getAxis('y').model} // y
{axisModel: grid.getAxis('x').model, axisIndex: 0}, // x
{axisModel: grid.getAxis('y').model, axisIndex: 0} // y
];
coordInfo.grid = grid;
......@@ -187,51 +190,66 @@ define(function(require) {
if (!selRanges.length) {
return;
}
selRanges = selRanges[0];
var selRange = selRanges[0];
controller.update(); // remove cover
var snapshot = {};
each(coordInfoList, function (coordInfo) {
var rect = coordInfo.grid.getRect();
rect = [[rect.x, rect.x + rect.width], [rect.y, rect.y + rect.height]];
var selDataRange = pointToDataInCartesian(selRange, coordInfo);
var xBatchItem = scaleCartesianAxis(rect, selRanges, coordInfo, 0); // x
var yBatchItem = scaleCartesianAxis(rect, selRanges, coordInfo, 1); // y
if (selDataRange) {
var xBatchItem = scaleCartesianAxis(selDataRange, coordInfo, 0, 'x');
var yBatchItem = scaleCartesianAxis(selDataRange, coordInfo, 1, 'y');
xBatchItem && (snapshot[xBatchItem.dataZoomId] = xBatchItem);
yBatchItem && (snapshot[yBatchItem.dataZoomId] = yBatchItem);
xBatchItem && (snapshot[xBatchItem.dataZoomId] = xBatchItem);
yBatchItem && (snapshot[yBatchItem.dataZoomId] = yBatchItem);
}
});
this._pushHistory(snapshot, ecModel);
this._dispatchAction(snapshot, api);
};
function scaleCartesianAxis(rect, selRanges, coordInfo, dimIdx) {
var dimCoordInfo = coordInfo[dimIdx];
var dataZoomModel = dimCoordInfo.dataZoomModel;
var dataRange = dataZoomModel.getRange();
function pointToDataInCartesian(selRange, coordInfo) {
var grid = coordInfo.grid;
var rectInterval = rect[dimIdx][1] - rect[dimIdx][0];
var dataRangeInterval = dataRange[1] - dataRange[0];
var selRange = [
dataRange[0] + (selRanges[dimIdx][0] - rect[dimIdx][0]) / rectInterval * dataRangeInterval,
dataRange[0] + (selRanges[dimIdx][1] - rect[dimIdx][0]) / rectInterval * dataRangeInterval
var selRect = new BoundingRect(
selRange[0][0],
selRange[1][0],
selRange[0][1] - selRange[0][0],
selRange[1][1] - selRange[1][0]
);
if (!selRect.intersect(grid.getRect())) {
return;
}
var cartesian = grid.getCartesian(coordInfo[0].axisIndex, coordInfo[1].axisIndex);
var dataLeftTop = cartesian.pointToData([selRange[0][0], selRange[1][0]], true);
var dataRightBottom = cartesian.pointToData([selRange[0][1], selRange[1][1]], true);
return [
asc([dataLeftTop[0], dataRightBottom[0]]), // x, using asc to handle inverse
asc([dataLeftTop[1], dataRightBottom[1]]) // y, using asc to handle inverse
];
}
selRange = dataZoomModel.fixRange(selRange, dataRange);
function scaleCartesianAxis(selDataRange, coordInfo, dimIdx, dimName) {
var dimCoordInfo = coordInfo[dimIdx];
var dataZoomModel = dimCoordInfo.dataZoomModel;
return (isFinite(selRange[0]) && isFinite(selRange[1]))
? {dataZoomId: dataZoomModel.id, range: selRange}
: null;
return {
dataZoomId: dataZoomModel.id,
startValue: selDataRange[dimIdx][0],
endValue: selDataRange[dimIdx][1]
};
}
/**
* @private
*/
proto._dispatchAction = function (snapshot, api) {
console.log(JSON.stringify(this._history, null, 4));
var batch = [];
each(snapshot, function (batchItem) {
......@@ -267,9 +285,11 @@ define(function(require) {
{mainType: 'dataZoom', subType: 'select', id: dataZoomId}
)[0];
if (dataZoomModel) {
var percentRange = dataZoomModel.getPercentRange();
history[0][dataZoomId] = {
dataZoomId: dataZoomId,
range: dataZoomModel.getRange()
start: percentRange[0],
end: percentRange[1]
};
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册