echarts实现自动轮播tooltip
最近需要实现echarts图形中hover效果轮播(即tooltip在各个数据点上轮流显示)的功能,以下就是我学习的一个过程,只是提供思路,具体场景需要自己修改。(仅针对echarts 2.2.7及以下版本,最后的代码有3.0以上的使用方法以及插件代码链接)
源码:https://github.com/chengwubin/echarts-tooltip-auto-show
关于echarts大家可以查看官网文档。
文档中有这么一段话:
自2.1.8起,我们为echarts开发了专门的合并压缩工具echarts-optimizer。如你所发现的,build文件夹下已经包含了由echarts-optimizer生成的单文件:
- dist(文件夹) : 经过合并、压缩的单文件
- echarts.js : 这是包含AMD加载器的echarts主文件,需要通过script最先引入
- chart(文件夹) : echarts-optimizer通过依赖关系分析同时去除与echarts.js的重复模块后为echarts的每一个图表类型单独打包生成一个独立文件,根据应用需求可实现图表类型按需加载
- line.js : 折线图(如需折柱动态类型切换,require时还需要echarts/chart/bar)
- bar.js : 柱形图(如需折柱动态类型切换,require时还需要echarts/chart/line)
- scatter.js : 散点图
- k.js : K线图
- pie.js : 饼图(如需饼漏斗图动态类型切换,require时还需要echarts/chart/funnel)
- radar.js : 雷达图
- map.js : 地图
- force.js : 力导向布局图(如需力导和弦动态类型切换,require时还需要echarts/chart/chord)
- chord.js : 和弦图(如需力导和弦动态类型切换,require时还需要echarts/chart/force)
- funnel.js : 漏斗图(如需饼漏斗图动态类型切换,require时还需要echarts/chart/pie)
- gauge.js : 仪表盘
- eventRiver.js : 事件河流图
- treemap.js : 矩阵树图
- venn.js : 韦恩图
- source(文件夹) : 经过合并,但并没有压缩的单文件,内容同dist,可用于调试
要的就是source文件下面的文件,可以调试,把source下面的echarts-all.js导入自己的工程,在找一个例子就可以运行看效果了。
<div id="chart" style="width: 800px; height: 500px;">
</div>
<span id="hover-console"></span>
<span id="console"></span> <script src="./js/echarts-all.js"></script>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts图表
var myChart = echarts.init(document.getElementById('chart'));
console.log(myChart);
var option = {
tooltip: {
show: true
},
legend: {
data:['销量']
},
xAxis : [
{
type : 'category',
data : ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
}
],
yAxis : [
{
type : 'value'
}
],
series : [
{
"name":"销量",
"type":"bar",
"data":[5, 20, 40, 10, 10, 20]
}
]
}; // 为echarts对象加载数据
myChart.setOption(option); var ecConfig = echarts.config;
function eConsole(param) {
var mes = '【' + param.type + '】';
if (typeof param.seriesIndex != 'undefined') {
mes += ' seriesIndex : ' + param.seriesIndex;
mes += ' dataIndex : ' + param.dataIndex;
}
if (param.type == 'hover') {
document.getElementById('hover-console').innerHTML = 'Event Console : ' + mes;
}
else {
document.getElementById('console').innerHTML = mes;
}
} function eHover(param) {
var mes = '【' + param.type + '】';
if (typeof param.seriesIndex != 'undefined') {
mes += ' seriesIndex : ' + param.seriesIndex;
mes += ' dataIndex : ' + param.dataIndex;
}
document.getElementById('hover-console').innerHTML = 'Event Console : ' + mes;
}
myChart.on(ecConfig.EVENT.HOVER, eHover);
</script>
先说一下大概思路,由于是canvas上面绘图,所以界面上没有对应的dom元素,所以没法用js中的事件来控制。
我们要触发事件,就需要先得到图上面的数据元素,然后再考虑怎么触发事件。
稍微看一下源码,就发现里面经常出现zrender,所以要先弄清楚zrender做什么的,查看zrender资料。
看了zrender的介绍,大概知道是用来处理canvas的绘画的,同时还封装了dom的事件(模拟)。
了解了zrender之后还是继续调试看源码,echarts-all.js文件太大,不太方便,可以下载zrender的源码查看对应的代码文件。
最开始我是想从例子中的hover事件入手,进行调试查看,最后查看到实际是mousemove事件触发的,然后发现zrender中有个storage。
查看了一下storage:
/**
* 内容仓库 (M)
* @alias module:zrender/Storage
* @constructor
*/
var Storage = function () {
// 所有常规形状,id索引的map
this._elements = {}; this._roots = []; this._displayList = []; this._displayListLen = 0;
};
是不是发现了新大陆!!!_elements,对,我们要的就是它。
但是怎么得到呢,后面在echarts中找到了getZrender(),添加代码:
var zrender = myChart.getZrender();
var elements = zrender.storage._elements;
console.log(elements);
运行后可以在console中看见elements的内容:

确实是我们想要的。
然后就是要处理触发事件了,怎么在指定坐标触发事件呢?网上查了查没查到相关信息,很多网友说的是不能再指定坐标触发事件,当时我就懵逼了!!!
但是想想,zrender里面封装了事件的,可以看看怎么从这里入手,是的,最后找到了解决办法:
zrender.trigger('mousemove', {
zrenderX: style.x,
zrenderY: style.y
});
试了下,成功了!!!!!!
说的比较粗糙,此文仅供参考,如过您有更好的方法希望能够分享出来,大家一起学习,哈哈!
下面贴上完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.chart {
height: 500px;
width: 800px;
}
</style>
</head>
<body>
<div id="chart" class="chart"> </div>
<span id="hover-console"></span>
<span id="console"></span> <script src="./js/echarts-all.js"></script>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts图表
var myChart = echarts.init(document.getElementById('chart'));
console.log(myChart);
var option = {
tooltip: {
show: true
},
legend: {
data:['销量']
},
xAxis : [
{
type : 'category',
data : ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
}
],
yAxis : [
{
type : 'value'
}
],
series : [
{
"name":"销量",
"type":"bar",
"data":[5, 20, 40, 10, 10, 20]
}
]
}; // 为echarts对象加载数据
myChart.setOption(option); var ecConfig = echarts.config;
function eHover(param) {
var mes = '【' + param.type + '】';
if (typeof param.seriesIndex != 'undefined') {
mes += ' seriesIndex : ' + param.seriesIndex;
mes += ' dataIndex : ' + param.dataIndex;
}
document.getElementById('hover-console').innerHTML = 'Event Console : ' + mes;
}
myChart.on(ecConfig.EVENT.HOVER, eHover); //可以获取有效的数据元素,数据元素属性包含坐标点和长宽(如果页面有变化需要重新获取)
var counts = option.series[0].data.length; setTimeout(function() {
autoHover();
setInterval(autoHover, 1000 * counts);
}, 1000); function autoHover() {
var zrender = myChart.getZrender();
var elements = zrender.storage._elements;
var times = 0;
console.log(elements); for (var key in elements) {
var style = elements[key].style; //根据series中的一系列name值对elements进行归类排序,然后在进行hover
//过滤条件需要完善
if (elements[key]._echartsData) {
console.log(style);
(function (style, times) {
setTimeout(function () {
zrender.trigger('mousemove', {
zrenderX: Math.ceil(style.x + style.width/2),
zrenderY: Math.ceil(style.y + style.height/2)
});
}, 1000 * times);
})(style, times); times++;
times %= counts;
}
}
}
</script>
</body>
</html>
当鼠标触发hover时要取消自动效果,这个就大家自己解决了!哈哈
第一次发文,见笑了!
PS:这个问题发现上面的处理不合适哈,echarts中提供了tooltip显示的方法,一直没更新,今天得空更新下。
为了解决有鼠标触发hover时怎么控制轮播效果的停止和开始,更细的去查看echarts和zrender的事件,看来看去感觉外部处理很困难,最后思路还是回到了tooltip上。
最后发现tooltip中其实是有提供showTip和hideTip方法,然后看echarts文档上component中的tooltip也有写这两个方法,然后添加代码:
var tooltip = myChart.component.tooltip;
//showTip方法参数请参见echarts文档
tooltip.showTip({seriesIndex: '1', dataIndex: '1'});
运行发现根本没效果(bar类型)。。。。。。。。。。。。。调试发现tooltip中showTip()源码:
if (isAxisTrigger) {
var dataIndex = params.dataIndex;
switch (chart.type) {
case ecConfig.CHART_TYPE_LINE:
case ecConfig.CHART_TYPE_BAR:
case ecConfig.CHART_TYPE_K:
case ecConfig.CHART_TYPE_RADAR:
//问题就在这儿,serie.data[0].value是什么鬼?
if (this.component.polar == null || serie.data[0].value.length <= dataIndex) {
return;
}
var polarIndex = serie.polarIndex || 0;
var vector = this.component.polar.getVector(polarIndex, dataIndex, 'max');
this._event = {
zrenderX: vector[0],
zrenderY: vector[1]
};
this._showPolarTrigger(polarIndex, dataIndex);
break;
}
}
然后在github上查看以前的版本,发现早在echarts 1.4版本中就加入了showTip()hideTip()的功能了,提交链接。
可以看见showTip():
1 + if (isAxisTrigger) {
2 + // axis trigger 3 + var dataIndex = params.dataIndex;
4 + switch (chart.type) {
5 + case ecConfig.CHART_TYPE_LINE :
6 + case ecConfig.CHART_TYPE_BAR :
7 + case ecConfig.CHART_TYPE_K :
8 + if (typeof xAxis == 'undefined'
9 + || typeof yAxis == 'undefined'
10 + || serie.data.length <= dataIndex
11 + ) {
12 + return;
13 + }
14 + var xAxisIndex = serie.xAxisIndex || 0;
15 + var yAxisIndex = serie.yAxisIndex || 0;
16 + if (xAxis.getAxis(xAxisIndex).type
17 + == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY
18 + ) {
19 + // 横轴是类目20 + _event = {
21 + zrenderX : xAxis.getAxis(xAxisIndex).getCoordByIndex(dataIndex),
22 + zrenderY : grid.getY() + (grid.getYend() - grid.getY()) / 4
23 + };
24 + }
25 + else {
26 + // 纵轴是类目27 + _event = {
28 + zrenderX : grid.getX() + (grid.getXend() - grid.getX()) / 4,
29 + zrenderY : yAxis.getAxis(yAxisIndex).getCoordByIndex(dataIndex)
30 + };
31 + }
32 + _showAxisTrigger(
33 + xAxisIndex,
34 + yAxisIndex,
35 + dataIndex
36 + );
37 + break;
38 + case ecConfig.CHART_TYPE_RADAR :
39 + if (typeof polar == 'undefined'
40 + || serie.data[0].value.length <= dataIndex
41 + ) {
42 + return;
43 + }
44 + var polarIndex = serie.polarIndex || 0;
45 + var vector = polar.getVector(polarIndex, dataIndex, 'max')
46 + _event = {
47 + zrenderX : vector[0],
48 + zrenderY : vector[1]
49 + };
50 + _showPolarTrigger(
51 + polarIndex,
52 + dataIndex
53 + );
54 + break;
55 + }
56 + }
我顺便找了一下是在2.2.2-到2.2.3版本中被改了。

下面这段代码被改过了:
switch (chart.type) {
case ecConfig.CHART_TYPE_LINE :
case ecConfig.CHART_TYPE_BAR :
case ecConfig.CHART_TYPE_K :
//应该只是想删掉这个项,结果把处理程序也删了
//case ecConfig.CHART_TYPE_TREEMAP :
if (this.component.xAxis == null
|| this.component.yAxis == null
|| serie.data.length <= dataIndex
) {
return;
}
var xAxisIndex = serie.xAxisIndex || 0;
var yAxisIndex = serie.yAxisIndex || 0;
if (this.component.xAxis.getAxis(xAxisIndex).type
=== ecConfig.COMPONENT_TYPE_AXIS_CATEGORY
) {
// 横轴是类目
this._event = {
zrenderX: this.component.xAxis.getAxis(xAxisIndex)
.getCoordByIndex(dataIndex),
zrenderY: this.component.grid.getY()
+ (this.component.grid.getYend()
- this.component.grid.getY()
) / 4
};
}
else {
// 纵轴是类目
this._event = {
zrenderX: this.component.grid.getX()
+ (this.component.grid.getXend()
- this.component.grid.getX()
) / 4,
zrenderY: this.component.yAxis.getAxis(yAxisIndex)
.getCoordByIndex(dataIndex)
};
}
this._showAxisTrigger(
xAxisIndex,
yAxisIndex,
dataIndex
);
break;
OK,把这个段删除的代码复制到你引用的echarts源码tooltip.js中,然后要合并的就重新合并压缩吧。
贴上例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.chart {
height: 500px;
width: 800px;
}
</style>
</head>
<body>
<div id="chart" class="chart"> </div>
<span id="hover-console"></span>
<span id="console"></span> <script src="./js/jquery.js"></script>
<script src="./js/echarts-all.js"></script>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts图表
var myChart = echarts.init(document.getElementById('chart')); var option = {
tooltip: {
show: true29
},
legend: {
data: ['销量']
},
xAxis: [
{
type: 'category',
data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
"name": "销量",
"type": "bar",
"data": [5, 20, 40, 10, 10, 20]
}
]
}; // 为echarts对象加载数据
myChart.setOption(option);
var timer = 0; var total = option.xAxis[0].data.length;
var count = 0;
var tooltip = myChart.component.tooltip;
function autoTip() {
timer = setInterval(function () {
var curr = count % total; //3.0以上版本的showTip使用方式
//myChart.dispatchAction({type: 'showTip', seriesIndex: '1', dataIndex: '1'});
tooltip.showTip({seriesIndex: '0', dataIndex: curr});
count += 1;
}, 1000);
}
autoTip(); var zRender = myChart.getZrender();
//mousemove和mouseout总是成对出现,而且out先出现。。。。所以没法解决鼠标hover时暂停自动tip的效果
zRender.on('mousemove', function (param) {
console.log('move')
if (timer) {
clearInterval(timer);
timer = 0;
}
});
zRender.on('mouseout', function (param) {
console.log('OUT');
if (param.event) {
//判断坐标是否在图表上,然后在处理应该可以实现
if (!timer) {
autoTip();
}
}
});
</script>
</body>
</html>
补充:
3.0以上的实现方法已经在github共享了代码,可以直接下载使用,如有问题欢迎补充纠正:
https://github.com/chengwubin/echarts-tooltip-auto-show
echarts实现自动轮播tooltip的更多相关文章
- [个人项目] echarts 实现数据(tooltip)自动轮播插件
前言 最近, 工作中要做类似这种的项目. 用到了百度的 echarts 这个开源的数据可视化的框架. 因为投屏项目不像PC端的WEB, 它不允许用户用鼠标键盘等交互. 有些图表只能看到各部分的占比情况 ...
- 使用ViewPager实现自动轮播
很多APP中都实现了类似引导页的自动轮播,不由得想到昨天的引导页上修改一下代码实现轮播. 其实大体上只需要添加一个线程循环执行就可以了. 项目已同步至:https://github.com/nanch ...
- ViewPager自动轮播
Android使用ViewPager实现左右循环滑动及轮播效果 ViewPager是一个常用的android组件,不过通常我们使用ViewPager的时候不能实现左右无限循环滑动,在滑到边界的时候 ...
- jQuery实现选项联动轮播
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 仿网易新闻 ViewPager 实现图片自动轮播
新闻 App 首页最上方一般会循环播放热点图片,如下图所示. 本文主要介绍了利用 ViewPager 实现轮播图片,图片下方加上小圆点指示器标记当前位置,并利用 Timer+Handler 实现了自动 ...
- ios - 图片自动轮播定时器(NSTimer)以及消息循环模式简介
本文只是演示如何设置图片轮播的定时器. 创建全局变量NSTimer 程序启动后就开始轮播图片,所以在- (void)viewDidLoad中就启动定时器. 将定时器放入消息循环池中.- (void)v ...
- Jquery+css实现图片无缝滚动轮播
Today,在XX学院的教学视频中,偶尔看到了Jquery+css实现图片无缝滚动轮播视频教程,虽然以前已写过类似的,但是我感觉他学的比较精简.为了方便以后做项目时直接拷贝,特地写出来,顺便和大家分享 ...
- 讲解版的自动轮播(新手福利)样式和js就不分离了为了看的方便
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- javascript焦点图左右按钮简单自动轮播
这里把css和html合在一块写了,这块代码只是布局和样式不是重点 <!DOCTYPE html> <html> <head> <meta charset=& ...
随机推荐
- Sql语法高级应用之二:视图
SQL CREATE VIEW 语句 什么是视图? 在 SQL 中,视图是基于 SQL 语句的结果集的可视化的表. 视图包含行和列,就像一个真实的表.视图中的字段就是来自一个或多个数据库中的真实的表中 ...
- EF6 使用SQLite Code First
SQLite是一款轻型关系型数据库,做一个小网站,用来替代sql server或者access数据库应该会是一个不错的选择. ASP.NET Entity Framework 6是微软平台的著名ORM ...
- java—实现一个监听器HttpServletRequest的创建销毁、在线人数 (56)
在JavaWeb中的监听器分类 在Javaweb中存在三个被监听对象: HttpServletRequest HttpSessoin ServletContext 监听者 被监听者 监听到事件对象 H ...
- 搭建一个ES6开发环境
一.首先先建立一个项目工程目录,并在目录下建立两个文件夹:src和dist src:书写ES6代码的文件夹,写的js程序都放在这里. dist:利用Babel编译成的ES5代码的文件夹,在HTML页面 ...
- [AIR] AS3操作文件时报SecurityError: fileWriteResource 错的解决方法
在用File操作(移动,删除等)或者写入文件时,以下写法会报错 var file:File =File.applicationDirectory.resolvePath("1.swf&quo ...
- wireshark 1.10.0 编译 及 协议解析部分的一些变化
wireshark不久前升级到1.10.0稳定版,这个版本正如其版本号一样,相比1.8.x有较大变化. 我们先说说在windows下编译的问题,1.8.4/1.8.6版本的编译见我的文章:http:/ ...
- [Linux] 如何在 Linux 中提取随机数
如何在 Linux 中提取随机数 一.设备文件 /dev/random & /dev/urandom 字符特殊文件 /dev/random 和 /dev/urandom (存在于Linux 1 ...
- jdk(1.8)命令行工具(二)
2.3 jinfo:java配置信息工具 jinfo(Configuration Info for Java)的作用是实时的查看和调整虚拟机的各项参数.使用jps -v 可以查看虚拟机启动时显示指定的 ...
- iOS 计算文字宽度的一个细节
设计师给到的图,经常是 "按钮的左边距离文字右边5px" 这样子的标注.于是我们需要计算文字的宽度. 有两种方法: 用 label 或 button 的 sizetofit 方法 ...
- Java中常见的jar包及其主要用途
jar包 用途 axis.jar SOAP引擎包 commons-discovery-0.2.jar 用来发现.查找和实现可插入式接口,提供一些一般类实例化.单件的生命周 ...