我想在d3.js映射中更改当前选定功能的颜色。但是,我的代码更改了我单击的每个功能的颜色。如何重置地图,以便当我单击一项功能时,以前单击的所有其他功能都将重置为默认颜色?下面是我的代码。颜色变化发生在“点击”功能上:
function ready(error, us) {
svg.append("g")
.selectAll("path")
.data(topojson.feature(us, us.objects.ecol3_wgs84).features)
.enter()
.append("path")
.attr("transform", "scale(" + SCALE + ")") //scale the map
.attr("class", "region")
.attr("ecoregion", function (d, i) {
return us.objects.ecol3_wgs84.geometries[i].properties.US_L3NAME;
})
.attr("d", path)
.on("mouseover", function (d) {
d3.select("h3").text(d.properties.US_L3NAME);
d3.select(this).attr("class", "region hover");
})
.on("mouseout", function (d) {
d3.select("h3").text("");
d3.select(this).attr("class", "region");
})
.on("click", function (d) {
var name = d.properties.US_L3NAME;
var region = d3.select("#regName");
region.property("value", name);
d3.select(this).style("fill", getColor(name));
});
}
function getColor(n) {
var selectedRegion = "";
selectedRegion = $("#regName").val();
if (n == selectedRegion) {
return 'orange';
}
else {
return '#005DAA';
}
}
Run Code Online (Sandbox Code Playgroud)
在click事件中,您可以将所有其他功能重置为其默认状态,然后将clicked功能设置为所需的样式:
.on("click", function (d) {
svg.selectAll('path').attr('class','region');
d3.select(this).attr('class','selected');
})
Run Code Online (Sandbox Code Playgroud)
为所选课程创建一个班级样式。据我所知,如果您将一个样式与selection.style一起应用,它将覆盖您的css样式,这就是为什么我在这里提出仅使用类的解决方案的原因。但这为我提供了一个替代解决方案的想法,该解决方案几乎不需要修改您的代码,请参见下文
但是,主要问题是,当您将鼠标悬停在鼠标上时,会将单击的功能重置为默认样式:
.on("mouseout", function (d) {
d3.select("h3").text("");
d3.select(this).attr("class", "region");
})
Run Code Online (Sandbox Code Playgroud)
而且由于单击必须在鼠标移出之前发生,所以一旦鼠标移动,您将失去单击样式。
在所有情况下,都很难将鼠标悬停/鼠标悬停和单击两者结合在一起才能获得所需的行为。
您需要:
从单击的功能中删除鼠标移出的事件侦听器,但在不再“单击”或激活后将其放回。
删除鼠标悬停侦听器的单击的功能,但将其放回不再被单击后。否则,将鼠标悬停在单击的要素上后,鼠标悬停将改变您的样式,这在处理小要素或不规则绘制的要素(例如生态区域/区域)时很容易。
当点击事件发生时,删除操作很容易:
d3.select(this).on('mouseout',null)
Run Code Online (Sandbox Code Playgroud)
单击下一个功能时,要重新添加侦听器还需要做更多工作。
这样做会稍微改变您的代码。我将在此处显示一个潜在的解决方案,但删除对更改输入框和标题的引用,这样会更简洁:
.on("mouseover", function (d) {
d3.select(this).attr("class", "region hover");
d3.select(this).on("mouseout", function(d) {
d3.select(this).attr("class", "region");
})
})
.on("click", function (d) {
svg.selectAll('path').attr('class','region'); // ensure every other feature is set to default
d3.selectAll('path').on("mouseover", function (d) { // add a mouseover event to every feature in order to get the last one clicked
d3.select(this).attr("class", "region hover");
d3.select(this).on("mouseout", function(d) {
d3.select(this).attr("class", "region"); // add a mouseout event to every feature on mouseover
});
});
d3.select(this).on("mouseout", null); // cancel mouseover out events for the clicked feature.
d3.select(this).on('mouseover',null);
d3.select(this).attr('class','selected');
});
Run Code Online (Sandbox Code Playgroud)
我在这里打包了一个包含您的地理特征的示例。您可以通过使用鼠标悬停功能的函数来清理它,基本上重复了这一部分。最后,可能有很多实现此目标的方法,这只是其中之一。但是,这应该演示如何设置事件侦听器,以使它们彼此不冲突,从而获得所需的结果。
更快的解决方案:(如上所述)
您应该能够修改单击功能,以从其他单击的元素中删除所有与selection.style一起应用的填充样式,然后将其应用于单击的功能:
.on("click", function (d) {
d3.selectAll('path').style('fill',null);
d3.select(this).style("fill","orange")
});
Run Code Online (Sandbox Code Playgroud)
这应该与您上面发布的代码一起使用。