D3弦图制作

弦图主要是用来表示一组元素之间的联系,弦图分为两部分,外部的节点和内部的弦。从一个元素到另外一个元素绘制弧,表示两个元素相关,弧的宽度表示权重,这就是弦。弦图的绘制,主要包括创建弦图布局对象、确定初始数据然后转换数据、添加节点和弦、添加文字、添加交互效果等。
访问地址:http://106.14.147.72/Graphtest/chord-interactive.html
1.初始化数据

    var continent = [ "亚洲" , "欧洲" , "非洲" , "美洲" , "大洋洲"  ];

        // 各州人口的来源,如
        //              亚洲      美洲
        //  亚洲      9000        1000
        //  美洲      7000        500
        // 该矩阵表示:
        // 1.亚洲的人口:有9000是本地人,有1000人是来自美洲的移民,总人口为 9000 + 1000
        // 2.美洲的人口:有500是本地人,有7000人是来自亚洲的移民,总人口为 500 + 7000

        var population = [
          [ 9000,  870  , 3000 , 1000 , 5200 ],
          [ 3400,  8000 , 2300 , 4922 , 374  ],
          [ 2000,  2000 , 7700 , 4881 , 1050 ],
          [ 3000,  8012  , 5531  , 500  , 400  ],
          [ 3540,  4310 , 1500  , 1900 , 300 ]
        ]; 

2.创建对象转换数据

var width  = 1400;  //SVG绘制区域的宽度
        var height = 700;   //SVG绘制区域的高度

        var svg = d3.select("body")         //选择<body>
                    .append("svg")          //在<body>中添加<svg>
                    .attr("width", width)   //设定<svg>的宽度属性
                    .attr("height", height);//设定<svg>的高度属性
        //2.转换数据
        var chord = d3.layout.chord()
                       .padding(0.03)
                       .sortSubgroups(d3.ascending)
                       .matrix(population);
//3.绘制

        //弦图的<g>元素
        var gChord = svg.append("g")
                        .attr("transform","translate(" + width/2 + "," + height/2 + ")");

        //节点的<g>元素
        var gOuter = gChord.append("g");

        //弦的<g>元素
        var gInner = gChord.append("g");

        //颜色比例尺
        var color20 = d3.scale.category20();

        //绘制节点
        var innerRadius = height/2 * 0.7;
        var outerRadius = innerRadius * 1.1;

        //弧生成器
        var arcOuter =  d3.svg.arc()
                     .innerRadius(innerRadius)
                     .outerRadius(outerRadius);

        gOuter.selectAll(".outerPath")
                            .data(chord.groups())
                            .enter()
                            .append("path")
                            .attr("class","outerPath")
                            .style("fill", function(d) { return color20(d.index); })
                            .attr("d", arcOuter );

        gOuter.selectAll(".outerText")
                            .data(chord.groups())
                            .enter()
                            .append("text")
                            .each( function(d,i) {
                                d.angle = (d.startAngle + d.endAngle)/2;
                                d.name = continent[i];
                            })
                            .attr("class","outerText")
                            .attr("dy",".35em")
                            .attr("transform", function(d){
                                var result = "rotate(" + ( d.angle * 180 / Math.PI ) + ")";

                                result += "translate(0,"+ -1.0 * ( outerRadius + 10 ) +")" ;

                                if( d.angle > Math.PI * 3 / 4 &&  d.angle < Math.PI * 5 / 4 )
                                    result += "rotate(180)";

                                return result;
                            })
                            .text(function(d){
                                return d.name;
                            });


        //绘制弦
        var arcInner =  d3.svg.chord()
                        .radius(innerRadius);

        gInner.selectAll(".innerPath")
                            .data(chord.chords())
                            .enter()
                            .append("path")
                            .attr("class","innerPath")
                            .attr("d", arcInner )
                            .style("fill", function(d) { return color20(d.source.index); });


        gOuter.selectAll(".outerPath")
            .on("mouseover",fade(0.0))      //鼠标放到节点上
            .on("mouseout",fade(1.0));      //鼠标从节点上移开

        function fade(opacity){
            //返回一个function(g, i)
            return function(g,i){

                gInner.selectAll(".innerPath")  //选择所有的弦
                        .filter( function(d) {  //过滤器
                            //没有连接到鼠标所在节点的弦才能通过
                            return d.source.index != i && d.target.index != i; 
                        })
                        .transition()   //过渡
                        .style("opacity", opacity); //透明度
            }

        }

效果图:
这里写图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我们来制作一个复杂的D3,其中包括以下交互: 1. 鼠标悬停时显示段的详细信息。 2. 点击段时,将相关的节点和段高亮显示。 3. 点击节点时,将与该节点相关的所有段高亮显示。 4. 双击节点时,展开一个子以显示该节点的上下文信息。 下面是实现该和交互的代码: ```javascript // 设置画布大小和边距 var margin = { top: 50, right: 50, bottom: 50, left: 50 }, width = 800 - margin.left - margin.right, height = 800 - margin.top - margin.bottom; // 创建SVG元素 var svg = d3.select("#chart") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // 布局 var chord = d3.chord() .padAngle(0.05) .sortSubgroups(d3.descending); // 颜色比例尺 var color = d3.scaleOrdinal() .domain(d3.range(4)) .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b"]); // 外半径和内半径 var outerRadius = Math.min(width, height) * 0.5 - 40, innerRadius = outerRadius - 30; // 根据数据生成的矩阵 var matrix = [ [11975, 5871, 8916, 2868], [1951, 10048, 2060, 6171], [8010, 16145, 8090, 8045], [1013, 990, 940, 6907] ]; // 节点名称 var nodes = ["Group A", "Group B", "Group C", "Group D"]; // 通过矩阵和节点名称生成的数据 var chords = chord(matrix); // 定义段的路径生成器 var arc = d3.arc() .innerRadius(innerRadius) .outerRadius(outerRadius); // 定义的路径生成器 var ribbon = d3.ribbon() .radius(innerRadius); // 生成段 var group = svg.append("g") .selectAll("g") .data(chords.groups) .enter() .append("g"); // 添加段路径 group.append("path") .style("fill", function(d) { return color(d.index); }) .style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); }) .attr("d", arc) .on("mouseover", function(d) { // 鼠标悬停时显示段的详细信息 d3.select(this).style("fill", "yellow"); }) .on("mouseout", function(d) { d3.select(this).style("fill", color(d.index)); }) .on("click", function(d) { // 点击段时,将相关的节点和段高亮显示 group.selectAll("path") .filter(function(e) { return e.source.index != d.index && e.target.index != d.index; }) .style("opacity", 0.1); group.selectAll("path") .filter(function(e) { return e.source.index == d.index || e.target.index == d.index; }) .style("stroke", "red") .style("stroke-width", 2); }); // 添加路径 svg.append("g") .attr("fill-opacity", 0.67) .selectAll("path") .data(chords) .enter() .append("path") .attr("d", ribbon) .style("fill", function(d) { return color(d.target.index); }) .style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); }) .on("mouseover", function(d) { // 鼠标悬停时显示段的详细信息 d3.select(this).style("fill", "yellow"); }) .on("mouseout", function(d) { d3.select(this).style("fill", color(d.target.index)); }); // 添加节点标签 group.append("text") .each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; }) .attr("dy", ".35em") .attr("transform", function(d) { return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")" + "translate(" + (innerRadius + 26) + ")" + (d.angle > Math.PI ? "rotate(180)" : ""); }) .attr("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; }) .text(function(d, i) { return nodes[i]; }) .on("click", function(d, i) { // 点击节点时,将与该节点相关的所有段高亮显示 group.selectAll("path") .filter(function(e) { return e.source.index != i && e.target.index != i; }) .style("opacity", 0.1); group.selectAll("path") .filter(function(e) { return e.source.index == i || e.target.index == i; }) .style("stroke", "red") .style("stroke-width", 2); }) .on("dblclick", function(d, i) { // 双击节点时,展开一个子以显示该节点的上下文信息 var newData = [ [11975, 5871, 8916], [1951, 10048, 2060], [8010, 16145, 8090] ]; var newNodes = ["Subgroup A", "Subgroup B", "Subgroup C"]; var newChords = chord(newData); outerRadius = Math.min(width, height) * 0.5 - 80; innerRadius = outerRadius - 30; arc.innerRadius(innerRadius) .outerRadius(outerRadius); ribbon.radius(innerRadius); group.remove(); svg.selectAll("text").remove(); group = svg.append("g") .selectAll("g") .data(newChords.groups) .enter() .append("g"); group.append("path") .style("fill", function(d) { return color(d.index); }) .style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); }) .attr("d", arc); svg.append("g") .attr("fill-opacity", 0.67) .selectAll("path") .data(newChords) .enter() .append("path") .attr("d", ribbon) .style("fill", function(d) { return color(d.target.index); }) .style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); }); group.append("text") .each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; }) .attr("dy", ".35em") .attr("transform", function(d) { return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")" + "translate(" + (innerRadius + 26) + ")" + (d.angle > Math.PI ? "rotate(180)" : ""); }) .attr("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; }) .text(function(d, i) { return newNodes[i]; }); }); ``` 这段代码使用D3库的`chord`函数来生成的数据,然后使用`arc`和`ribbon`函数分别生成段和的路径。在`mouseover`、`click`和`dblclick`事件处理函数中,我们可以实现鼠标悬停、点击和双击时的交互效果。其中,双击事件处理函数会生成一个子,以展示与双击节点相关的上下文信息。 这个复杂的D3交互可以帮助用户更好地理解和探索数据,提高数据可视化的交互性和易用性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值