echart3 力引导布局实现节点的提示和折叠

阅读更多

     最近在项目中需要开发一个图表来显示人员的各种属性,类似于一种树形的结构进行显示数据。如果多个人员有同一个属性,那么需要将相同的属性进行连线,即关联起来。即形成一个关系图,由于我自身对echarts稍微熟悉一下,因此采用echarts3来完成此图表的开发。
注意:echarts的不同版本api有些稍微的不同。

完成效果:

  需求:
    1、点击父节点
        |- 该父节点的子节点是没有显示的,那么显示它的子节点
        |- 该父节点的子节点是显示的,那么隐藏它的子节点和子孙节点
    2、对于父节点显示出它的分类名称,比如 用户信息(父节点)下有用户名、性别、生日、身份证(子节点)等
        |- 父节点显示 用户信息
        |- 子节点显示 用户名 : 名称
                     性别 : 名称
    3、鼠标移动到父节点上,显示出它下方子节点的具体信息

 

预备知识:
    1、节点的隐藏和实现:在 series[index].data[index]中存在category 值,如果它的值和series[index].categories中的角标没有对应起来,那么此节点是不显示的(即隐藏,将category的值改成负数,显示 改成整数,值要和categories的角标对应起来)
    2、2个节点要连接起来,那么 links 中的 source,target 的值只需要和 data 中的 name 属性的值对应起来即可
    3、需要了解一下echarts的富文本样式,用于格式化节点上显示的值
    4、了解一点es5,es6的语法

 

图片解释:(下方的 lengedName 实际是data中的 legendName ,图片上写错了
echart3 力引导布局实现节点的提示和折叠_第1张图片

具体实现:
    1、点击显示和隐藏节点


echart3 力引导布局实现节点的提示和折叠_第2张图片
 
        |- 找到点击节点的 open 的值(第一次点击是不存在的,点击完增加这个属性)
            > true(存在,即点过一回)
                * 从links中找到所有的子节点和子孙节点的 name(links中的target属性)的值,需要递归获取
                * 从data中获取获取关联的节点
                * 将节点的category 的值改成 负数
                * 如果节点的nodeType === 1(即上面图片解释中的父节点), 那么需要将 open的值设置成false
                * 将当前点击的节点的 open 属性改成 false
                * 重新渲染echarts图表

                * 此时图表的节点就折叠起来了
            > false(即不存在或后续赋值为false)
                * 从links中找到所有的子节点的 name(links中的target属性)的值
                * 从data中获取获取关联的节点
                * 将节点的category 的值改成 整数
                * 将当前点击的节点的 open 属性改成 true
                * 重新渲染echarts图表

                * 此时图表的节点就展开了

/**
     * 绑定图表的点击事件
     * @param chart
     */
    function bindChartClickEvent(chart) {
        chart.on('click', function (params) {
            var category = params.data.category,
                nodeType = params.data.nodeType;
            if (category === 0 || nodeType === 1) {
                toggleShowNodes(chart, params);
            }
        });
    }

    /**
     * 展开或关闭节点
     * @param chart
     * @param params
     */
    function toggleShowNodes(chart, params) {
        var open = !!params.data.open,
            options = chart.getOption(),
            seriesIndex = params.seriesIndex,
            srcLinkName = params.name,
            serieLinks = options.series[seriesIndex].links,
            serieData = options.series[seriesIndex].data,
            serieDataMap = new Map(),
            serieLinkArr = [];
        // 当前根节点是展开的,那么就需要关闭所有的根节点
        if (open) {
            // 递归找到所有的link节点的target的值
            findLinks(serieLinkArr, srcLinkName, serieLinks, true);
            if (serieLinkArr.length) {
                serieData.forEach(sd => serieDataMap.set(sd.name, sd));
                for (var i = 0; i < serieLinkArr.length; i++) {
                    if (serieDataMap.has(serieLinkArr[i])) {
                        var currentData = serieDataMap.get(serieLinkArr[i]);
                        currentData.category = -Math.abs(currentData.category);
                        if (currentData.nodeType === 1) {
                            currentData.open = false;
                        }
                    }
                }
                serieDataMap.get(srcLinkName).open = false;
                chart.setOption(options);
            }
        } else {
            // 当前根节点是关闭的,那么就需要展开第一层根节点
            findLinks(serieLinkArr, srcLinkName, serieLinks, false);
            if (serieLinkArr.length) {
                serieData.forEach(sd => serieDataMap.set(sd.name, sd));
                for (var j = 0; j < serieLinkArr.length; j++) {
                    if (serieDataMap.has(serieLinkArr[j])) {
                        var currentData = serieDataMap.get(serieLinkArr[j]);
                        currentData.category = Math.abs(currentData.category);
                    }
                }
                serieDataMap.get(srcLinkName).open = true;
                chart.setOption(options);
            }
        }
    }

    /**
     * 查找连接关系
     * @param links 返回的节点放入此集合
     * @param srcLinkName 源线的名称
     * @param serieLinks 需要查找的集合
     * @param deep 是否需要递归进行查找
     */
    function findLinks(links, srcLinkName, serieLinks, deep) {
        var targetLinks = [];
        serieLinks.filter(link => link.source === srcLinkName).forEach(link => {
            targetLinks.push(link.target);
            links.push(link.target)
        });
        if (deep) {
            for (var i = 0; i < targetLinks.length; i++) {
                findLinks(links, targetLinks[i], serieLinks, deep);
            }
        }
    }

 2、节点名称显示的格式化


echart3 力引导布局实现节点的提示和折叠_第3张图片
        富文本样式的使用 (series中label的设置

"label": {
                    "normal": {
                        "show": true,
                        "position": "top",
                        "formatter": function (args) {
                            if (args.data.nodeType === 1) {
                                return "{prefixClassName|" + args.data.legendName + "}";
                            } else {
                                return "{prefixClassName|" + args.data.legendName + " :}\r\n    " + args.name;
                            }
                        },
                        "rich": {
                            "prefixClassName": {
                                color: "#FF9301",
                                fontWeight: "bold"
                            }
                        }
                    }
                }

 3、鼠标移动到父节点上显示子节点的信息
echart3 力引导布局实现节点的提示和折叠_第4张图片
 
        找到当前节点关联的所有的子节点,通过links来进行查找,当前节点的name属性的值等于links中source中的值,那么target就是关联的子节点的name的值,遍历data数据,如果name属性的值等于target的值,就找到了关联节点的数据。
        注意: 在显示的时候需要注意一下获取前面颜色的获取(当categories中的值过多时需要注意一下)

tooltip: {
            "formatter": function (arg) {
                var nodeType = arg.data.nodeType,
                    srcName = arg.name,
                    seriesIndex = arg.seriesIndex,
                    options = echart.getOption(),
                    serieData = options.series[seriesIndex].data,
                    serieLinks = options.series[seriesIndex].links,
                    colors = options.color,
                    serieDataMap = new Map(),
                    serieLinkArr = [],
                    tips = '';
                // 父节点,排除根节点
                if (nodeType === 1) {
                    serieLinks.filter(link => link.source === srcName).forEach(link => serieLinkArr.push(link.target));
                    if (serieLinkArr.length) {
                        serieData.forEach(sd => serieDataMap.set(sd.name, sd));
                        for (var i = 0; i < serieLinkArr.length; i++) {
                            if (serieDataMap.has(serieLinkArr[i])) {
                                var currentData = serieDataMap.get(serieLinkArr[i]),
                                    color = getColor(colors, currentData.category);
                                tips += ' ' + currentData.legendName + " : " + currentData.name + ' 
'; } } } return tips; } else { return ''; } } } /** * 获取颜色 * @param colors * @param index * @returns {*} */ function getColor(colors, index) { var length = colors.length, colorIndex = index; if (index >= length) { colorIndex = length - index; } return colors[colorIndex]; }

       

完成代码如下:(如需运行,下载附件中的即可,或自定导入echarts3的js文件)




    
    echart3 力引导布局实现节点的提示和折叠
    


  • echart3 力引导布局实现节点的提示和折叠_第5张图片
  • 大小: 1.1 MB
  • echart3 力引导布局实现节点的提示和折叠_第6张图片
  • 大小: 87.7 KB
  • echart3 力引导布局实现节点的提示和折叠_第7张图片
  • 大小: 703.4 KB
  • echart3 力引导布局实现节点的提示和折叠_第8张图片
  • 大小: 32.2 KB
  • echart3 力引导布局实现节点的提示和折叠_第9张图片
  • 大小: 40.6 KB
  • 力引向图.zip (213.3 KB)
  • 下载次数: 18
  • 查看图片附件

你可能感兴趣的:(echarts,引力图,力引向布局,引力图点击折叠)