我正在使用一个函数来构建一系列 d3 散点图。基本上,每个散点图显示一系列“案例”,然后每个案例及时显示两个事件。 Y 轴上是案例,X 轴上是每个不同案例的两个时间事件。图片在这里:
每个图都基于一个 CSV,红/蓝点只是为电子表格中的每个“案例”记录绘制两个不同的日期列。
每个案例都映射在散点图上,每个案例都有两个不同的时间事件。目前,当鼠标悬停在圆上时,圆的半径会发生变化。我希望能够在将鼠标悬停在任一圆上时,使每种情况下的两个圆都改变半径,以便产生“链接”效果。例如,如果您将鼠标悬停在案例 1 的蓝点或红点上,这两个圆圈都会显得更大(一种在该案例中直观地链接这两个事件的方法)。
这是我用来构建每个散点图的函数:
function makeScatterplot(dataset, dataviz, field_1, field_2, field_3, numCases, maxAge, htmlText, xLabel, yLabel, legendItem1, legendItem2){
//load csv//read the data
d3.csv(dataset)
.then(function(data) {
//append svg to body of page
var margin = {top: 60, right: 30, bottom: 50, left: 60},
width = 580 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
var svg = d3.select(dataviz)
.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 + ")");
//add x axis
var x = d3.scaleLinear()
.domain([0,maxAge])
.range([0, width-100])
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.attr("class", "axisLine")
.call(d3.axisBottom(x));
//add y axis
var y = d3.scaleLinear()
.domain([0,numCases])
.range([ height, 0]);
svg.append("g")
.attr("class", "axisLine")
.call(d3.axisLeft(y));
// text label for the x axis
svg.append("text")
.attr("class", "axisLabel")
.attr("transform",
"translate(" + ((width-100)/2 ) + " ," +
(height + margin.top + -15) + ")")
.style("text-anchor", "middle")
.text("Age");
// Add the tooltip container to the vis container
var tooltip = d3.select("#my_dataviz").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
//add dots for field 1 (red circles)
svg.append("g")
.selectAll("dot")
.data(data)
.enter()
.append("circle")
.attr("cx", function (d) {return x(d[field_1]);})
.attr("cy", function (d) {return y(d.case);})
.attr("r", 6)
.attr("class", "events_1")
.style("fill", "ff4c4c")
.style("opacity", '.7')
.on("mouseover", function(data) {
d3.select(this).attr("r", 10)
d3.select('.tooltip')
tooltip.transition()
.duration(200)
.style("opacity", 1);
tooltip.html(data[field_3] + htmlText)
.style("left", (d3.event.pageX + 15) + "px")
.style("top", (d3.event.pageY - 18) + "px");
})
.on("mouseout", function(data) {
d3.select(this).style("stroke", 'none')
d3.select(this).attr("r", 6)
tooltip.transition()
.duration(500)
.style("opacity", 0);
})
//add dots for field 2 (blue circles)
svg.append("g")
.selectAll("dot")
.data(data)
.enter()
.append("circle")
.attr("cy", function (d) {return y(d.case);})
.attr("cx", function (d) {return x(d[field_2]);})
.attr("r", 6)
.attr("class", "events_2")
.style("fill", "#6666ff")
.style("opacity", '.8')
.on("mouseover", function(data) {
d3.select(this).attr("r", 10)
this_case = data.case // record the current case selected from blue circles on hover
d3.selectAll(".events_1") // change the radius of the red circle that matches the case selected from blue circles
.attr("r", function(this_case){
d3.select(this)
this_case=data.case
console.log(this_case)
if (this_case) {
return 10
}
else {
return 6
}
})
return this_case
//.data(data.filter(function(d){return d.case == d.case;}))
d3.select('.tooltip')
tooltip.transition()
.duration(200)
.style("opacity", 1);
tooltip.html(data[field_3] + htmlText)
.style("left", (d3.event.pageX + 15) + "px")
.style("top", (d3.event.pageY - 18) + "px");
})
.on("mouseout", function(data) {
d3.select(this).style("stroke", 'none')
d3.select(this).attr("r", 6)
tooltip.transition()
.duration(500)
.style("opacity", 0);
})
})
}
//Build scatterplots by calling function
makeScatterplot(dataset_suicide, dataviz_1, demo_dod, avi_suicide_date, suicide_to_DOD, 22, 70, suicide_html, xLabel, yLabel, suicide_title, dod_legend, suicide_legend, )
makeScatterplot(dataset_DOC, dataviz_1, demo_dod, doc_inc_release_dte, release_to_DOD, 20, 70, DOC_html, xLabel, yLabel, DOC_title, dod_legend, doc_legend)
makeScatterplot(dataset_last_od, dataviz_2, demo_dod, avi_od_date, od_to_death, 41, 75, last_od_html, xLabel, yLabel, last_od_title, dod_legend, last_od_legend)
目前,此代码将半径应用于蓝色圆圈悬停时的所有情况:
有没有一种简单的方法可以完成我想要完成的任务?基本上,只是尝试在悬停时链接这些圆圈,对于每个单独的散点图(圆圈半径只会增加散点图中选定的圆圈,来自相同的情况,而不是所有散点图)。
我猜我可能需要将圆类作为一个可变参数,以便可以相应地选择它们。
最佳答案
我明白您想用 if
语句做什么,但是当您将变量 this_case
定义为传递给 函数的对象时r
,对于 d3,这是绑定(bind)到每个单独选定对象的任何数据对象 - 覆盖我认为您尝试为上面几行 this_case
创建的范围。
在保留 this_case
的第一个定义的同时,尝试重命名传递到函数作用域的变量,如下所示,我刚刚将其更改为 d
:
.attr("r", function(d){
if (d.case == this_case) {
return 10
}
else {
return 6
}
})
替代方法:如果是我,我可能会为每个案例仅附加一个 g
标签,并带有一个包含案例编号的 id 内容。然后,我将两个圆圈附加到此标签,这样在鼠标悬停时我可以首先使用我创建的 id 选择适当的 g
标签,然后在其上执行 selectAll('circle')
更改两个圆圈。只是感觉更有条理,但当然,这只是我的意见!
关于javascript - 根据条件改变D3散点图上多个点的半径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59490983/