gpt4 book ai didi

javascript - D3 鼠标悬停组问题

转载 作者:行者123 更新时间:2023-11-30 14:34:52 25 4
gpt4 key购买 nike

我正在尝试对显示相应和弦的每个国家/地区进行鼠标悬停。我为此在代码底部创建了一个不透明度函数,但由于某种原因它似乎没有注册组或鼠标悬停函数。

            <!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(",.0", 1e3);

var chord = d3.chord()
.padAngle(0.05)
.sortSubgroups(d3.descending);

var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);

var ribbon = d3.ribbon()
.radius(innerRadius);

var color = d3.scaleOrdinal()
.domain(d3.range(4))
.range(["#4B5320", "#50C878", "#98FB98", "#679267","#2E8B57","#043927", "#0B6623","#9DC183","#708238", "#C7EA46", "#3F704D","#00A86B","8F9779"]);

var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
.datum(chord(matrix));

var group = g.append("g")
.attr("class", "groups")
.selectAll("g")
.data(function(chords) { return 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", fade(5))
.on("mouseout", fade(5));

function fade(opacity) {
return function(d, i) {
svg.selectAll(".ribbons path")
.filter(function(d) { return d.source.index != i && d.target.index != i; })
.transition()
};
}

group.append("text")
.each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; })
.attr("dy", ".35em")
.attr("class", "titles")
.attr("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
.attr("transform", function(d) {
if (outerArcs = 0) {
width = 10;
}
return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
+ "translate(" + (outerRadius + 10) + ")"
+ (d.angle > Math.PI ? "rotate(180)" : "");
})
.text(function(d,i) { return names[i]; });

g.append("g")
.attr("class", "ribbons")
.selectAll("path")
.data(function(chords) { return 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(); });

// Returns an array of tick angles and values for a given group and step.
function groupTicks(d, i) {
var k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value,0.2).map(function(v, i) {
return {
angle: v * k + d.startAngle,
label: i*100 % 5 ? null : v,
id: i
};
});
}

svg.selectAll("path")
.on("mouseover", function(d) { //event when we mouseover
d3.select(this) //this gives us acess to the particular rectange in the selection
.transition()
.duration(100)
.attr("fill", "rgb(170, 255, 44)"); //hover colour
var h = 20;
//get tooltip location
var xPosition = parseFloat(d3.select(this).attr("x"));
var yPosition = parseFloat(d3.select(this).attr("y")) / 100 + h / 7;

svg.selectAll("path")
.transition()
.style("opacity", 0.1);
d3.select(this)
.transition()
.style("opacity", 1);
//update tooltip location and value
console.log(d.source.index);
d3.select("#tooltip")
.style("left", xPosition + "100px")
.style("top", yPosition + "3000px")
//.select("#value")
.text(names[d.source.index] + " received " + d.source.value + " points from " + names[d.target.index]);

//use hidden css to hide and show the tooltip
d3.select("#tooltip").classed("hidden", false);
})
.on("mouseout", function(d) { //reset fill on mouse out
d3.select(this)
.transition()
.duration(250)
.attr("fill", "rgb(0," + Math.round(d+60) + ",0)");
//hide tooltip
d3.select("#tooltip").classed("hidden", true);
});

function fade(opacity) {
return function(g, i) {
svg.selectAll("g.chord ribbons")
.filter(function(d) {
return d.source.index != i && d.target.index != i;
})
.transition()
.style("opacity", opacity);

};
}
</script>

如果有人对此有可行的解决方案,那就太棒了,干杯:)

最佳答案

首先,我要说明为什么保持正确的选择很重要。例如,这里:

 group.append("path")
...
.on("mouseover", fade(5))
.on("mouseout", fade(5));

您为鼠标事件应用监听器,但在您下方(您可能正在 try catch 丝带,但我不确定),您覆盖了这两个监听器:

   svg.selectAll("path")
.on("mouseover", function(d) { ...

并且通过更复杂的方法(不遵循通常的模式),您还覆盖了 mouseout 的监听器。事件监听器只能为特定元素分配一次。由于我们需要为两个组(外弧)和色带设置不同的监听器,因此我们需要更改这种方法。

好消息是,这可以使代码更短、更清晰。为了重用您的色带选择,我创建了一个名为 ribbons 的变量来保存它,变量 group 将继续保存外弧。

我将打破我看到你尝试做的三个主要事件:

  1. 取消突出显示所有内容

这应该非常简单,我们可以使用如下函数:

function showAllRibbons() {
ribbons.style("opacity",1)
}
  1. 在鼠标事件中突出显示单个路径:

这也非常简单,我们隐藏所有其他内容并显示 this 指向的元素:

function highlightOneRibbon() {
ribbons.style("opacity",0.1);
d3.select(this).style("opacity",1);
}
  1. 突出显示在特定外弧中具有源或目标的所有色带。

这是最具挑战性的,它有助于查看每个色带的数据结构,它具有位于以下两个 anchor 的 id 的属性:d.source.indexd .target.index。现在使用选择组中每个外弧的索引,我们可以对满足基本条件的色带进行简单的筛选:

function highlightRibbons(d,i) {
ribbons.style("opacity",0.1); // set all relatively transparent
// fix the ones that need to be shown:
ribbons.filter(function(r) {
if(r.target.index == i || r.source.index == i) return r;
})
.style("opacity",1);

当然你可以更花哨一些,过滤掉那些不符合标准的让它们淡出,过滤掉那些符合条件的让它们淡入。

这个函数进一步证明了为什么你需要为 ribbon 和 arc 使用不同的事件监听器,因为这个函数不适用于 d3.selectAll("path").on("mouseouver,highlightRibbons ) 因为我们的索引可能是错误的(因为我们也在选择色带,但是这个函数对色带也没有意义)。


好的,所以。让我们去掉一些使用 d3.selectAll("path") 来操纵已经存在的元素的代码(大约从第 247 行开始?),因为这给我们带来了一些悲伤,而我们正在这样做,作为调用的事件监听器函数 fade 被覆盖,我们没有使用它,让我们也删除该函数。

因此,我失去了工具提示的交互性,但这似乎有一些独立于问题的问题(但同样,组和功能区可能需要单独的听众,以便工具提示具有基于它引用的特征类型)。

这是一个结果的快速演示,添加了一些显示组(转换)的技巧(因为片段似乎讨厌大量代码,我已经 trim 了工具提示样式和按钮等,因为它们不起作用无论如何在这个演示中或在这个演示中使用):

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(",.0", 1e3);

var chord = d3.chord()
.padAngle(0.05)
.sortSubgroups(d3.descending);

var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);

var ribbon = d3.ribbon()
.radius(innerRadius);

var color = d3.scaleOrdinal()
.domain(d3.range(4))
.range(["#4B5320", "#50C878", "#98FB98", "#679267","#2E8B57","#043927", "#0B6623","#9DC183","#708238", "#C7EA46", "#3F704D","#00A86B","8F9779"]);

var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
.datum(chord(matrix));

// Append the groups:
var group = g.append("g")
.attr("class", "groups")
.selectAll("g")
.data(function(chords) { return 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", highlightRibbons)
.on("mouseout", showAllRibbons)

group.append("text")
.each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; })
.attr("dy", ".35em")
.attr("class", "titles")
.attr("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
.attr("transform", function(d) {
if (outerArcs = 0) {
width = 10;
}
return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
+ "translate(" + (outerRadius + 10) + ")"
+ (d.angle > Math.PI ? "rotate(180)" : "");
})
.text(function(d,i) { return names[i]; });

// Append the ribbons
var ribbons = g.append("g") // save the selection as a variable
.attr("class", "ribbons")
.selectAll("path")
.data(function(chords) { return chords; })
.enter().append("path")
.attr("d", ribbon)
.style("fill", function(d) { return color(d.target.index); })
.attr("class","ribbon")
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); })
.on("mouseover",highlightOneRibbon)
.on("mouseout",showAllRibbons);


// New Functions:
// Highlight
function highlightRibbons(d,i) {
ribbons.filter(function(r) {
if(!(r.target.index == i || r.source.index == i)) return r;
})
.transition()
.style("opacity",0.1)
.duration(500);
ribbons.filter(function(r) {
if(r.target.index == i || r.source.index == i) return r;
})
.transition()
.style("opacity",1)
.duration(500);
}

// Unhighlight
function showAllRibbons() {
ribbons
//.transition() // don't use for individual ribbons - transition is too long
.style("opacity",1)
//.duration(500); // any visually effective transition will be too long given how quickly the mouse can cross multiple paths
}

// show a particular ribbon:
function highlightOneRibbon() {
ribbons.style("opacity",0.1);
d3.select(this).style("opacity",1);
}

// Returns an array of tick angles and values for a given group and step.
function groupTicks(d, i) {
var k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value,0.2).map(function(v, i) {
return {
angle: v * k + d.startAngle,
label: i*100 % 5 ? null : v,
id: i
};
});
}
.group-tick line {
stroke: #000;
}

.ribbons {
fill-opacity: 1;

}
<svg width="1000" height="1000"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>

关于javascript - D3 鼠标悬停组问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50581972/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com