我是D3.js的新人,我被要求接管其他人在工作的项目。
目标是获得一个拉入点的json数据的地图,然后当点击这些点时,会弹出一个jQuery对话框,其中包含每个点的正确json数据。
我已经能够在地图上使用jQuery弹出窗口,但是点击的每个点都填充了完全相同的文本。
我还测试了使用$ .getJSON在一个简单的html页面中加载和显示json数据,我能够让它循环遍历所有的json数据。
以下是创建点的功能:
function addCirclesForArray(element,index,array) {
var coordinates =
projection([element.sendLocation.longitude,element.sendLocation.latitude]);
g.append("circle")
.attr("cx",coordinates[0])
.attr("cy",coordinates[1])
.attr("r",(index<array.length-1)?2:4)
.attr("r",4)
.style("fill",$colorScale(d3.round(element.profileReadings[0].psal)))
.attr("class","circle")
g.selectAll("circle")
.on("click",circleClicked)
}
这是我循环jQuery弹出窗口的json数据的方法:
function circleClicked(data, i) {
console.log(data) // undefined
console.log(i); // index #
$.getJSON("data/oc-readings3.json", function(data){
$.each(data, function(key, value){
//populate jQuery dialog
$('#floatID').text("Float ID: "+value.platformNumber);
$('#latitude').text("Latitude: "+value.sendLocation.latitude);
$('#longitude').text("Longitude: "+value.sendLocation.longitude);
// jQuery UI dialog and tabs
$( "#tabs" ).tabs();
$( "#dialog" ).dialog({ width: 400 })
});
});
}
我可能在getJSON方法中忽略了一些简单的循环,或者它可能与未定义的数据有关。如果您有任何提示,请告诉我。感谢。
UPDATE /解决方案 我意识到我不需要使用$ .getJSON,因为我已经在addCirclesForArray方法中获取了json数据。我可以使用传入的数组参数中的索引。
我还摆脱了circleClicked方法,并将新逻辑添加到addCirclesForArray方法中。
g.selectAll("circle")
.on("mouseover", increaseSize)
.on("mouseout", decreaseSize)
.on("click", function(d,i) {
//console.log(array[i]);
//jQuery popup
$( "#tabs" ).tabs();
$( "#dialog" ).dialog({
width: 418,
resizable: false
});
//populate tabs
$('#floatID').text("Float ID: "+array[i].platformNumber);
// etc.
答案 0 :(得分:0)
使用d3的 selection.on(类型,回调)绑定(单击,鼠标悬停等)处理程序时,您的回调函数调用其上下文(“this”)绑定到单击的DOM节点,并将元素的数据作为其第一个参数。 为了使其工作,您需要首先将数据绑定到D3创建的DOM / SVG节点。
我建议使用声明性数据绑定,而不是循环遍历数据元素。 D3的创建者Mike Bostock提供a general overview on declarative binding in d3(“联接”)以及thorough, technical explanation。
对于对话框,基本思想是只定义一个对话框/弹出/工具提示,它最初是隐藏的,并且对于每个被点击的节点都可以重用。从回调函数中,您可以将对话框中的占位符字段替换为数据对象中的实际值。
您的示例可能会被修改为如下所示:
var containerElement = $('#container'),
svg = d3.select(containerElement).append('svg')
/* .attr('width', ...).attr('height',...)*/;
// jQuery UI dialog and tabs
$( "#tabs" ).tabs();
$( "#dialog" ).dialog({ width: 400 });
$.getJSON("data/oc-readings3.json", addCirclesForArray);
/** called only once */
function addCirclesForArray(data) {
var coordinates = [];
$.each(data, function(key, value){
coordinates.push(projection([value.sendLocation.longitude, value.sendLocation.latitude]));
});
// data join / declarative binding
// caution: binding requires an array of array(s)!
var groups = svg.selectAll('g').data([data]);
// exit
groups.exit().remove();
// enter
groups.enter().append("svg:circle");
// enter + update
groups.attr("cx",coordinates[0])
.attr("cy",coordinates[1])
.attr("r", function(d,index) {
return (index<array.length-1)? 2: 4;
})
//.attr("r", 4) // duplicate assignment of r
.style("fill", function(d) {
return $colorScale(d3.round(d.profileReadings[0].psal));
})
.attr("class","circle");
groups.selectAll("circle")
.on("click", circleClicked); // :TODO: bind circleClicked to your preferred context
}
/**
* @param {arrayElement} data
* @this {svg:circle}
*/
function circleClicked(data) {
var dialog = $('dialogPlaceholder');
$('#floatID', dialog).text("Float ID: " + data.platformNumber);
$('#latitude', dialog).text("Latitude: " + data.sendLocation.latitude);
$('#longitude', dialog).text("Longitude: " + data.sendLocation.longitude);
}