关系图点击节点展开次级节点效果尝试

描述:当前是关于Echarts图表中的 关系图 示例。
 
            data = [{
    name: 'node0',
    category: 'node0',
    value: 64,
    x: 100,
    y: 20
}];
links = [];
categories = [];

// 生成 2 个子节点函数
function generateNodes(nodeName, nodeX, nodeY, nodeValue, times) {

    let children_0 = {
        name: nodeName + '_0',
        category: nodeName + '_childrens',
        value: nodeValue / 2,
        x: nodeX - 10 - times * 5,
        y: nodeY + 17.32
    };

    let children_1 = {
        name: nodeName + '_1',
        category: nodeName + '_childrens',
        value: nodeValue / 2,
        x: nodeX + 10 + times * 5,
        y: nodeY + 17.32
    };

    data.push(children_0, children_1);

    links.push({
        source: nodeName,
        target: nodeName + '_0'
    }, {
        source: nodeName,
        target: nodeName + '_1'
    });

    // 递归
    if (times - 1 > 0) {
        generateNodes(children_0.name, children_0.x, children_0.y, nodeValue / 2, times - 1);
        generateNodes(children_1.name, children_1.x, children_1.y, nodeValue / 2, times - 1);
    }
}

function getCategories(src) {
    tmp = {};
    ret = [];

    for (let i in src) {
        if (typeof tmp[src[i].category] === 'undefined') {
            tmp[src[i].category] = '';
            ret.push(src[i].category);
        }
    }

    return ret;
}

generateNodes(data[0].name, data[0].x, data[0].y, data[0].value, 3);

categories = getCategories(data);

categoryStatus = (function(){
    let ret = {};
    for (let i in categories){
        ret[categories[i]] = true;
    }
    return ret;
})();
//console.log(data);
//console.log(links);
//console.log(categories);
//console.log(categoryStatus);


data.forEach(function(node) {
    node.itemStyle = null;
    node.symbolSize = node.value;
    node.label = {
        normal: {
            show: node.value > 30
        }
    };
    node.label.normal.show = node.value > 30;
    node.category = categories.indexOf(node.category);
});


option = {
    title: {
        text: '关系图点击节点展开次级节点效果尝试'
    },
    tooltip: {},
    legend: {
        show:false,
        y: '8%',
        data: categories
    },
    animationDuration: 1500,
    animationEasingUpdate: 'quinticInOut',
    series: [{
        name: 'ECharts学习',
        type: 'graph',
        layout: 'none',
        data: data,
        links: links,
        categories: categories.map(function(a) {
            return {
                name: a
            };
        }),
        roam: true,
        focusNodeAdjacency: true,
        itemStyle: {
            normal: {
                borderColor: '#fff',
                borderWidth: 1,
                shadowBlur: 10,
                shadowColor: 'rgba(0, 0, 0, 0.3)'
            }
        },
        label: {
            position: 'right',
            formatter: '{b}'
        },
        lineStyle: {
            color: 'source',
            curveness: 0.3
        },
        emphasis: {
            lineStyle: {
                width: 10
            }
        }
    }]
};

myChart.on('click', function(params) {
    
    categoryName = params.name + '_childrens';

    // 如果 category 状态为显示,则通过一定规则隐藏所有 childres
    if (categoryStatus[categoryName]) {

        // 这里为了省事,直接通过字符串匹配判断了
        for (let i in categories) {
            if (categories[i].includes(params.name) && categories[i] != 'node0') {
                myChart.dispatchAction({
                    type: 'legendUnSelect',
                    // 图例名称
                    name: categories[i]
                });
            }
        }
        
        categoryStatus[categoryName] = false;
    
    // 如 category 状态为隐藏,则显示    
    } else {
        for (let i in categories) {
            if (categories[i].includes(params.name) && categoryStatus[categories[i]] || categories[i] === categoryName) {
                myChart.dispatchAction({
                    type: 'legendSelect',
                    // 图例名称
                    name: categories[i]
                });
            }
        }
        
        categoryStatus[categoryName] = true;
    }

});

/** 
【备注】
1、此处为了省事,没有按照层级结构做判断(毕竟只是示意),所以显示隐藏时会有些 bug。
  比如先点击 node0_1 隐藏,再点击 2 下 node0

2、也可以通过直接修改 legend.selected + myChart.setOption 的方式实现。

*/