今天要用到的理论在前两篇都讲过,如果你错过了前两篇,你应该先看看。
从0开始写一个支持单轴轮播的雷达图之首篇
从0开始写一个支持单轴轮播的雷达图之中篇
前言
通过前面我们自己实现了一个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,欢迎star
本文首发于:http://closertb.site ,转载请注明
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。