资讯专栏INFORMATION COLUMN

从0开始撸一个支持单轴轮播的雷达图之加强篇(解决Echarts单轴轮播问题)

xcold / 3191人阅读

摘要:如果你嫌上面太琐碎,可以直接取看我的试验源码,文件是欢迎本文后续从开始撸一个支持单轴轮播的雷达图之末篇本文首发于

在线示例
如果你还不了解canvas,还不知道要讲啥,建议从首篇看起:从0开始写一个支持单轴轮播的雷达图
在首篇我们已经讲了怎么实现轮播,在这里我们将要用这一篇文章来说一下雷达图的单轴hover效果的实现,也是我写这篇文章的原因,因为echarts只支持单个series的hover。而我想要的是支持下面的效果:单轴hover。如果你只想知道怎么解决Echarts单轴轮播问题,并且你足够机智,你可以直接看最后一节。

理清思路

如果你用过Echarts的radar图,如果你去看过生成雷达图形成的dom结构,你hover后会发现如下图所示

有没有一种恍然大悟的感觉,其实就是在这画布的容器(我们称其为target)里里,添加了一个dom元素,来显示提示词。而这个dom元素的定位是绝对定位,定位点是根据hover捕获点在画布上的left和top计算值,然后显示生成的tooltip值;所以我们可以思考,要达到前面这几句话,我们需要提前做以下几步:
1、绑定一个鼠标移动事件,并试图捕捉画布上的拐点;
2、根据捕捉的点,获取相应的数据(标签,数值);
3:生成一个div元素(也可以是label这些元素),并设定位置,样式,及显示值,并添加到容器中,大功告成;

step by step

原谅我用了个英文单词,我确实不知道该用个什么标题。
如果你细心看过首篇的每一个实现步骤,并且理解整体思路,那接下来,事情会简单很多。因为无论哪个js插件画雷达图,前面的几步都是必须的,其核心除了canvas,其实就是计算和坐标转换,即将一块高为width,宽为height的dom元素变成一张拥有直角坐标系的画布,就像下面这个简图:

绑定事件,并获取相对位置坐标点

我们为这个target元素绑定一个click事件,然后

     
const draw = document.getElementById("canvas"); const ctx = draw.getContext("2d"); /*获取鼠标在canvas画布上的位置(**不是浏览器窗口的鼠标位置) * clientX获取的相对浏览器窗口左上角的位置,适用于所有浏览器 * 在chrome浏览器中,有一个zrX属性,是相对于元素本身的相对位置 * getBoundingClientRect()函数是获取元素边框相对于浏览器窗口的位置 * */ function getMousePos(canvas, event) { var rect = canvas.getBoundingClientRect(); return { x: event.clientX - rect.left , y: event.clientY - rect.top } } draw.addEventListener("click",function(event){ console.log(getMousePos(draw,event)); //打印得到的,就是鼠标点击位置相对于canvas容器元素左上角的坐标值,而不是相对于浏览器窗口。 });

如果你还不明白,你可以试着拷贝代码,建立一个html页面尝试一下

根据获取的坐标点,判断是不是需要捕捉的点

你有可能会疑问,就算捕捉了这个点,那怎么才能判断这个点是不是需要捕捉的拐点呢?答案是,前面绘制这个拐点的时候,我们已经记录下了这个拐点在坐标位置,所以我们只需要将点击获取到的像素(px)值,转化为建立的坐标系坐标,我们就能轻易判断是不是拐点了,当然为了实现的灵敏度,我们需要给其配一个误差值,保证在拐点某个面积内都能触发这个hover。代码中有较多注释,具体看代码实现:

function addListener(dom,canvas,pointData){
    //获取鼠标在canvas画布上的位置(**不是浏览器窗口的鼠标位置)
    function getMousePos(canvas, evt) { //canvas就是dom中的canvas元素
        var rect = canvas.getBoundingClientRect();
        return {
            x: evt.clientX - rect.left * (canvas.width / rect.width),
            y: evt.clientY - rect.top * (canvas.height / rect.height)
        }
    }
    dom.addEventListener("click",function (evt) { //开始测试建议用点击,后面弄清楚了改成mousemove事件就ok
        const mouse = getMousePos(canvas, evt);
        let point={};
        let text = "";
        let index =-1;
        const r =5; //这个r就是那个允许的误差值,值越大,越容易触发hover
        point.x=mouse.x-offset.x/2; //offset的值就是画布的长和宽值,利用他们的中心点,可以计算鼠标点击位置在坐标系中的坐标值;
        point.y=mouse.y-offset.y/2;//同上
        for(let i=0;i (item[0] - r) && point.x < (item[0] + r) && point.y > (item[1] - r) && point.y < (item[1] + r)) {
                index = i; //满足条件,就记录下这个值,用于后面单轴显示
                break;
            }
        }
        if(index!==-1){
            hoverLabel(dom,mouse,index);  //在下一步,我们将实现这个方法
        }else{
            removeLabel(dom);//当然,我们也将顺便实现这个方法
        }
    })
生成一个div元素,显示相应展示的轮播值

当我们生成一个div,并试图定位将其添加到画布容器中显示出来时,你需要明白下面两点:
1:这个div需要绝对定位,装他的容器需要一个非static定位;
2:装这个div的元素是装canvas容器的元素,而不是canvas,添加到canvas中 ,你将什么也看不到;
这个实现较简单,就直接看源码吧

  /*dom 即要添加div的容器,point即触发hover事件的位置,是位置,不是变换后的坐标,text即要显示的值*/
function hoverLabel(dom,point,text){ 
    removeLabel(dom);//生成前先判断有无,有就移除这个显示标签
    let label =document.createElement("div");
    label.style.position="absolute";
    label.style.top=point.y+"px";
    label.style.left=point.x+"px";
    label.style.border="1px solid yellowgreen";
    label.style.background = "gray";
    label.style.zIndex = 999;

    label.innerHTML ="show:0999"+text;
    dom.appendChild(label);
}
function removeLabel(dom) {  //移除这个显示标签
  (dom.querySelectorAll("label").length)&&(dom.removeChild(dom.querySelector("label")));  //有就删除,没有就不动作
}

提示,我们也可以提前生成一个标签元素,将其添加到画布容器中,并不显示它,后面我们只需动态改变它的位置和内容。
至此,我们已经完成了单轴的hover,也就是下面这种效果图


到这里,似乎该告一段落了,但好戏才要真正开始,我们的标题是解决Echarts单轴轮播,我不是一个标题党,所以接下来,将要讨论这个有趣的话题。

解决Echarts单轴轮播问题

通过上面我们已经自己实现了一个Radar图,并对其实现了单轴轮播和hover,我们已经明白了其中的坐标变换,所以我们可否用Echarts生成一个radar图,自己为其写一个tooltip呢,答案是必须的,但前提是,这是个Radar图只有一个系列,而且最好半径是设定好的。其实现的核心思想就是,通过我们option中的设置,获取画布大小,获取标签和值,生成坐标系,算出目标点的坐标,然后添加上面说的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 (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});
 

至此,我们就 完全解决了Echarts单轴轮播问题。
如果你嫌上面太琐碎,可以直接取github看我的试验源码,文件是mouse.html,欢迎star

本文后续:从0开始撸一个支持单轴轮播的雷达图之末篇

本文首发于:http://closertb.site

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85057.html

相关文章

  • 0开始一个支持单轴播的雷达图之-解决Echarts雷达单轴轮播

    摘要:今天要用到的理论在前两篇都讲过,如果你错过了前两篇,你应该先看看。但是我们可否用生成一个图,自己为其写一个呢答案是肯定的。但一切的一切前提是,要支持单轴轮播,这个图只有一个系列。 今天要用到的理论在前两篇都讲过,如果你错过了前两篇,你应该先看看。从0开始写一个支持单轴轮播的雷达图之首篇从0开始写一个支持单轴轮播的雷达图之中篇 前言 通过前面我们自己实现了一个Radar图,并对其实现了单...

    Prasanta 评论0 收藏0
  • 0开始一个支持单轴播的雷达图(Ehcarts的单轴显示问题)之头

    摘要:引子最近做公司的数据展示项目,用的核心插件是,但在雷达图的展示案列上,需求上出现了需要单轴轮播标签和数据,在看完上的后,这个不支持,看了一下源码,似乎有点复杂,改了改,只实现了多个的轮播,和需求还是有差距,周末反正无聊,何不自己动手撸一个。 引子 最近做公司的数据展示项目,用的核心插件是Echarts,但在雷达图的展示案列上,需求上出现了需要单轴轮播标签和数据,在看完github上的i...

    wemall 评论0 收藏0
  • 关于css动态样式注入,你不知道的那些冷知识

    摘要:以上三种动态样式注入,不同的使用场景,各有利弊,至于你想用哪一种,需要你自己权衡,睡觉去啦。。。。 前言 作为一个前端,我们都听过结构,样式,行为分离;关于样式,我们都听过外联样式,内联样式和行内样式;关于这三者,什么权重啊,啊,对了,这些都不会出现在这篇文章里,这篇文章就说一些那些我们不怎么使用的,动态引入css样式的方法; 静态样式引入 前面说过外联样式,内联样式和行内样式,所谓外...

    ztyzz 评论0 收藏0
  • 干货--手把手vue移动UI框架:滑动轮播

    摘要:其次父组件中负责通用的功能,以及轮播的整体架构,其结构如下。下面的是一种移动端的适配方案。接下来实现函数运用动画切换到指定下标的子项到此为止,咱们就已经完成了一个初步的滑动切换轮播图的功能了。 前言 昨天写了一篇侧边菜单组件的文章,阅读人数挺多的,内心很欣喜(偷着乐,第一篇文章有这么多人看)!乘着这股劲,今天在继续写一篇我们平时工作中更常用的滑动轮播组件的文章。 效果展示 老规矩,咱们...

    MSchumi 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<