两个具有常见下拉菜单的D3.js热图

时间:2018-09-04 15:50:46

标签: javascript html d3.js

我正在尝试创建两个热图,以显示在同一日期下拉列表中更新的不同数据。我使用heatmap with data update并创建两个单独的svg,以在下拉列表中选择新的日期字段时进行更新。我能够遵循一些SO答案在同一页面上创建两个图表,但是我完全不知道要删除哪一个位置同时更新两个图表。任何有关如何实现这一目标的指针将不胜感激。我已经包括了我一直在使用的代码和json数据。我现在有两个不同文件中的数据。如果它仅来自一个文件,甚至可以使其更易于读取位置下拉值,那就更好了。

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示例与上面的链接相同。只是修改了一些值以显示差异。 (不知道如何在此处包括大json文件)。再次感谢。

0 个答案:

没有答案