I am trying to create two heatmaps showing different data updated by a common date drop down. I am using heatmap with data update and creating two separate svgs to update when a new date field is selected in the dropdown. I was able to follow some of the SO answers to create two plots in the same page, but I am totally clueless as to have just one drop down of the locations update both charts simultaneously. Any pointers on how to achieve this would be greatly appreciated. I have included the code I have been working with and the json data. I have the data in two different files for now. Would be even better if it can be just from one file to make it easier to read the location dropdown value.
var dataset;
var dataset2;
var days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
times = d3.range(24);
var margin = {top:40, right:50, bottom:70, left:50};
// calculate width and height based on window size
var w = Math.max(Math.min(window.innerWidth, 1000), 500) - margin.left - margin.right - 20,
gridSize = Math.floor(w / times.length),
h = gridSize * (days.length+2);
//reset the overall font size
var newFontSize = w * 62.5 / 900;
d3.select("html").style("font-size", newFontSize + "%");
// svg container
var svg = d3.select("#heatmap")
.append("svg")
.attr("width", w + margin.top + margin.bottom)
.attr("height", h + margin.left + margin.right)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// svg container
var svg2 = d3.select("#heatmap2")
.append("svg")
.attr("width", w + margin.top + margin.bottom)
.attr("height", h + margin.left + margin.right)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// linear colour scale
var colours = d3.scaleLinear()
.domain(d3.range(1, 11, 1))
.range(["#87cefa", "#86c6ef", "#85bde4", "#83b7d9", "#82afce", "#80a6c2", "#7e9fb8", "#7995aa", "#758b9e", "#708090"]);
var dayLabels = svg.selectAll(".dayLabel")
.data(days)
.enter()
.append("text")
.text(function(d) { return d; })
.attr("x", 0)
.attr("y", function(d, i) { return i * gridSize; })
.style("text-anchor", "end")
.attr("transform", "translate(-6," + gridSize / 1.5 + ")")
var dayLabels = svg2.selectAll(".dayLabel")
.data(days)
.enter()
.append("text")
.text(function(d) { return d; })
.attr("x", 0)
.attr("y", function(d, i) { return i * gridSize; })
.style("text-anchor", "end")
.attr("transform", "translate(-6," + gridSize / 1.5 + ")")
var timeLabels = svg.selectAll(".timeLabel")
.data(times)
.enter()
.append("text")
.text(function(d) { return d; })
.attr("x", function(d, i) { return i * gridSize; })
.attr("y", 0)
.style("text-anchor", "middle")
.attr("transform", "translate(" + gridSize / 2 + ", -6)");
var timeLabels = svg2.selectAll(".timeLabel")
.data(times)
.enter()
.append("text")
.text(function(d) { return d; })
.attr("x", function(d, i) { return i * gridSize; })
.attr("y", 0)
.style("text-anchor", "middle")
.attr("transform", "translate(" + gridSize / 2 + ", -6)");
// load data heatmap 1
d3.json("test.json", function(error, data) {
data.forEach(function(d) {
d.day = +d.day;
d.hour = +d.hour;
d.value = +d.value;
});
dataset = data;
// group data by location
var nest = d3.nest()
.key(function(d) { return d.location; })
.entries(dataset);
// array of locations in the data
var locations = nest.map(function(d) { return d.key; });
var currentLocationIndex = 0;
// create location dropdown menu
var locationMenu = d3.select("#locationDropdown1");
locationMenu
.append("select")
.attr("id", "locationMenu")
.selectAll("option")
.data(locations)
.enter()
.append("option")
.attr("value", function(d, i) { return i; })
.text(function(d) { return d; });
// function to create the initial heatmap
var drawHeatmap = function(location) {
// filter the data to return object of location of interest
var selectLocation = nest.find(function(d) {
return d.key == location;
});
var heatmap = svg.selectAll(".hour")
.data(selectLocation.values)
.enter()
.append("rect")
.attr("x", function(d) { return (d.hour-1) * gridSize; })
.attr("y", function(d) { return (d.day-1) * gridSize; })
.attr("class", "hour bordered")
.attr("width", gridSize)
.attr("height", gridSize)
.style("stroke", "white")
.style("stroke-opacity", 0.6)
.style("fill", function(d) { return colours(d.value); })
}
drawHeatmap(locations[currentLocationIndex]);
var updateHeatmap = function(location) {
// filter data to return object of location of interest
var selectLocation = nest.find(function(d) {
return d.key == location;
});
// update the data and redraw heatmap
var heatmap = svg.selectAll(".hour")
.data(selectLocation.values)
.transition()
.duration(500)
.style("fill", function(d) { return colours(d.value); })
}
// run update function when dropdown selection changes
locationMenu.on("change", function() {
// find which location was selected from the dropdown
var selectedLocation = d3.select(this)
.select("select")
.property("value");
currentLocationIndex = +selectedLocation;
// run update function with selected location
updateHeatmap(locations[currentLocationIndex]);
});
})
// load data heatmap 2
d3.json("test2.json", function(error, data2) {
data2.forEach(function(d2) {
d2.day = +d2.day;
d2.hour = +d2.hour;
d2.value = +d2.value;
});
dataset2 = data2;
// group data by location
var nest2 = d3.nest()
.key(function(d2) { return d2.location; })
.entries(dataset2);
// array of locations in the data
var locations2 = nest2.map(function(d2) { return d2.key; });
var currentLocationIndex2 = 0;
// create location dropdown menu
var locationMenu2 = d3.select("#locationDropdown2");
locationMenu2
.append("select")
.attr("id", "locationMenu")
.selectAll("option")
.data(locations2)
.enter()
.append("option")
.attr("value", function(d2, i2) { return i2; })
.text(function(d2) { return d2; });
// function to create the initial heatmap
var drawHeatmap2 = function(location2) {
// filter the data to return object of location of interest
var selectLocation2 = nest2.find(function(d2) {
return d2.key == location2;
});
var heatmap2 = svg2.selectAll(".hour")
.data(selectLocation2.values)
.enter()
.append("rect")
.attr("x", function(d2) { return (d2.hour-1) * gridSize; })
.attr("y", function(d2) { return (d2.day-1) * gridSize; })
.attr("class", "hour bordered")
.attr("width", gridSize)
.attr("height", gridSize)
.style("stroke", "white")
.style("stroke-opacity", 0.6)
.style("fill", function(d2) { return colours(d2.value); })
}
drawHeatmap2(locations2[currentLocationIndex2]);
var updateHeatmap2 = function(location2) {
console.log("currentLocationIndex: " + currentLocationIndex2)
// filter data to return object of location of interest
var selectLocation2 = nest2.find(function(d2) {
return d2.key == location2;
});
// update the data and redraw heatmap
var heatmap2 = svg2.selectAll(".hour")
.data(selectLocation2.values)
.transition()
.duration(500)
.style("fill", function(d2) { return colours(d2.value); })
}
// run update function when dropdown selection changes
locationMenu2.on("change", function() {
// find which location was selected from the dropdown
var selectedLocation2 = d3.select(this)
.select("select")
.property("value");
currentLocationIndex2 = +selectedLocation2;
// run update function with selected location
updateHeatmap2(locations2[currentLocationIndex2]);
});
})
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
html {
font-size: 62.5%;
}
body {
margin-top: 30px;
font-size: 1.4rem;
font-family: 'Source Sans Pro', sans-serif;
font-weight: 400;
fill: #696969;
text-align: center;
}
.timeLabel, .dayLabel {
font-size: 1.6rem;
fill: #AAAAAA;
font-weight: 300;
}
#nav-container {
display: flex;
justify-content: center;
cursor: pointer;
}
</style>
</head>
<body>
<div id="nav-container">
<div id="locationDropdown1"></div>
</div>
<div id="heatmap"></div>
<div id="nav-container">
<div id="locationDropdown2"></div>
</div>
<div id="heatmap2"></div>
JSON sample is the same as the link above .. just with some values modified to show differentiation. (Not sure how to include a big json file on here). Thanks again.