提交 d4c6cd36 编写于 作者: 1 100pah

[api] support containPixel

上级 869cf8b9
......@@ -3,10 +3,9 @@ define(function(require) {
'use strict';
var zrUtil = require('zrender/core/util');
var modelUtil = require('./util/model');
/**
* Coordinate Interface
* Interface of Coordinate System Class
*
* create:
* @param {module:echarts/model/Global} ecModel
......@@ -27,6 +26,10 @@ define(function(require) {
* @param {Object} finder
* @param {Array|number} value
* @return {Array|number} convert result.
*
* containPoint:
* @param {Array.<number>} point In pixel coordinate system.
* @return {boolean}
*/
var coordinateSystemCreators = {};
......@@ -57,43 +60,9 @@ define(function(require) {
});
},
/**
* Convert from logical coordinate system to pixel coordinate system.
* @param {string|Object} finder
* If string, e.g., 'geo', means {geoIndex: 0}.
* If Object, could contain some of these properties below:
* {
* seriesIndex, seriesId,
* geoIndex, geoId,
* bmapIndex, bmapId,
* xAxisIndex, xAxisId,
* yAxisIndex, yAxisId,
* gridIndex, gridId,
* ... (can be extended)
* }
* @param {Array|number} value
* @return {Array|number} result
*/
convertToPixel: zrUtil.curry(doConvert, 'convertToPixel'),
/**
* Convert from pixel coordinate system to logical coordinate system.
* @param {string|Object} finder
* If string, e.g., 'geo', means {geoIndex: 0}.
* If Object, could contain some of these properties below:
* {
* seriesIndex, seriesId,
* geoIndex, geoId,
* bmapIndex, bmapId,
* xAxisIndex, xAxisId,
* yAxisIndex, yAxisId,
* gridIndex, gridId,
* ... (can be extended)
* }
* @param {Array|number} value
* @return {Array|number} result
*/
convertFromPixel: zrUtil.curry(doConvert, 'convertFromPixel')
getCoordinateSystems: function () {
return this._coordinateSystems.slice();
}
};
CoordinateSystemManager.register = function (type, coordinateSystemCreator) {
......@@ -104,27 +73,5 @@ define(function(require) {
return coordinateSystemCreators[type];
};
function doConvert(methodName, ecModel, finder, value) {
finder = modelUtil.parseFinder(ecModel, finder);
var result;
var coordSysList = this._coordinateSystems;
for (var i = 0; i < coordSysList.length; i++) {
var coordSys = coordSysList[i];
if (coordSys[methodName]
&& (result = coordSys[methodName](ecModel, finder, value)) != null
) {
return result;
}
}
if (__DEV__) {
console.warn(
'No coordinate system that supports ' + methodName + ' found by the given finder.'
);
}
}
return CoordinateSystemManager;
});
\ No newline at end of file
......@@ -358,6 +358,20 @@ define(function (require) {
}, seriesModel, cb);
return clipPath;
},
/**
* @implement
*/
containPoint: function (point, seriesModel) {
var data = seriesModel.getData();
var itemLayout = data.getItemLayout(0);
if (itemLayout) {
var dx = point[0] - itemLayout.cx;
var dy = point[1] - itemLayout.cy;
var radius = Math.sqrt(dx * dx + dy * dy);
return radius <= itemLayout.r && radius >= itemLayout.r0;
}
}
});
......
......@@ -263,7 +263,15 @@ define(function (require) {
* @implements
* see {module:echarts/CoodinateSystem}
*/
convertFromPixel: zrUtil.curry(doConvert, 'pointToData')
convertFromPixel: zrUtil.curry(doConvert, 'pointToData'),
/**
* @implements
* see {module:echarts/CoodinateSystem}
*/
containPoint: function (point) {
return this.getViewRect().contain(point[0], point[1]);
}
/**
* @return {number}
......
......@@ -285,6 +285,17 @@ define(function(require, factory) {
return {cartesian: cartesian, axis: axis};
};
/**
* @implements
* see {module:echarts/CoodinateSystem}
*/
gridProto.containPoint = function (point) {
var coord = this._coordsList[0];
if (coord) {
return coord.containPoint(point);
}
};
/**
* Initialize cartesian coordinate systems
* @private
......
......@@ -422,24 +422,120 @@ define(function (require) {
* Convert from logical coordinate system to pixel coordinate system.
* See CoordinateSystem#convertToPixel.
* @param {string|Object} finder
* If string, e.g., 'geo', means {geoIndex: 0}.
* If Object, could contain some of these properties below:
* {
* seriesIndex, seriesId,
* geoIndex, geoId,
* bmapIndex, bmapId,
* xAxisIndex, xAxisId,
* yAxisIndex, yAxisId,
* gridIndex, gridId,
* ... (can be extended)
* }
* @param {Array|number} value
* @return {Array|number} result
*/
echartsProto.convertToPixel = function (finder, value) {
return this._coordSysMgr.convertToPixel(this._model, finder, value);
};
echartsProto.convertToPixel = zrUtil.curry(doConvertPixel, 'convertToPixel');
/**
* Convert from pixel coordinate system to logical coordinate system.
* See CoordinateSystem#convertFromPixel.
* @param {string|Object} finder
* If string, e.g., 'geo', means {geoIndex: 0}.
* If Object, could contain some of these properties below:
* {
* seriesIndex, seriesId,
* geoIndex, geoId,
* bmapIndex, bmapId,
* xAxisIndex, xAxisId,
* yAxisIndex, yAxisId,
* gridIndex, gridId,
* ... (can be extended)
* }
* @param {Array|number} value
* @return {Array|number} result
*/
echartsProto.convertFromPixel = function (finder, value) {
return this._coordSysMgr.convertFromPixel(this._model, finder, value);
echartsProto.convertFromPixel = zrUtil.curry(doConvertPixel, 'convertFromPixel');
function doConvertPixel(methodName, finder, value) {
var ecModel = this._model;
var coordSysList = this._coordSysMgr.getCoordinateSystems();
var result;
finder = modelUtil.parseFinder(ecModel, finder);
for (var i = 0; i < coordSysList.length; i++) {
var coordSys = coordSysList[i];
if (coordSys[methodName]
&& (result = coordSys[methodName](ecModel, finder, value)) != null
) {
return result;
}
}
if (__DEV__) {
console.warn(
'No coordinate system that supports ' + methodName + ' found by the given finder.'
);
}
}
/**
* Is the specified coordinate systems or components contain the given pixel point.
* @param {string|Object} finder
* If string, e.g., 'geo', means {geoIndex: 0}.
* If Object, could contain some of these properties below:
* {
* seriesIndex, seriesId,
* geoIndex, geoId,
* bmapIndex, bmapId,
* xAxisIndex, xAxisId,
* yAxisIndex, yAxisId,
* gridIndex, gridId,
* ... (can be extended)
* }
* @param {Array|number} value
* @return {boolean} result
*/
echartsProto.containPixel = function (finder, value) {
var ecModel = this._model;
var result;
finder = modelUtil.parseFinder(ecModel, finder);
zrUtil.each(finder, function (models, key) {
key.indexOf('Models') >= 0 && zrUtil.each(models, function (model) {
var coordSys = model.coordinateSystem;
if (coordSys && coordSys.containPoint) {
result |= !!coordSys.containPoint(value);
}
else if (key === 'seriesModels') {
var view = this._chartsMap[model.__viewId];
if (view && view.containPoint) {
result |= view.containPoint(value, model);
}
else {
if (__DEV__) {
console.warn(key + ': ' + (view
? 'The found component do not support containPoint.'
: 'No view mapping to the found component.'
));
}
}
}
else {
if (__DEV__) {
console.warn(key + ': containPoint is not supported');
}
}
}, this);
}, this);
return !!result;
};
var updateMethods = {
/**
......
......@@ -381,17 +381,23 @@ define(function(require) {
* gridIndex, gridId, gridName,
* ... (can be extended)
* }
* @param {Object} [opt]
* @param {boolean} [opt.singleResult=false]
* Each properties can be number|string|Array.<number>|Array.<string>
* For example, a finder could be
* {
* seriesIndex: 3,
* geoId: ['aa', 'cc'],
* gridName: ['xx', 'rr']
* }
* @return {Object} result like:
* {
* seriesModel: xxx,
* geoModel: xxx
* seriesModels: [seriesModel1, seriesModel2],
* seriesModel: seriesModel1, // The first model
* geoModels: [geoModel1, geoModel2],
* geoModel: geoModel1, // The first model
* ...
* }
* If opt.singleResult, result in the first found model.
*/
modelUtil.parseFinder = function (ecModel, finder, opt) {
modelUtil.parseFinder = function (ecModel, finder) {
if (zrUtil.isString(finder)) {
var obj = {};
obj[finder + 'Index'] = 0;
......@@ -400,20 +406,15 @@ define(function(require) {
var result = {};
for (var key in finder) {
if (finder.hasOwnProperty(key)) {
var value = finder[key];
key = key.match(/^(\w+)(Index|Id|Name)$/);
var queryParam = {mainType: key[1]};
queryParam[key[2].toLowerCase()] = value;
var model = ecModel.queryComponents(queryParam)[0];
result[key[1] + 'Model'] = model;
if (opt && opt.singleResult) {
return model;
}
}
}
zrUtil.each(finder, function (value, key) {
var value = finder[key];
key = key.match(/^(\w+)(Index|Id|Name)$/);
var queryParam = {mainType: key[1]};
queryParam[key[2].toLowerCase()] = value;
var models = ecModel.queryComponents(queryParam);
result[key[1] + 'Models'] = models;
result[key[1] + 'Model'] = models[0];
});
return result;
};
......
......@@ -77,6 +77,14 @@ define(function (require) {
*/
dispose: function () {}
/**
* The view contains the given point.
* @interface
* @param {Array.<number>} point
* @return {boolean}
*/
// containPoint: function () {}
};
var chartProto = Chart.prototype;
......
/* jshint maxlen:200 */
describe('api/containPixel', function() {
var utHelper = window.utHelper;
var testCase = utHelper.prepare([
'echarts/chart/pie',
'echarts/chart/map',
'echarts/chart/scatter',
'echarts/chart/graph',
'echarts/component/geo',
'echarts/component/grid',
'echarts/component/polar'
]);
var testGeoJson1 = {
'type': 'FeatureCollection',
'features': [
{
'geometry': {
'type': 'Polygon',
'coordinates': [
[
[
2000,
3000
],
[
5000,
3000
],
[
5000,
8000
],
[
2000,
8000
]
]
]
},
'properties': {
'name': 'Afghanistan',
'childNum': 1
}
}
]
};
var testGeoJson2 = {
'type': 'FeatureCollection',
'features': [
{
'geometry': {
'type': 'Polygon',
'coordinates': [
[
[
200,
300
],
[
500,
300
],
[
500,
800
],
[
200,
800
]
]
]
},
'properties': {
'name': 'Afghanistan',
'childNum': 1
}
}
]
};
testCase.createChart()('geo', function () {
this.echarts.registerMap('test1', testGeoJson1);
this.echarts.registerMap('test2', testGeoJson2);
var chart = this.chart;
chart.setOption({
geo: [
{
id: 'aa',
left: 10,
right: '50%',
top: 30,
bottom: 40,
map: 'test1'
},
{
id: 'bb',
layoutCenter: ['50%', 50],
layoutSize: 20,
aspectScale: 1,
map: 'test2'
}
],
series: [
{id: 'k1', type: 'scatter', coordinateSystem: 'geo', geoIndex: 1},
{id: 'k2', type: 'scatter', coordinateSystem: 'geo'}
]
});
var width = chart.getWidth();
expect(chart.containPixel('geo', [15, 30])).toEqual(true);
expect(chart.containPixel('geo', [9.5, 30])).toEqual(false);
expect(chart.containPixel({geoIndex: 1}, [width / 2, 50])).toEqual(true);
expect(chart.containPixel({geoIndex: 1}, [10, 20])).toEqual(false);
});
testCase.createChart()('map', function () {
this.echarts.registerMap('test1', testGeoJson1);
this.echarts.registerMap('test2', testGeoJson2);
var chart = this.chart;
chart.setOption({
series: [
{
id: 'k1',
type: 'map',
map: 'test1',
left: 10,
right: '50%',
top: 30,
bottom: 40
},
{
id: 'k2',
type: 'map',
map: 'test2',
layoutCenter: ['50%', 50],
layoutSize: 20,
aspectScale: 1
}
]
});
var width = chart.getWidth();
expect(chart.containPixel('series', [15, 30])).toEqual(true);
expect(chart.containPixel('series', [9.5, 30])).toEqual(false);
expect(chart.containPixel({seriesId: 'k2'}, [width / 2, 50])).toEqual(true);
expect(chart.containPixel({seriesId: 1}, [10, 20])).toEqual(false);
});
testCase.createChart()('cartesian', function () {
this.echarts.registerMap('test1', testGeoJson1);
var chart = this.chart;
chart.setOption({
geo: [ // Should not affect grid converter.
{
map: 'test1'
}
],
grid: [
{
id: 'g0',
left: 10,
right: '50%',
top: 30,
bottom: 40
},
{
id: 'g1',
left: '50%',
right: 20,
top: 30,
bottom: 40
}
],
xAxis: [
{
id: 'x0',
type: 'value',
min: -500,
max: 3000,
gridId: 'g0'
},
{
id: 'x1',
type: 'value',
min: -50,
max: 300,
gridId: 'g0'
},
{
id: 'x2',
type: 'value',
min: -50,
max: 300,
gridId: 'g1'
}
],
yAxis: [
{
id: 'y0',
type: 'value',
min: 6000,
max: 9000,
gridId: 'g0'
},
{
id: 'y1',
type: 'value',
inverse: true, // test inverse
min: 600,
max: 900,
gridId: 'g1'
}
],
series: [
{
id: 'k1',
type: 'scatter',
left: 0,
right: 0,
top: 0,
bottom: 0,
data: [[1000, 700]]
},
{
id: 'k2',
type: 'scatter',
left: 0,
right: 0,
top: 0,
bottom: 0,
data: [[100, 800]]
},
{
id: 'j1',
type: 'scatter',
left: 0,
right: 0,
top: 0,
bottom: 0,
data: [[100, 800]],
xAxisIndex: 1
},
{
id: 'i1',
type: 'scatter',
left: 0,
right: 0,
top: 0,
bottom: 0,
data: [],
xAxisId: 'x2',
yAxisId: 'y1'
}
]
});
var width = chart.getWidth();
expect(chart.containPixel('grid', [15, 30])).toEqual(true);
expect(chart.containPixel('grid', [9.5, 30])).toEqual(false);
expect(chart.containPixel({gridIndex: 1}, [width / 2, 50])).toEqual(true);
expect(chart.containPixel({gridIndex: 1}, [10, 20])).toEqual(false);
});
testCase.createChart()('pie', function () {
var chart = this.chart;
chart.setOption({
series: [
{
id: 'k1',
type: 'pie',
center: [40, '50%'],
radius: [10, '50%'],
data: [
{x: 1000, y: 2000},
{x: 1000, y: 5000},
{x: 3000, y: 5000},
{x: 3000, y: 2000}
],
links: []
}
]
});
var height = chart.getHeight();
expect(chart.containPixel('series', [40, height / 2])).toEqual(false);
expect(chart.containPixel('series', [40, height / 2 + 10])).toEqual(true);
expect(chart.containPixel('series', [9.5, 1])).toEqual(false);
});
testCase.createChart()('pieAndGeo', function () {
this.echarts.registerMap('test1', testGeoJson1);
this.echarts.registerMap('test2', testGeoJson2);
var chart = this.chart;
chart.setOption({
geo: [
{
id: 'aa',
left: 10,
top: 10,
width: 10,
height: 10,
map: 'test1'
},
{
id: 'bb',
left: 100,
top: 10,
width: 10,
height: 10,
map: 'test2'
}
],
series: [
{id: 'k1', type: 'scatter', coordinateSystem: 'geo', geoIndex: 1},
{id: 'k2', type: 'scatter', coordinateSystem: 'geo'},
{
id: 'k3',
type: 'pie',
center: [40, 100],
radius: [3, 10],
data: [
{x: 1000, y: 2000},
{x: 1000, y: 5000}
],
links: []
}
]
});
expect(chart.containPixel({geoIndex: [0, 1], seriesId: 'k3'}, [15, 15])).toEqual(true);
expect(chart.containPixel({geoIndex: [0, 1], seriesId: 'k3'}, [15, 25])).toEqual(false);
expect(chart.containPixel({geoIndex: [0, 1], seriesId: 'k3'}, [105, 15])).toEqual(true);
expect(chart.containPixel({geoIndex: [0, 1], seriesId: 'k3'}, [105, 25])).toEqual(false);
expect(chart.containPixel({geoIndex: [0, 1], seriesId: 'k3'}, [45, 100])).toEqual(true);
expect(chart.containPixel({geoIndex: [0, 1], seriesId: 'k3'}, [55, 100])).toEqual(false);
});
testCase.createChart()('graph', function () {
this.echarts.registerMap('test1', testGeoJson1);
var chart = this.chart;
chart.setOption({
geo: [ // Should not affect graph converter.
{
map: 'test1'
}
],
series: [
{
id: 'k1',
type: 'graph',
left: 10,
right: '50%',
top: 30,
bottom: 40,
data: [
{x: 1000, y: 2000},
{x: 1000, y: 5000},
{x: 3000, y: 5000},
{x: 3000, y: 2000}
],
links: []
}
]
});
expect(chart.containPixel('series', [15, 35])).toEqual(true);
expect(chart.containPixel('series', [3, 4])).toEqual(false);
});
});
\ No newline at end of file
......@@ -8,6 +8,7 @@ document.write('<script src="spec/model/Component.js"><\/script>');
document.write('<script src="spec/model/Global.js"><\/script>');
document.write('<script src="spec/model/timelineOptions.js"><\/script>');
document.write('<script src="spec/api/converter.js"><\/script>');
document.write('<script src="spec/api/containPixel.js"><\/script>');
document.write('<script src="spec/data/List.js"><\/script>');
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册