D3.js弦图国家组鼠标悬停功能异常技术求助
问题描述
我正在尝试为每个国家组实现鼠标悬停效果,以显示对应的弦图。我已在代码底部编写了一个透明度函数,但不知为何该函数无法识别组或鼠标悬停事件。
代码片段(原代码)
<!DOCTYPE html> <meta charset="utf-8"> <head> <style> body { font: 10px sans-serif; background-color: #F0F0F0; } h1 { font-size: 400%; position: relative; font-family: Helvetica; } h3 { font-family: Helvetica; position: relative; } p { position: relative; font-style: italic; font-family: Helvetica; top:1000px; left: 100px; } @media only screen and (max-width:1000px) { /* For tablets: */ .main { width: 80%; padding: 0; } .right { width: 100%; } } button { background-color: #4CA350; position: relative; border: none; color: white; padding: 15px 32px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; margin: 4px 2px; cursor: pointer; } .group-tick line { stroke: #000; } .ribbons { fill-opacity: 1; } #tooltip.total { position: relative; width: 200px; height: auto; padding: 10px; background-color: white; -webkit-border-radius: 10px; -moz-border-radius: 10px; border-radius: 10px; -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4); -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4); box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4); pointer-events: none; } #tooltip { position: relative; font-family: Helvetica Neue; font-size: 16px; top:870px; left:720px; width: 200px; height: auto; padding: 10px; background-color: white; -webkit-border-radius: 10px; -moz-border-radius: 10px; border-radius: 10px; -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4); -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4); box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4); pointer-events: none; } #tooltip.hidden { display: none; } #tooltip p { margin: 0; font-family: sans-serif; font-size: 40px; line-height: 20px; } </style> <title>Julia Spyrou DECO3100 Assignment 3</title> <body> <h1>Voting at the Eurovision Song Contest</h1> <h3>Mouseover individual chords to view voting relationships</h3> <p>NB: These visualisations exclude the countries that did not make the Final and their votes as well</p> <button type="button">2016</button> <button type="button">2017</button> <button type="button">2018</button> <div id="tooltip" class="hidden"> <p>$<span id="value">100</span></p> </div> <svg width="1000" height="1000"></svg> <script src="https://d3js.org/d3.v4.min.js"></script> <script> var names = ["Ukraine","Spain","Slovenia","Lithuania","Austria","Estonia","Norway","Portugal","UK","Serbia","Germany","Albania","France","Czech Republic","Denmark","Australia","Finland","Bulgaria","Moldova","Sweden","Hungary","Israel","Netherlands","Ireland","Cyprus","Italy"]; var opacityDefault = 0.7; var matrix = [ [0.1,0,0,0,0,0,0,4,0,0,0,0,4,12,0,0,0,1,15,0,0,7,0,0,2,8], //Ukraine [0,0,0,0,0,0,2,14,1,0,6,0,5,0,6,7,0,0,0,0,0,0,0,1,7,0], //Spain [5,0,0,0,0,0,0,3,0,8,0,0,2,7,0,0,0,0,0,0,0,4,1,0,0,0], //Slovenia [2,0,0,0,0,22,15,6,12,0,8,0,0,1,0,3,0,10,0,7,5,0,7,12,6,0], //Lithuania [7,8,12,15,0,18,16,8,12,4,15,2,7,5,18,5,10,16,3,12,11,13,13,5,2,7], //Austria [4,3,5,12,2,0,0,19,6,3,2,4,7,5,7,8,12,2,13,0,0,8,4,7,5,10], //Estonia [0,3,5,0,0,6,0,0,5,9,0,0,0,0,8,1,0,0,7,10,7,0,4,0,5,12], //Norway [0,0,0,7,0,3,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,2,6,0,0], //Portugal [0,0,0,0,0,0,0,0,0,0,1,3,3,0,3,6,0,0,0,0,0,8,0,10,0,6], //UK [0,0,0,0,8,0,0,0,0,0,0,3,1,0,0,0,0,7,0,0,0,0,0,0,0,1], //Serbia [0,13,4,7,16,6,18,8,3,10,0,14,8,3,24,12,1,6,8,6,1,8,24,16,3,13], //Germany [0,0,5,0,9,0,0,10,7,1,0,0,0,6,0,0,0,7,0,0,10,0,0,2,6,12], //Albania [19,10,2,15,0,0,8,5,0,0,0,12,0,0,2,0,9,5,0,5,0,6,0,4,4,0], //France [14,14,11,8,15,5,4,0,5,5,8,1,4,0,6,4,5,11,6,3,8,12,6,7,13,0], //Czech Republic [11,0,7,10,5,8,10,2,2,4,3,0,2,7,0,10,13,0,0,12,24,0,8,2,0,12], //Denmark [2,0,0,0,0,0,6,0,1,0,7,0,10,0,12,0,0,0,7,8,7,7,0,0,0,0], //Australia [0,0,0,0,0,12,0,0,4,0,0,0,0,3,0,4,0,0,0,9,0,6,0,0,0,0], //Finland [0,5,0,0,6,7,0,7,14,2,0,14,0,5,1,0,10,0,11,6,0,1,0,10,12,0], //Bulgaria [6,0,6,0,0,1,0,6,4,6,0,2,6,6,0,7,0,8,0,0,2,10,0,1,10,10], //Moldova [6,2,12,12,8,5,13,0,2,12,12,4,5,8,11,12,8,2,0,0,1,10,8,0,12,1], //Sweden [1,0,3,2,3,3,0,0,0,12,2,0,0,2,0,0,8,5,2,0,0,3,2,0,4,0], //Hungary [22,22,1,7,19,0,7,2,17,9,11,6,24,22,3,18,19,14,22,17,16,0,15,13,10,9], //Israel [8,0,7,3,1,1,9,0,0,7,5,0,6,0,5,0,2,0,0,1,8,0,0,3,0,0], //Netherlands [0,6,0,4,8,0,1,3,13,0,15,7,1,14,4,12,2,1,0,4,3,0,4,0,0,5], //Ireland [4,20,14,7,1,12,7,5,8,10,9,20,3,8,6,7,7,15,13,16,7,2,11,17,0,8], //Cyprus [5,10,10,7,10,7,0,14,0,14,12,24,10,2,0,0,10,6,8,0,6,5,7,0,15,0], //Italy ]; var svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height"), outerRadius = Math.min(width, height) * 0.4 - 100, innerRadius = outerRadius - 20; var formatValue = d3.formatPrefix( </script>
问题分析与修复方案
你的代码主要存在几个问题:语法不完整、缺少弦图核心生成逻辑、鼠标事件未正确绑定到组元素。下面是具体的修复步骤:
1. 补全语法错误
原代码中var formatValue = d3.formatPrefix(未完成,这会直接导致JS执行中断,补全为符合需求的格式:
var formatValue = d3.formatPrefix(",.0", 1e3);
2. 添加弦图核心生成逻辑
需要生成和弦数据、弧生成器、丝带生成器,并完成基础的元素绘制:
// 颜色比例尺,给每个国家分配颜色 var color = d3.scaleOrdinal() .domain(d3.range(names.length)) .range(d3.schemeCategory20); // 生成和弦数据 var chord = d3.chord() .padAngle(0.05) .sortSubgroups(d3.descending) .sortChords(d3.descending)(matrix); // 弧生成器(绘制国家组的外圈) var arc = d3.arc() .innerRadius(innerRadius) .outerRadius(outerRadius); // 丝带生成器(绘制国家间的连接弦) var ribbon = d3.ribbon() .radius(innerRadius);
3. 绘制丝带与组元素,并绑定鼠标事件
// 绘制丝带 var ribbons = svg.append("g") .attr("class", "ribbons") .selectAll("path") .data(chord) .enter().append("path") .attr("d", ribbon) .style("fill", function(d) { return color(d.target.index); }) .style("opacity", opacityDefault); // 绘制国家组的外圈弧,并绑定鼠标事件 var group = svg.append("g") .attr("class", "groups") .selectAll("path") .data(chord.groups) .enter().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", mouseover) // 绑定悬停事件 .on("mouseout", mouseout); // 绑定离开事件
4. 实现透明度控制函数
// 鼠标悬停时:高亮当前组相关的丝带,其他丝带变暗 function mouseover(d) { ribbons.style("opacity", function(p) { return p.source.index === d.index || p.target.index === d.index ? 1 : 0.1; }); } // 鼠标离开时:恢复所有丝带的默认透明度 function mouseout(d) { ribbons.style("opacity", opacityDefault); }
5. 可选:添加国家标签
为了让用户更清楚每个弧对应的国家,可以添加标签:
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(" + (outerRadius + 10) + ")" + (d.angle > Math.PI ? "rotate(180)" : ""); }) .style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; }) .text(function(d) { return names[d.index]; });
完整修复后的代码
将上述片段整合到原代码中,即可实现鼠标悬停组时高亮对应弦图的效果。
内容的提问来源于stack exchange,提问作者Julia Spyrou
相关产品推荐
相关产品推荐

