在D3

时间:2018-04-17 03:30:43

标签: google-maps d3.js heatmap

我正在尝试在我的D3可视化中使用Google地图热图图层。我跟着Mike Bostock's example在D3中创建了一个谷歌地图图层,并使用我的数据文件添加了标记。然后我尝试将其扩展为使用Google地图中的热图图层而不是标记上的简单圆圈。我无法弄清楚这段代码中的问题是什么,我不明白我得到的错误(Uncaught TypeError: Cannot read property 'NaN' of undefined)。

var csvData = "lat,lon,temp1,temp2\n41.87148,-87.67644,6.68,39.8\n41.880497,-87.745268,4.75,7.6\n41.910922,-87.649518,7.39,36.5\n41.866786,-87.666306,6.5,39\n41.751142,-87.71299,5.46,14.2\n41.786756,-87.664343,5.33,34.1\n41.808594,-87.665048,6.15,27.8\n41.666078,-87.539374,3.79,32\n41.823527,-87.641054,5.12,31.6\n41.946373,-87.727382,6.73,35.2\n41.751142,-87.71299,5.02,37.5\n41.764122,-87.72242,4.5,34\n41.903632,-87.648093,5.3,30.6\n41.713867,-87.536509,4.68,31.3\n41.800846,-87.703739,4.99,32.7\n41.918733,-87.668257,5.24,34\n41.83107,-87.617298,5.8,8.4\n41.92617,-87.631533,5.31,33.5\n41.794477,-87.615957,4.9,33.3\n41.906481,-87.671373,5.28,18.4\n41.741148,-87.54045,,\n41.891964,-87.611603,,\n41.858136, -87.616055,,\n41.857797,-87.685806,,\n41.881172,-87.686359,,\n41.954626,-87.645247,,"
var colorScale = d3.scale.linear().range(['blue', 'yellow']);

var tooltip = d3.select("#map").append("div")
    .attr("class", "tooltip")
    .style("opacity", 0);

// Create the Google Map…
var map = new google.maps.Map(d3.select("#map").node(), {
  zoom: 10,
  center: new google.maps.LatLng(41.83379085476929,-87.73212559320208),
  mapTypeId: google.maps.MapTypeId.TERRAIN
});

data=d3.csv.parse(csvData)
  var heatmapData = [];
  data.forEach(function(d){
	heatmapData.push(new google.maps.LatLng(d.lat, d.lng));
  });
  var heatmap = new google.maps.visualization.HeatmapLayer({
          data: heatmapData,
		  map: map
    });
  
  var max=d3.max(data, function(d) { return d.temp1; });
  var min=d3.min(data, function(d) { return d.temp1; });
  
  if(max>0 && min>0){ min=-max;}
  if(max<0 && min<0){ max=-min;}
  
  colorScale.domain([min,max]);

  var overlay = new google.maps.OverlayView();

  // Add the container when the overlay is added to the map.
  overlay.onAdd = function() {
    var layer = d3.select(this.getPanes().overlayMouseTarget).append("div")
        .attr("class", "nodes");
		
    overlay.draw = function() {
      var projection = this.getProjection(),
          padding = 10;

      var marker = layer.selectAll("svg")
          .data(data)
          .each(transform)
        .enter().append("svg")
          .each(transform)
          .attr("class", "marker")
		.on("mouseover", function(d) {
			tooltip.transition()
				 .duration(200)
				 .style("opacity", 1);
			tooltip.html(d.node_id)
				 .style("left", (d3.event.pageX) + "px")
				 .style("top", (d3.event.pageY) + "px");
		})
		.on("mouseout", function(d) {
			tooltip.transition()
				.duration(500)
				.style("opacity", 0);
		});

      
      marker.append("circle")
          .attr("r", 7)
          .attr("cx", padding)
          .attr("cy", padding)
		  .style("fill", function(d) { 
			if(d.temp1){
				return colorScale(d.temp1); 
				}
			else 
				return "none";
			});
		  
      
      marker.append("text")
          .attr("x", padding + 7)
          .attr("y", padding)
          .attr("dy", ".31em")
          .text(function(d) { return d.temp1; });

      function transform(d) {
        d = new google.maps.LatLng(d.lat, d.lon);
        d = projection.fromLatLngToDivPixel(d);
        return d3.select(this)
            .style("left", (d.x - padding) + "px")
            .style("top", (d.y - padding) + "px");
      }
    };
  };

  overlay.setMap(map);
html, body, #map {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

.nodes, .nodes svg {
  position: absolute;
}

.nodes svg {
  width: 60px;
  height: 20px;
  padding-right: 100px;
  font: 10px sans-serif;
}

.nodes circle {
  stroke: black;
  stroke-width: 1px;
}

.tooltip {
    position: absolute;
    text-align: center;
	min-width: 200;
    width: auto;
	min-height:25;
    height: auto;
    padding: 2px;		
    font: 10px sans-serif;
    background: rgba(0, 0, 0, 0.8);
	color: #fff;
    border: 0px;
    border-radius: 8px;
    pointer-events: none;
}
<!DOCTYPE html>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.10/d3.min.js"></script>
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?libraries=visualization"></script>

1 个答案:

答案 0 :(得分:1)

我的代码错误是:

Uncaught TypeError: Cannot read property 'NaN' of undefined

您的代码中有拼写错误。您正在传递d.lat / d.lon;但代码需要d.lat / d.lng。更改代码以使用d.lon或更改对象以包含d.lng。 (您的代码不一致,它在热图中使用d.lng,在d3代码中使用d.lon

更新了代码段(使用d.lng并删除d3标记,因为它们隐藏了热图):

var csvData = "lat,lng,temp1,temp2\n41.87148,-87.67644,6.68,39.8\n41.880497,-87.745268,4.75,7.6\n41.910922,-87.649518,7.39,36.5\n41.866786,-87.666306,6.5,39\n41.751142,-87.71299,5.46,14.2\n41.786756,-87.664343,5.33,34.1\n41.808594,-87.665048,6.15,27.8\n41.666078,-87.539374,3.79,32\n41.823527,-87.641054,5.12,31.6\n41.946373,-87.727382,6.73,35.2\n41.751142,-87.71299,5.02,37.5\n41.764122,-87.72242,4.5,34\n41.903632,-87.648093,5.3,30.6\n41.713867,-87.536509,4.68,31.3\n41.800846,-87.703739,4.99,32.7\n41.918733,-87.668257,5.24,34\n41.83107,-87.617298,5.8,8.4\n41.92617,-87.631533,5.31,33.5\n41.794477,-87.615957,4.9,33.3\n41.906481,-87.671373,5.28,18.4\n41.741148,-87.54045,,\n41.891964,-87.611603,,\n41.858136, -87.616055,,\n41.857797,-87.685806,,\n41.881172,-87.686359,,\n41.954626,-87.645247,,"
var colorScale = d3.scale.linear().range(['blue', 'yellow']);

var tooltip = d3.select("#map").append("div")
  .attr("class", "tooltip")
  .style("opacity", 0);

// Create the Google Map…
var map = new google.maps.Map(d3.select("#map").node(), {
  zoom: 10,
  center: new google.maps.LatLng(41.83379085476929, -87.73212559320208),
  mapTypeId: google.maps.MapTypeId.TERRAIN
});

data = d3.csv.parse(csvData)
var heatmapData = [];
data.forEach(function(d) {
  heatmapData.push(new google.maps.LatLng(d.lat, d.lng));
});
var heatmap = new google.maps.visualization.HeatmapLayer({
  data: heatmapData,
  map: map
});

var max = d3.max(data, function(d) {
  return d.temp1;
});
var min = d3.min(data, function(d) {
  return d.temp1;
});

if (max > 0 && min > 0) {
  min = -max;
}
if (max < 0 && min < 0) {
  max = -min;
}

colorScale.domain([min, max]);

var overlay = new google.maps.OverlayView();

// Add the container when the overlay is added to the map.
overlay.onAdd = function() {
  var layer = d3.select(this.getPanes().overlayMouseTarget).append("div")
    .attr("class", "nodes");

  overlay.draw = function() {
    /* var projection = this.getProjection(),
      padding = 10;

    var marker = layer.selectAll("svg")
      .data(data)
      .each(transform)
      .enter().append("svg")
      .each(transform)
      .attr("class", "marker")
      .on("mouseover", function(d) {
        tooltip.transition()
          .duration(200)
          .style("opacity", 1);
        tooltip.html(d.node_id)
          .style("left", (d3.event.pageX) + "px")
          .style("top", (d3.event.pageY) + "px");
      })
      .on("mouseout", function(d) {
        tooltip.transition()
          .duration(500)
          .style("opacity", 0);
      });


    marker.append("circle")
      .attr("r", 7)
      .attr("cx", padding)
      .attr("cy", padding)
      .style("fill", function(d) {
        if (d.temp1) {
          return colorScale(d.temp1);
        } else
          return "none";
      });


    marker.append("text")
      .attr("x", padding + 7)
      .attr("y", padding)
      .attr("dy", ".31em")
      .text(function(d) {
        return d.temp1;
      });
*/
    function transform(d) {
      d = new google.maps.LatLng(d.lat, d.lng);
      d = projection.fromLatLngToDivPixel(d);
      return d3.select(this)
        .style("left", (d.x - padding) + "px")
        .style("top", (d.y - padding) + "px");
    }
  };
};

overlay.setMap(map);
html,
body,
#map {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

.nodes,
.nodes svg {
  position: absolute;
}

.nodes svg {
  width: 60px;
  height: 20px;
  padding-right: 100px;
  font: 10px sans-serif;
}

.nodes circle {
  stroke: black;
  stroke-width: 1px;
}

.tooltip {
  position: absolute;
  text-align: center;
  min-width: 200;
  width: auto;
  min-height: 25;
  height: auto;
  padding: 2px;
  font: 10px sans-serif;
  background: rgba(0, 0, 0, 0.8);
  color: #fff;
  border: 0px;
  border-radius: 8px;
  pointer-events: none;
}
<!DOCTYPE html>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.10/d3.min.js"></script>
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?libraries=visualization"></script>