从0开始撸一个支持单轴轮播的雷达图之未篇(解决 Echarts 雷达图单轴轮播)
通过前面我们自己实现了一个 Radar 图,并对其实现了单轴轮播和 hover,我们已经明白了其中的坐标变换,在工作中,我们用自己写的雷达图来做产品的可能性不大,毕竟精力有限,而且和 Echarts 的图表相比,展示效果和鲁棒性都没法比。
但是我们可否用 Echarts 生成一个 radar 图,自己为其写一个 tooltip 呢,答案是肯定的。
但一切的一切前提是,要支持单轴 hover 轮播,这个 Radar 图只有一个系列。其实现的核心思想:通过实例化 Echarts 对象的 option,我们可以获取画布大小,获取标签和值,生成坐标系,算出要 hover 点的坐标,然后添加上面说的 hover 事件和自动轮播事件,直接上源码:
第一步绘制对应坐标系
/*target 添加画布的容器,option 即为 setOption 中的 Option,autoOption 用于设定是否自动轮播,是否 hover 触发,*/ function addHover(target,option,autoOption={autoShow:false,hoverEnable:true,time:1000}){ const m =Math; var center ={ //获取画布的中心偏离比,因为 echarts 支持百分数控制 radar 图在画布中的位置,所以我们需要计算这个点,当然我们也可以为了方便,不在 option 中设置,这样我们就可以直接用画布的中心点,即(0.5,0.5); pointx:(option.radar.center&&Number(option.radar.center[0].substr(0,option.radar.center[0].length-1))/100)||0.5, //计算 X 轴的偏离比例 pointy:(option.radar.center&&Number(option.radar.center[1].substr(0,option.radar.center[1].length-1))/100)||0.5, //计算 y 轴的偏离比例 }; var x=target.offsetWidth*center.pointx,y=target.offsetHeight*center.pointy; //计算 radar 中心点 x 的值,计算 radar 中心点 x 的值 var indicator = option.radar.indicator; //获取 option 中 radar 的标签 var data = option.series[0].data[0].value;//获取 option 中 radar 的值,我们在这里只去第一个 series 的值; var length = indicator.length; //获取标签的长度,即雷达的拐点数,这个很重要 var step =-1; //自动轮播要用到的参数 var hovering =false ; //这个参数是控制轮播与 hover 同时触发,显示 hover 值,暂停轮播显示 var radius=option.radar.radius,pointData=[]; //获取 radar 的半径 var style ={ //hover 显示的样式 color:'#fff', border:'1px solid rgb(51,51,51)', borderRadius:'4px', backgroundColor:'rgba(50,50,50,0.7)' }; const single = 2*m.PI /length*(-1); for(let i = 0;i<length;i++){ var ratio = data[i]/indicator[i].max; pointData.push([radius*m.sin(i*single)*ratio,radius*m.cos(i*single)*ratio]); } } /*获取鼠标在 canvas 画布上的位置(**不是浏览器窗口的鼠标位置) * clientX 获取的相对浏览器窗口左上角的位置,适用于所有浏览器 * 在 chrome 浏览器中,有一个 zrX 属性,是相对于元素本身的相对位置 * getBoundingClientRect()函数是获取元素边框相对于浏览器窗口的位置 * */ function getMousePos(canvas, event) { var rect = canvas.getBoundingClientRect(); return { x: event.clientX - rect.left , y: event.clientY - rect.top } }
创建 hover 事件和自动轮播显示标签
创建标签
let label =document.createElement('label'); label.style.position='absolute'; label.style.display='none'; target.appendChild(label); function hoverLabel(label,point,text,style){ label.style.display ='none'; label.style.top=point.y+'px'; label.style.left=point.x+'px'; label.style.border=style.border; label.style.color =style.color; label.style.borderRadius=style.borderRadius; label.style.backgroundColor = style.backgroundColor; label.style.transition ='left 0.4s cubic-bezier(0.23,1,0.32,1),top 0.4s cubic-bezier(0.23,1,0.32,1)'; label.style.zIndex = 999; label.innerHTML =text; label.style.display ='inline'; } function removeLabel(dom) { dom.style.display ='none'; }
添加轮播事件
autoOption.autoShow&&(setInterval(function () { //控制轮播 step = (step+1)%length; var showPoint={ x:pointData[step][0]+x, y:y-pointData[step][2] } var tag =indicator[step]; var text = tag.name+':'+m.round(data[step]*100/tag.max)+"%"; (!hovering)&&hoverLabel(label,showPoint,text,style); },autoOption.time||1000)); target.addEventListener('click',function(event){ console.log(event); });
添加 hover 事件
autoOption.hoverEnable&&(target.addEventListener('mousemove',function(event){ //控制 hover const canvas= target.querySelector('canvas'); const mouse = getMousePos(canvas, event); let point={}; let index =-1; const r =5; point.x=mouse.x-x; point.y=y-mouse.y; for(let i=0;i<pointData.length;i++) { let item = pointData[i]; if (point.x > (item[0] - r) && point.x < (item[0] + r) && point.y > (item[1] - r) && point.y < (item[1] + r)) { index = i; break; } } if(index!==-1){ var tag =indicator[index] var text = tag.name+':'+m.round(data[index]*100/tag.max)+"%"; hovering =true; hoverLabel(label,mouse,text,style); }else{ hovering =false; removeLabel(label); } })) }
至于调用,那就简单了
// 第一步: var ele = document.getElementById('chart'); var draw = echarts.init(ele); // 第二步:配置你的 option var option ={}; // 第三步画出你的雷达图 draw.setOption(option); // 第四步:绑定事件: addHover(ele,option,{autoShow:true,hoverEnable:true});
上面,其实只是一个简易的版本,在实际应用中,我们需要考虑很多问题。
- 图表局部刷新带来的数据重载,就上面的代码,完全不行,我们没有清除定时器,这样会找出多个 hover 重叠
- 用过 Echarts 的人,我们都知道,tooltip 有个 formatter 函数,用于显示数据的格式化,以便展示出我们想要的效果。
- 性能问题,每次 Hover 生成一个 labe 元素,是否太消耗性能,作为产品,我们应该怎样优化
- 怎样才能更通用,更方便的让人使用
基于上述问题,我对这个轮播函数做了改进和封装,使用方法是这样的:
/*Echarts 图表的正常实例化*/ var target = document.getElementById('highOpinionChart'); myChart = echarts.init(target); myChart.setOption(option); /*为图表绑定轮播事件和 Hover 事件*/ var radarAutoInfo = {hoverEnable: true, autoShow: true, time: 2000, formatter:function(v){ return v.text + ':' + (v.value*100/v.max).toFixed(2)+'%'; }}; RadarAutoTip(myChart,target, option, radarAutoInfo); //绑定 //测试停止,开始和重置方法 document.querySelector('#reset').addEventListener('click',function (e) { console.log(e); if(e.target.innerText === '停止'){ e.target.innerText ='开始' myChart.radarAutoTip.stop(); }else{ e.target.innerText = '停止'; myChart.radarAutoTip.start(); } }); document.querySelector('#rereset').addEventListener('click',function (e) { myChart.radarAutoTip.reset(); });
至此,我们就完全解决了 Echarts 单轴轮播问题。如果你嫌上面讲的太琐碎,不直观,可以直接取 github 看我的试验源码 ,文件是 radarAutoTip.html。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论