D3.js Sankey图表-如何突出显示来自节点的链接集?

时间:2020-10-19 13:02:30

标签: d3.js

我一直在研究D3 sankey图表,该图表显示了两个时间段内节点之间的音量移动。我的节点是颜色协调的(基于它们的名称)。我已经通过使用简单的CSS设法在链接上设置了悬停行为,但是理想情况下,我需要能够悬停在左侧的节点上,然后突出显示来自该节点的所有链接。同样,您应该能够将鼠标悬停在右侧的相应节点上,并突出显示进入该节点的所有链接。

到目前为止,这是我的代码。任何帮助将不胜感激:

// set the dimensions and margins of the graph
var margin = {
    top: 75,
    right: 10,
    bottom: 10,
    left: 10
  },
  width = 900 - margin.left - margin.right,
  height = 500 - margin.top - margin.bottom;

// append the svg object to the body of the page
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 + ")");

//Color scale used
var color = d3.scaleOrdinal().range(["#002060ff", "#164490ff", "#4d75bcff", "#98b3e6ff", "#d5e2feff", "#008cb0ff"]);


// Set the sankey diagram properties
var sankey = d3.sankey()
  .nodeWidth(175)
  .nodePadding(10)
  .size([width, height]);

// load the data

var data = {
  "years": [{
      "year": 2019
    }, {
      "year": 2020
    }

  ],
  "nodes": [{
      "node": 0,
      "id": "a",
      "name": "A"
    },
    {
      "node": 1,
      "id": "b",
      "name": "B"
    },
    {
      "node": 2,
      "id": "c",
      "name": "C"
    },
    {
      "node": 3,
      "id": "d",
      "name": "D"
    },
    {
      "node": 4,
      "id": "e",
      "name": "E"
    },
    {
      "node": 5,
      "id": "f",
      "name": "F"
    },
    {
      "node": 6,
      "id": "a",
      "name": "A"
    },
    {
      "node": 7,
      "id": "b",
      "name": "B"
    },
    {
      "node": 8,
      "id": "c",
      "name": "C"
    },
    {
      "node": 9,
      "id": "d",
      "name": "D"
    },
    {
      "node": 10,
      "id": "e",
      "name": "E"
    },
    {
      "node": 11,
      "id": "f",
      "name": "F"
    }
  ],
  "links": [{
      "source": 0,
      "target": 6,
      "value": 20
    },
    {
      "source": 0,
      "target": 7,
      "value": 10
    },
    {
      "source": 0,
      "target": 8,
      "value": 10
    },
    {
      "source": 0,
      "target": 9,
      "value": 10
    },
    {
      "source": 0,
      "target": 10,
      "value": 20
    },
    {
      "source": 0,
      "target": 11,
      "value": 10
    },

    {
      "source": 1,
      "target": 6,
      "value": 40
    },
    {
      "source": 1,
      "target": 7,
      "value": 10
    },
    {
      "source": 1,
      "target": 8,
      "value": 10
    },
    {
      "source": 1,
      "target": 9,
      "value": 10
    },
    {
      "source": 1,
      "target": 10,
      "value": 10
    },
    {
      "source": 1,
      "target": 11,
      "value": 10
    },

    {
      "source": 2,
      "target": 6,
      "value": 20
    },
    {
      "source": 2,
      "target": 7,
      "value": 10
    },
    {
      "source": 2,
      "target": 8,
      "value": 10
    },
    {
      "source": 2,
      "target": 9,
      "value": 10
    },
    {
      "source": 2,
      "target": 10,
      "value": 10
    },
    {
      "source": 2,
      "target": 11,
      "value": 10
    },

    {
      "source": 3,
      "target": 6,
      "value": 20
    },
    {
      "source": 3,
      "target": 7,
      "value": 10
    },
    {
      "source": 3,
      "target": 8,
      "value": 10
    },
    {
      "source": 3,
      "target": 9,
      "value": 10
    },
    {
      "source": 3,
      "target": 10,
      "value": 10
    },
    {
      "source": 3,
      "target": 11,
      "value": 10
    },

    {
      "source": 4,
      "target": 6,
      "value": 20
    },
    {
      "source": 4,
      "target": 7,
      "value": 10
    },
    {
      "source": 4,
      "target": 8,
      "value": 10
    },
    {
      "source": 4,
      "target": 9,
      "value": 10
    },
    {
      "source": 4,
      "target": 10,
      "value": 10
    },
    {
      "source": 4,
      "target": 11,
      "value": 10
    },

    {
      "source": 5,
      "target": 6,
      "value": 20
    },
    {
      "source": 5,
      "target": 7,
      "value": 10
    },
    {
      "source": 5,
      "target": 8,
      "value": 10
    },
    {
      "source": 5,
      "target": 9,
      "value": 10
    },
    {
      "source": 5,
      "target": 10,
      "value": 10
    },
    {
      "source": 5,
      "target": 11,
      "value": 10
    }


  ]
}

// Constructs a new Sankey
sankey
  .nodes(data.nodes)
  .links(data.links)
  .layout(0);

// add in the links
var link = svg.append("g")
  .selectAll(".link")
  .data(data.links)
  .enter()
  .append("path")
  .attr("class", "link")
  .attr("d", sankey.link())
  .style("stroke-width", function(d) {
    return Math.max(1, d.dy);
  })
  .sort(function(a, b) {
    return b.dy - a.dy;
  })


// add in the nodes
var node = svg.append("g")
  .selectAll(".node")
  .data(data.nodes)
  .enter().append("g")
  .attr("class", "node")
  .attr("transform", function(d) {
    return "translate(" + d.x + "," + d.y + ")";
  })


// add the rectangles for the nodes
node
  .append("rect")
  .attr("height", function(d) {
    return d.dy;
  })
  .attr("width", sankey.nodeWidth())
  .attr("rx", 3)
  .attr("ry", 3)
  .style("fill", function(d) {
    return d.color = color(d.id.replace(/ .*/, ""));
  })
  // Add hover text
  .append("title")
  .text(function(d) {
    return d.name + "\n" + d.value
  });

// add in the title for the nodes
node
  .append("text")
  .attr("x", 87)
  .attr("y", function(d) {
    return d.dy / 2;
  })
  .attr("dy", ".35em")
  .attr("text-anchor", "middle")
  .text(function(d) {
    return d.name;
  })
  .style("fill", "white")
@import url('https://fonts.googleapis.com/css2?family=Assistant:wght@600&display=swap');
text {
  font-family: 'Assistant', sans-serif
}

text {
  font-size: 14px
}

.link {
  fill: none;
  stroke: #000;
  stroke-opacity: .2;
}

.link:hover {
  stroke-opacity: .5;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Assistant:wght@700&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/gh/holtzy/D3-graph-gallery@master/LIB/sankey.js"></script>
<div id="chart"></div>

1 个答案:

答案 0 :(得分:1)

d3具有its own event system,它支持悬停,单击,触摸以及更多事件。除了非常简单的东西之外,通常不需要使用CSS伪类。

// set the dimensions and margins of the graph
var margin = {
    top: 75,
    right: 10,
    bottom: 10,
    left: 10
  },
  width = 900 - margin.left - margin.right,
  height = 500 - margin.top - margin.bottom;

// append the svg object to the body of the page
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 + ")");

//Color scale used
var color = d3.scaleOrdinal().range(["#002060ff", "#164490ff", "#4d75bcff", "#98b3e6ff", "#d5e2feff", "#008cb0ff"]);


// Set the sankey diagram properties
var sankey = d3.sankey()
  .nodeWidth(175)
  .nodePadding(10)
  .size([width, height]);

// load the data

var data = {
  "years": [{
      "year": 2019
    }, {
      "year": 2020
    }

  ],
  "nodes": [{
      "node": 0,
      "id": "a",
      "name": "A"
    },
    {
      "node": 1,
      "id": "b",
      "name": "B"
    },
    {
      "node": 2,
      "id": "c",
      "name": "C"
    },
    {
      "node": 3,
      "id": "d",
      "name": "D"
    },
    {
      "node": 4,
      "id": "e",
      "name": "E"
    },
    {
      "node": 5,
      "id": "f",
      "name": "F"
    },
    {
      "node": 6,
      "id": "a",
      "name": "A"
    },
    {
      "node": 7,
      "id": "b",
      "name": "B"
    },
    {
      "node": 8,
      "id": "c",
      "name": "C"
    },
    {
      "node": 9,
      "id": "d",
      "name": "D"
    },
    {
      "node": 10,
      "id": "e",
      "name": "E"
    },
    {
      "node": 11,
      "id": "f",
      "name": "F"
    }
  ],
  "links": [{
      "source": 0,
      "target": 6,
      "value": 20
    },
    {
      "source": 0,
      "target": 7,
      "value": 10
    },
    {
      "source": 0,
      "target": 8,
      "value": 10
    },
    {
      "source": 0,
      "target": 9,
      "value": 10
    },
    {
      "source": 0,
      "target": 10,
      "value": 20
    },
    {
      "source": 0,
      "target": 11,
      "value": 10
    },

    {
      "source": 1,
      "target": 6,
      "value": 40
    },
    {
      "source": 1,
      "target": 7,
      "value": 10
    },
    {
      "source": 1,
      "target": 8,
      "value": 10
    },
    {
      "source": 1,
      "target": 9,
      "value": 10
    },
    {
      "source": 1,
      "target": 10,
      "value": 10
    },
    {
      "source": 1,
      "target": 11,
      "value": 10
    },

    {
      "source": 2,
      "target": 6,
      "value": 20
    },
    {
      "source": 2,
      "target": 7,
      "value": 10
    },
    {
      "source": 2,
      "target": 8,
      "value": 10
    },
    {
      "source": 2,
      "target": 9,
      "value": 10
    },
    {
      "source": 2,
      "target": 10,
      "value": 10
    },
    {
      "source": 2,
      "target": 11,
      "value": 10
    },

    {
      "source": 3,
      "target": 6,
      "value": 20
    },
    {
      "source": 3,
      "target": 7,
      "value": 10
    },
    {
      "source": 3,
      "target": 8,
      "value": 10
    },
    {
      "source": 3,
      "target": 9,
      "value": 10
    },
    {
      "source": 3,
      "target": 10,
      "value": 10
    },
    {
      "source": 3,
      "target": 11,
      "value": 10
    },

    {
      "source": 4,
      "target": 6,
      "value": 20
    },
    {
      "source": 4,
      "target": 7,
      "value": 10
    },
    {
      "source": 4,
      "target": 8,
      "value": 10
    },
    {
      "source": 4,
      "target": 9,
      "value": 10
    },
    {
      "source": 4,
      "target": 10,
      "value": 10
    },
    {
      "source": 4,
      "target": 11,
      "value": 10
    },

    {
      "source": 5,
      "target": 6,
      "value": 20
    },
    {
      "source": 5,
      "target": 7,
      "value": 10
    },
    {
      "source": 5,
      "target": 8,
      "value": 10
    },
    {
      "source": 5,
      "target": 9,
      "value": 10
    },
    {
      "source": 5,
      "target": 10,
      "value": 10
    },
    {
      "source": 5,
      "target": 11,
      "value": 10
    }
  ]
};

// Constructs a new Sankey
sankey
  .nodes(data.nodes)
  .links(data.links)
  .layout(0);

// add in the links
var link = svg.append("g")
  .selectAll(".link")
  .data(data.links)
  .enter()
  .append("path")
  .attr("class", "link")
  .attr("d", sankey.link())
  .style("stroke-opacity", 0.2)
  .style("stroke-width", function(d) {
    return Math.max(1, d.dy);
  })
  .sort(function(a, b) {
    return b.dy - a.dy;
  });

// add in the nodes
var node = svg.append("g")
  .selectAll(".node")
  .data(data.nodes)
  .enter().append("g")
  .attr("class", "node")
  .attr("transform", function(d) {
    return "translate(" + d.x + "," + d.y + ")";
  })

// add the rectangles for the nodes
node
  .append("rect")
  .attr("height", function(d) {
    return d.dy;
  })
  .attr("width", sankey.nodeWidth())
  .attr("rx", 3)
  .attr("ry", 3)
  .style("fill", function(d) {
    return d.color = color(d.id.replace(/ .*/, ""));
  })
  .on("mouseover", function(d) {
    link
      .transition()
      .duration(300)
      .style("stroke-opacity", function(l) {
        return l.source === d || l.target === d ? 0.5 : 0.2;
      });
  })
  .on("mouseleave", function(d) {
    link
      .transition()
      .duration(300)
      .style("stroke-opacity", 0.2);
  })
  // Add hover text
  .append("title")
  .text(function(d) {
    return d.name + "\n" + d.value
  });

// add in the title for the nodes
node
  .append("text")
  .attr("x", 87)
  .attr("y", function(d) {
    return d.dy / 2;
  })
  .attr("dy", ".35em")
  .attr("text-anchor", "middle")
  .text(function(d) {
    return d.name;
  })
  .style("fill", "white");
@import url('https://fonts.googleapis.com/css2?family=Assistant:wght@600&display=swap');
text {
  font-family: 'Assistant', sans-serif
}

text {
  font-size: 14px
}

.link {
  fill: none;
  stroke: #000;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Assistant:wght@700&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/gh/holtzy/D3-graph-gallery@master/LIB/sankey.js"></script>
<div id="chart"></div>

相关问题