最近需要实现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的更多相关文章

  1. [个人项目] echarts 实现数据(tooltip)自动轮播插件

    前言 最近, 工作中要做类似这种的项目. 用到了百度的 echarts 这个开源的数据可视化的框架. 因为投屏项目不像PC端的WEB, 它不允许用户用鼠标键盘等交互. 有些图表只能看到各部分的占比情况 ...

  2. 使用ViewPager实现自动轮播

    很多APP中都实现了类似引导页的自动轮播,不由得想到昨天的引导页上修改一下代码实现轮播. 其实大体上只需要添加一个线程循环执行就可以了. 项目已同步至:https://github.com/nanch ...

  3. ViewPager自动轮播

    Android使用ViewPager实现左右循环滑动及轮播效果   ViewPager是一个常用的android组件,不过通常我们使用ViewPager的时候不能实现左右无限循环滑动,在滑到边界的时候 ...

  4. jQuery实现选项联动轮播

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 仿网易新闻 ViewPager 实现图片自动轮播

    新闻 App 首页最上方一般会循环播放热点图片,如下图所示. 本文主要介绍了利用 ViewPager 实现轮播图片,图片下方加上小圆点指示器标记当前位置,并利用 Timer+Handler 实现了自动 ...

  6. ios - 图片自动轮播定时器(NSTimer)以及消息循环模式简介

    本文只是演示如何设置图片轮播的定时器. 创建全局变量NSTimer 程序启动后就开始轮播图片,所以在- (void)viewDidLoad中就启动定时器. 将定时器放入消息循环池中.- (void)v ...

  7. Jquery+css实现图片无缝滚动轮播

    Today,在XX学院的教学视频中,偶尔看到了Jquery+css实现图片无缝滚动轮播视频教程,虽然以前已写过类似的,但是我感觉他学的比较精简.为了方便以后做项目时直接拷贝,特地写出来,顺便和大家分享 ...

  8. 讲解版的自动轮播(新手福利)样式和js就不分离了为了看的方便

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  9. javascript焦点图左右按钮简单自动轮播

    这里把css和html合在一块写了,这块代码只是布局和样式不是重点 <!DOCTYPE html> <html> <head> <meta charset=& ...

随机推荐

  1. .net程序员书单

    C# 基础 <CLR via C#> <c# 高级编程> 框架学习 <WPF编程宝典 > (英文名:<Pro WPF 4.5 in C#. Windows P ...

  2. deepin获取root权限

    ctrk+alt+t 打开终端 输入 sudo passwd root mywork@mywork-PC:~$ sudo passwd root[sudo] mywork 的密码: [sudo] 输入 ...

  3. 3-C#面向对象概念

    本篇博客对应视频讲解 回顾 前两篇博文带大家快速的感知一下使用C#编写程序是怎样的过程,能实现什么样的功能.同时也提到了面向对象的概念.本篇文章就是更加详细的去将面向对象编程中常见的概念进行示例说明, ...

  4. windows server 2008 站点系列--AD的站点建立与子网的管理(zhuanzai)

    本次课程将给大家介绍AD中站点和子网的功能.站点和子网之间的关联,以及相关的设置步骤. 应用背景介绍: contoso公司的总部在西安(Xian),陕南的汉中(Shannan)和陕北的榆林(Shanb ...

  5. winform textbox控件keydown、keypress、keyup简单介绍

    1.执行先后顺序: keydown-->keypress-->keyup 2.按键相关操作: 1)keydown和keyup参数类型KeyEventArgs(提供了KeyCode)实现形式 ...

  6. K - 欧拉回路(并查集)

    点击打开链接 K - 欧拉回路 欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路.现给定一个图,问是否存在欧拉回路? Input 测试输入包含若干测试用例.每个测试用例的第 ...

  7. [Swift实际操作]七、常见概念-(13)使用UIScreen查询设备屏幕信息

    本文将为你演示,如何获得设备的屏幕信息,了解设备的屏幕尺寸等信息,才能做出适配性更好的应用程序. 首先导入需要使用到的界面工具框架 import UIKit 然后通过UIScreen类,就可以获得设备 ...

  8. linux下查找命令总结

    查找命令总结,which,whereis,find,locate,type http://blog.csdn.net/jessica1201/article/details/8139249   1.f ...

  9. python基础知识梳理-----1变量,常量,注释

    因为公司用的是delphi ,所以自学了一阵delphi,但是随着语言的发展,delphi的前景堪忧啊.辞职以后打算好好学学python,然后找找数据分析和爬虫方面的工作. 记录此贴,仅作学习使用,所 ...

  10. gitlab的简单使用

    mkdir folder //创建文件夹 cd folder/ git clone git连接 git status //git当前的状态 ls //当前目录下的所有文件 cd gitFolder 进 ...