提交 0f17e9c6 编写于 作者: L lang

Axis pointer of tooltip

上级 ec08c772
define(function (require) {
var TooltipContent = require('./tooltip/TooltipContent');
var zrUtil = require('zrender/core/util');
var graphic = require('../util/graphic');
function getAxisPointerKey(coordName, axisType) {
return coordName + axisType;
}
require('./tooltip/TooltipModel');
......@@ -9,15 +13,19 @@ define(function (require) {
type: 'tooltip',
init: function (ecModel, api) {
var zr = api.getZr();
_axisPointers: {},
zr.on('mousemove', this._mouseMove, this);
init: function (ecModel, api) {
api.getZr().on('mousemove', this._mouseMove, this);
this._tooltipContent = new TooltipContent(api.getDom());
},
render: function (tooltipModel, ecModel, api) {
// Reset
this.group.clear();
this._axisPointers = {};
this._tooltipModel = tooltipModel;
this._ecModel = ecModel;
......@@ -36,19 +44,21 @@ define(function (require) {
return;
}
if (!el || !el.data) {
if (trigger === 'item') {
this._tooltipContent.hideLater(tooltipModel.get('hideDelay'));
if (!el || !el.data) {
return;
}
this._tooltipContent.hideLater(tooltipModel.get('hideDelay'));
var dataItem = el.data;
return;
}
var dataItem = el.data;
if (trigger === 'item') {
this._showItemTooltip(dataItem, e);
}
else {
this._showAxisTooltip(e);
}
},
......@@ -60,7 +70,140 @@ define(function (require) {
_showAxisTooltip: function (e) {
var ecModel = this._ecModel;
ecModel.eachSeries(function (seriesModel) {
// Try show the axis pointer
this.group.show();
var coordinateSystem = seriesModel.coordinateSystem;
// If mouse position is not in the grid or polar
var point = [e.offsetX, e.offsetY];
if (coordinateSystem && ! coordinateSystem.containPoint(point)) {
// Hide axis pointer
this._hideAxisTooltip();
return;
}
if (coordinateSystem.type === 'cartesian2d') {
this._showCartesianAxis(coordinateSystem, point);
}
else if (coordinateSystem.type === 'polar') {
this._showPolarAxis(coordinateSystem, point);
}
}, this)
},
/**
* Show tooltip on axis of cartesian coordinate
* @param {Object} e
*/
_showCartesianAxis: function (cartesian, point) {
var self = this;
var tooltipModel = this._tooltipModel;
var axisPointerModel = tooltipModel.getModel('axisPointer');
var cateogryAxis = cartesian.getAxesByScale('ordinal')[0];
var axisPointerType = axisPointerModel.get('type');
var value = cartesian.pointToData(point);
// Make sure point is discrete on cateogry axis
if (cateogryAxis) {
point = cartesian.dataToPoint(value);
}
if (axisPointerType === 'line') {
var axisType = axisPointerModel.get('axis');
if (axisType === 'auto') {
axisType = (cateogryAxis && cateogryAxis.dim) || 'x';
}
var pointerAxis = cartesian.getAxis(axisType);
var otherAxis = cartesian.getOtherAxis(pointerAxis);
var otherExtent = otherAxis.getExtent();
moveLine(axisType, point, otherExtent);
}
else if (axisPointerType === 'cross') {
moveLine('x', point, cartesian.getAxis('y').getExtent());
moveLine('y', point, cartesian.getAxis('x').getExtent());
}
else if (axisPointerType === 'shadow') {
}
function moveLine(axisType, point, otherExtent) {
var pointerEl = self._getPointerElement(cartesian, axisPointerModel, axisType)
var targetShape;
if (axisType === 'x') {
targetShape = {
x1: point[0],
y1: otherExtent[0],
x2: point[0],
y2: otherExtent[1]
};
}
else {
targetShape = {
x1: otherExtent[0],
y1: point[1],
x2: otherExtent[1],
y2: point[1]
};
}
// pointerEl.animateTo({
// shape: targetShape
// }, 100, 'cubicOut');
pointerEl.attr({
shape: targetShape
})
}
},
/**
* Show tooltip on axis of polar coordinate
* @param {Object} e
*/
_showPolarAxis: function () {
},
/**
* Hide axis tooltip
*/
_hideAxisTooltip: function () {
this.group.hide();
},
_getPointerElement: function (coordSystem, pointerModel, axisType) {
var axisPointers = this._axisPointers;
var key = getAxisPointerKey(coordSystem.name, axisType);
if (axisPointers[key]) {
return axisPointers[key];
}
// Create if not exists
var pointerType = pointerModel.get('type');
var styleModel = pointerModel.getModel(pointerType + 'Style');
var isShadow = pointerType === 'shadow';
var style = styleModel[isShadow ? 'getAreaStyle' : 'getLineStyle']();
var elementType = axisType === 'radius'
? (isShadow ? 'Sector' : 'Circle')
: (isShadow ? 'Rect' : 'Line');
var el = axisPointers[key] = new graphic[elementType]({
style: style,
silent: true
});
this.group.add(el);
return el;
},
/**
......
......@@ -5,44 +5,88 @@ define(function (require) {
type: 'tooltip',
defaultOption: {
zlevel: 1, // 一级层叠,频繁变化的tooltip指示器在pc上独立一层
z: 8, // 二级层叠
// 一级层叠,频繁变化的tooltip指示器在pc上独立一层
zlevel: 1,
// 二级层叠
z: 8,
show: true,
showContent: true, // tooltip主体内容
trigger: 'item', // 触发类型,默认数据触发,见下图,可选为:'item' ¦ 'axis'
// tooltip主体内容
showContent: true,
// 触发类型,默认数据触发,见下图,可选为:'item' ¦ 'axis'
trigger: 'item',
// If the tooltip follow the mouse position
// TODO
// followMouse: true,
// position: null // 位置 {Array} | {Function}
// formatter: null // 内容格式器:{string}(Template) ¦ {Function}
islandFormatter: '{a} <br/>{b} : {c}', // 数据孤岛内容格式器
showDelay: 20, // 显示延迟,添加显示延迟可以避免频繁切换,单位ms
hideDelay: 100, // 隐藏延迟,单位ms
transitionDuration: 0.4, // 动画变换时间,单位s
// 位置 {Array} | {Function}
// position: null
// 内容格式器:{string}(Template) ¦ {Function}
// formatter: null
// 数据孤岛内容格式器
islandFormatter: '{a} <br/>{b} : {c}',
// 显示延迟,添加显示延迟可以避免频繁切换,单位ms
showDelay: 20,
// 隐藏延迟,单位ms
hideDelay: 100,
// 动画变换时间,单位s
transitionDuration: 0.4,
enterable: false,
backgroundColor: 'rgba(0,0,0,0.7)', // 提示背景颜色,默认为透明度为0.7的黑色
borderColor: '#333', // 提示边框颜色
borderRadius: 4, // 提示边框圆角,单位px,默认为4
borderWidth: 0, // 提示边框线宽,单位px,默认为0(无边框)
padding: 5, // 提示内边距,单位px,默认各方向内边距为5,
// 接受数组分别设定上右下左边距,同css
axisPointer: { // 坐标轴指示器,坐标轴触发有效
type: 'line', // 默认为直线,可选为:'line' | 'shadow' | 'cross'
lineStyle: { // 直线指示器样式设置
// 提示背景颜色,默认为透明度为0.7的黑色
backgroundColor: 'rgba(0,0,0,0.7)',
// 提示边框颜色
borderColor: '#333',
// 提示边框圆角,单位px,默认为4
borderRadius: 4,
// 提示边框线宽,单位px,默认为0(无边框)
borderWidth: 0,
// 提示内边距,单位px,默认各方向内边距为5,
// 接受数组分别设定上右下左边距,同css
padding: 5,
// 坐标轴指示器,坐标轴触发有效
axisPointer: {
// 默认为直线
// 可选为:'line' | 'shadow' | 'cross'
type: 'line',
// type 为 line 的时候有效,指定 tooltip line 所在的轴,可选
// 可选 'x' | 'y' | 'angle' | 'radius' | 'auto'
// 默认 'auto',会选择类型为 cateogry 的轴,对于双数值轴,笛卡尔坐标系会默认选择 x 轴
// 极坐标系会默认选择 angle 轴
axis: 'auto',
// 直线指示器样式设置
lineStyle: {
color: '#48b',
width: 2,
type: 'solid'
},
crossStyle: {
color: '#1e90ff',
width: 1,
type: 'dashed'
},
shadowStyle: { // 阴影指示器样式设置
color: 'rgba(150,150,150,0.3)', // 阴影颜色
width: 'auto', // 阴影大小
// 阴影指示器样式设置
shadowStyle: {
color: 'rgba(150,150,150,0.3)',
width: 'auto',
type: 'default'
}
},
......
......@@ -56,30 +56,31 @@ define(function (require) {
*/
contain: function (coord) {
var extent = this._extent;
return coord >= extent[0] && coord <= extent[1];
var min = Math.min(extent[0], extent[1]);
var max = Math.max(extent[0], extent[1]);
return coord >= min && coord <= max;
},
/**
* Get coord extent
* Get coord extent.
* @return {Array.<number>}
*/
getExtent: function () {
var ret = this._extent.slice();
if (this.inverse) {
ret.reverse();
}
this.inverse && ret.reverse();
return ret;
},
/**
* Set coord extent
* @param {number} start
* @param {number} end
* @param {number} min
* @param {number} max
*/
setExtent: function (start, end) {
setExtent: function (min, max) {
var extent = this._extent;
extent[0] = start;
extent[1] = end;
extent[0] = min;
extent[1] = max;
},
/**
......@@ -105,18 +106,18 @@ define(function (require) {
/**
* Convert coord to data. Data is the rank if it has a ordinal scale
* @param {number} mapped
* @param {number} coord
* @param {boolean} clamp
* @return {number}
*/
coordToData: function (mapped, clamp) {
coordToData: function (coord, clamp) {
var extent = this.getExtent();
if (this.onBand) {
fixExtentWithBands(extent, this.scale.count());
}
var t = linearMap(mapped, extent, [0, 1], clamp);
var t = linearMap(coord, extent, [0, 1], clamp);
return this.scale.scale(t);
},
......
......@@ -101,7 +101,7 @@ define(function (require) {
for (var i = 0; i < dimList.length; i++) {
var dim = dimList[i];
var axis = this._axes[axis];
var axis = this._axes[dim];
output[dim] = axis[method](input[dim]);
}
......
......@@ -17,9 +17,9 @@ define(function(require) {
/**
* If contain point
*/
containPoint: function (x, y) {
return this.getAxis('x').contain(x)
&& this.getAxis('y').contain(y);
containPoint: function (point) {
return this.getAxis('x').contain(point[0])
&& this.getAxis('y').contain(point[1]);
},
/**
......@@ -30,17 +30,34 @@ define(function(require) {
* `[[10, 10], [20, 20], [30, 30]]`
*/
dataToPoints: function (data) {
var xAxis = this.getAxis('x');
var yAxis = this.getAxis('y');
return data.map(function (dataItem) {
var coord = [];
coord[0] = xAxis.dataToCoord(dataItem.getX(true));
coord[1] = yAxis.dataToCoord(dataItem.getY(true));
return coord;
// PENDGING `MUST` Stack ?
return this.dataToPoint([dataItem.getX(true), dataItem.getY(true)]);
}, this);
},
/**
* @param {Array.<number>} data
* @return {Array.<number>}
*/
dataToPoint: function (data) {
return [
this.getAxis('x').dataToCoord(data[0]),
this.getAxis('y').dataToCoord(data[1])
];
},
/**
* @param {Array.<number>} point
* @return {Array.<number>}
*/
pointToData: function (point) {
return [
this.getAxis('x').coordToData(point[0]),
this.getAxis('y').coordToData(point[1])
];
},
/**
* Get other axis
* @param {module:echarts/coord/cartesian/Axis2D} axis
......
......@@ -83,7 +83,7 @@ define(function(require) {
*/
dataToPoints: function (data) {
return data.map(function (dataItem) {
return this.dataToCoord([dataItem.getRadius(true), dataItem.getAngle(true)]);
return this.dataToPoint([dataItem.getRadius(true), dataItem.getAngle(true)]);
}, this);
},
......
define({
getAreaStyle: function () {
return require('./makeStyleMapper')(
define(function (require) {
return {
getAreaStyle: require('./makeStyleMapper')(
[
['fill', 'color'],
['shadowBlur'],
......@@ -8,6 +8,6 @@ define({
['shadowOffsetY'],
['shadowColor']
]
);
}
)
};
});
\ No newline at end of file
......@@ -41,6 +41,15 @@ define(function (require) {
type: 'interval',
/**
* If scale extent contain give value
* @param {number}
*/
contain: function (pos) {
var extent = this._extent;
return pos >= extent[0] && pos <= extent[1];
},
/**
* Normalize value to linear [0, 1]
* @param {number} val
......
......@@ -32,6 +32,15 @@ define(function (require) {
type: 'ordinal',
/**
* If scale extent contain give value
* @param {number}
*/
contain: function (rank) {
var extent = this._extent;
return rank >= extent[0] && rank <= extent[1] && this._list[rank] != null;
},
/**
* Normalize given rank to linear [0, 1]
* @return {number} [val]
......@@ -46,7 +55,7 @@ define(function (require) {
},
/**
* Scale normalized value
* Scale normalized value to rank
* @param {number} val
* @return {number}
*/
......
......@@ -18,7 +18,8 @@
'echarts',
'echarts/chart/line',
'echarts/component/legend',
'echarts/component/grid'
'echarts/component/grid',
'echarts/component/tooltip'
], function (echarts) {
var chart = echarts.init(document.getElementById('main'), null, {
......@@ -30,44 +31,72 @@
var data2 = [];
var data3 = [];
for (var i = 0; i < 20; i++) {
for (var i = 0; i < 10; i++) {
xAxisData.push('类目' + i);
data1.push(Math.random());
data2.push(Math.random());
data3.push(Math.random());
data1.push(+Math.random().toFixed(3));
data2.push(+Math.random().toFixed(3));
data3.push(+Math.random().toFixed(3));
}
var itemStyle = {
normal: {
borderColor: 'white',
borderWidth: 3,
shadowBlur: 10,
shadowOffsetX: 0,
shadowOffsetY: 5,
shadowColor: 'rgba(0, 0, 0, 0.4)',
lineStyle: {
width: 3,
shadowBlur: 10,
shadowOffsetX: 0,
shadowOffsetY: 5,
shadowColor: 'rgba(0, 0, 0, 0.4)'
}
}
};
chart.setOption({
legend: {
data: ['line', 'line2', 'line3']
},
tooltip: {
trigger: 'axis'
},
xAxis: {
// data: ['类目1', '类目2', '类目3', '类目4', '类目5',]
data: xAxisData
data: xAxisData,
boundaryGap: false
},
yAxis: {
splitLine: {
show: false
// show: false
}
},
series: [{
name: 'line',
type: 'line',
stack: 'all',
symbol: 'circle',
symbolSize: 10,
data: data1
data: data1,
itemStyle: itemStyle
}, {
name: 'line2',
type: 'line',
stack: 'all',
symbol: 'circle',
symbolSize: 10,
data: data2
data: data2,
itemStyle: itemStyle
}, {
name: 'line3',
type: 'line',
stack: 'all',
symbol: 'circle',
symbolSize: 10,
data: data3
data: data3,
itemStyle: itemStyle
}]
});
})
......
......@@ -18,7 +18,8 @@
'echarts',
'echarts/chart/scatter',
'echarts/component/legend',
'echarts/component/grid'
'echarts/component/grid',
'echarts/component/tooltip'
], function (echarts) {
var chart = echarts.init(document.getElementById('main'), null, {
......@@ -39,11 +40,20 @@
legend: {
data: ['scatter', 'scatter2', 'scatter3']
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
xAxis: {
type: 'value',
splitLine: {
show: false
}
},
min: 0,
max: 15,
splitNumber: 30
},
yAxis: {
type: 'value',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册