Skip to content

Instantly share code, notes, and snippets.

@kbroman
Last active February 9, 2024 05:19
Show Gist options
  • Save kbroman/ded6a0784706a109c3a5 to your computer and use it in GitHub Desktop.
Save kbroman/ded6a0784706a109c3a5 to your computer and use it in GitHub Desktop.
Linking two D3-based plots

An example that links two plots

This is an example to link two plots with D3, in response to a question posed by @keeghin.

See also this jsfiddle.

The typical thing I do is to assign a class to points that includes a data index, and then when hovering over one point, do the action on all points with the same class.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script charset="utf-8" type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<title>Example linking two plots with D3</title>
</head>
<body>
<h2>Example linking two plots with D3</h2>
<script type="text/javascript" src="linking.js"></script>
</body>
</html>
height = 300
width = 250
gap = 10
// overall svg
svg = d3.select("body")
.append("svg")
.attr("id", "mainsvg")
.attr("height", height)
.attr("width", width*2 + gap)
// first svg
svg1 = d3.select("svg#mainsvg")
.append("svg")
.attr("id", "svg1")
.attr("height", height)
.attr("width", width)
svg2 = d3.select("svg#mainsvg")
.append("g") // group to move svg sideways
.attr("transform", "translate(" + (width+gap) + ")")
.append("svg")
.attr("id", "svg2")
.attr("height", height)
.attr("width", width)
// add a box around each SVG
svg1.append("rect")
.attr("height", height)
.attr("width", width)
.attr("stroke", "black")
.attr("fill", "#ccc")
.attr("stroke-width", 2)
svg2.append("rect")
.attr("height", height)
.attr("width", width)
.attr("stroke", "black")
.attr("fill", "#ccc")
.attr("stroke-width", 2)
// simulate some data
n_pts = 20
index = d3.range(n_pts)
data = index.map(function(i) {
x = Math.random()*(width-10)+5;
y = x*0.3 + Math.random()*height/2;
z = x*0.4 + Math.random()*height/2;
return {x:x, y:y, z:z};
})
// plot y vs x in first plot
svg1.selectAll("empty")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return height-d.y+10; })
.attr("class", function(d,i) { return "pt" + i; })
.attr("r", 5)
.attr("stroke", "black")
.attr("fill", "slateblue")
.on("mouseover", function(d, i) {
console.log(i)
d3.selectAll("circle.pt" + i)
.attr("fill", "Orchid")
.attr("r", 10)
})
.on("mouseout", function(d, i) {
d3.selectAll("circle.pt" + i)
.attr("fill", "slateblue")
.attr("r", 5)
})
// plot z vs x in 2nd plot
svg2.selectAll("empty")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return height-d.z+10; })
.attr("class", function(d,i) { return "pt" + i; })
.attr("r", 5)
.attr("stroke", "black")
.attr("fill", "slateblue")
.on("mouseover", function(d, i) {
console.log(i)
d3.selectAll("circle.pt" + i)
.attr("fill", "Orchid")
.attr("r", 10)
})
.on("mouseout", function(d, i) {
d3.selectAll("circle.pt" + i)
.attr("fill", "slateblue")
.attr("r", 5)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment