我正在尝试在我的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>
答案 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>