我仍处于学习如何操作javascript和d3的初级阶段,在搜索之后,我无法弄清楚如何将正确的信息输入到我的工具提示中。
我已经采用了已编码的hexbin script并将其替换为.csv格式的学校数据。它在map上正确显示。但是,当我尝试传递工具提示的学校名称信息时,我得到:
[错误] TypeError:undefined不是对象(评估'd.school') (匿名函数)(d3.min.js,第1行)
我尝试使用以下代码调用学校名称:
function makePie (data) {
var tooltip = d3.select("#tooltip")
.html(function(d){
return d.school;
})
}
我的完整脚本在这里:
L.HexbinLayer = L.Class.extend({
includes: L.Mixin.Events,
initialize: function (rawData, options) {
this.levels = {};
this.layout = d3.hexbin().radius(10);
this.rscale = d3.scale.sqrt().range([0, 10]).clamp(false);
this.rwData = rawData;
this.config = options;
},
project: function(x) {
var point = this.map.latLngToLayerPoint([x[1], x[0]]);
return [point.x, point.y];
},
getBounds: function(d) {
var b = d3.geo.bounds(d)
return L.bounds(this.project([b[0][0], b[1][1]]), this.project([b[1][0], b[0][1]]));
},
update: function () {
var pad = 100, xy = this.getBounds(this.rwData), zoom = this.map.getZoom();
this.container
.attr("width", xy.getSize().x + (2 * pad))
.attr("height", xy.getSize().y + (2 * pad))
.style("margin-left", (xy.min.x - pad) + "px")
.style("margin-top", (xy.min.y - pad) + "px");
if (!(zoom in this.levels)) {
this.levels[zoom] = this.container.append("g").attr("class", "zoom-" + zoom);
this.genHexagons(this.levels[zoom]);
this.levels[zoom].attr("transform", "translate(" + -(xy.min.x - pad) + "," + -(xy.min.y - pad) + ")");
}
if (this.curLevel) {
this.curLevel.style("display", "none");
}
this.curLevel = this.levels[zoom];
this.curLevel.style("display", "inline");
},
genHexagons: function (container) {
var data = this.rwData.features.map(function (d) {
var coords = this.project(d.geometry.coordinates)
return [coords[0],coords[1], d.properties];
}, this);
var bins = this.layout(data);
var hexagons = container.selectAll(".hexagon").data(bins);
var counts = [];
bins.map(function (elem) { counts.push(elem.length) });
this.rscale.domain([0, (ss.mean(counts) + (ss.standard_deviation(counts) * 10))]);
var path = hexagons.enter().append("path").attr("class", "hexagon");
this.config.style.call(this, path);
that = this;
hexagons
.attr("d", function(d) { return that.layout.hexagon(that.rscale(d.length)); })
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.on("mouseover", function (d) {
var s=0, k=0;
that.config.mouse.call(this, [s,k]);
d3.select("#tooltip")
.style("visibility", "visible")
.style("top", function () { return (d3.event.pageY - 115)+"px"})
.style("left", function () { return (d3.event.pageX - 115)+"px";});
})
.on("mouseout", function (d) { d3.select("#tooltip").style("visibility", "hidden") });
},
addTo: function (map) {
map.addLayer(this);
return this;
},
onAdd: function (map) {
this.map = map;
var overlayPane = this.map.getPanes().overlayPane;
if (!this.container || overlayPane.empty) {
this.container = d3.select(overlayPane)
.append('svg')
.attr("id", "hex-svg")
.attr('class', 'leaflet-layer leaflet-zoom-hide');
}
map.on({ 'moveend': this.update }, this);
this.update();
}
});
L.hexbinLayer = function (data, styleFunction) {
return new L.HexbinLayer(data, styleFunction);
};
//**********************************************************************************
//******** IMPORT DATA AND REFORMAT ***********************************************
//**********************************************************************************
d3.csv('http://test.indiscreetacumen.com/schoolRawV.csv', function (error, schools) {
function reformat (array) {
var data = [];
array.map(function (d){
data.push({
properties: {
nfree: +d.nfree,
free: +d.free,
school: d.school
},
type: "Feature",
geometry: {
coordinates:[+d.longitude,+d.latitude],
type:"Point"
}
});
});
return data;
}
var geoData = { type: "FeatureCollection", features: reformat(schools) };
//**********************************************************************************
//******** CREATE LEAFLET MAP *****************************************************
//**********************************************************************************
var cscale = d3.scale.linear().domain([0,1]).range(["#00FF00","#FFA500"]);
// PLEASE DO NOT USE MY MAP ID :) YOU CAN GET YOUR OWN FOR FREE AT MAPBOX.COM
L.mapbox.accessToken = 'pk.eyJ1IjoiZG5ld21zIiwiYSI6IlR6WE9kUDAifQ.IXJ0PfUXntjO2LeyaxDzWw';
var leafletMap = L.mapbox.map('mapContainer', 'dnewms.4e733c6b')
.setView([47.62, -122.362], 11);
//**********************************************************************************
//******** ADD HEXBIN LAYER TO MAP AND DEFINE HEXBIN STYLE FUNCTION ***************
//**********************************************************************************
var hexLayer = L.hexbinLayer(geoData, {
style: hexbinStyle,
mouse: schoolName
}).addTo(leafletMap);
function hexbinStyle(hexagons) {
hexagons
.attr("stroke", "grey")
.attr("fill", function (d) {
var avg = d3.mean(d, function(d) { return +d[2].free; })
return cscale(avg);
})
};
//**********************************************************************************
//******** PIE CHART ROLL-OVER ****************************************************
//**********************************************************************************
function schoolName (hexagons) {
var svg = d3.select("#tooltip").select("svg")
.append("g")
.attr("transform", "translate(50,50)");
var g = svg.selectAll("svg")
.data(schools)
.enter().append("g");
g.append("text")
.style("text-anchor", "middle")
.text(function (d, i) {
return d.school;
});
}
});
我知道导入地图的数据会将其放入巢中,但是当脚本似乎失去对'd'的引用时,我不确定如何深入查看学校名称。
谢谢,并随时指出我可能尚未发现的答案。