我一直试图将热图与csv加载的数据投影到D3上的正交投影上。在旋转地球(即D3,正交投影)时,点/圆保持静止。我尝试了很多组合,但未能弄清楚缺少什么。
基本上,我需要小圈子沿着国家的道路前进。
以下是完整的代码:
<script>
var width = 600,
height = 500,
sens = 0.25,
focused;
//Setting projection
var projection = d3.geo.orthographic()
.scale(245)
.rotate([0,0])
.translate([width / 2, height / 2])
.clipAngle(90);
var path = d3.geo.path()
.projection(projection);
//SVG container
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
// Define the gradient
var gradient = svg.append("svg:defs")
.append("svg:linearGradient")
.attr("id", "gradient")
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "100%")
.attr("spreadMethod", "pad");
// Define the gradient colors
gradient.append("svg:stop")
.attr("offset", "0%")
.attr("stop-color", "#FFFF00")
.attr("stop-opacity", 0);
gradient.append("svg:stop")
.attr("offset", "100%")
.attr("stop-color", "#FF0000")
.attr("stop-opacity", 1);
//Adding water
svg.append("path")
.datum({type: "Sphere"})
.attr("class", "water")
.attr("d", path)
var countryTooltip = d3.select("body").append("div").attr("class", "countryTooltip"),
countryList = d3.select("body").append("select").attr("name", "countries");
queue()
.defer(d3.json, "world-110m.json")
.defer(d3.tsv, "world-110m-country-names.tsv")
.await(ready);
//Main function
function ready(error, world, countryData) {
var countryById = {},
countries = topojson.feature(world, world.objects.countries).features;
//Adding countries to select
countryData.forEach(function(d) {
countryById[d.id] = d.name;
option = countryList.append("option");
option.text(d.name);
option.property("value", d.id);
});
//circles for heatmap are coming from the csv below
d3.csv("cities.csv", function(error, data) {
svg.selectAll("circle")
.data(data)
.enter()
.append("a")
.attr("xlink:href", function(d) {
return "https://www.google.com/search?q="+d.city;}
)
.append("circle")
.attr("cx", function(d) {
return projection([d.lon, d.lat])[0];
})
.attr("cy", function(d) {
return projection([d.lon, d.lat])[1];
})
.attr("r", 5.5)
.attr('fill', 'url(#gradient)');
var world = svg.selectAll("path.circle")
.data(countries) //countries from the tsc file is used to populate the names
.enter().append("path")
.attr("class", "land")
.attr("d", path)
//.attr('fill', 'url(#gradient)')
//Drag event
.call(d3.behavior.drag()
.origin(function() { var r = projection.rotate(); return {x: r[0] / sens, y: -r[1] / sens}; })
.on("drag", function() {
var rotate = projection.rotate();
projection.rotate([d3.event.x * sens, -d3.event.y * sens, rotate[2]]);
svg.selectAll("path.land").attr("d", path);
svg.selectAll(".focused").classed("focused", focused = false);
}))
//Mouse events
.on("mouseover", function(d) {
countryTooltip.text(countryById[d.id])
.style("left", (d3.event.pageX + 7) + "px")
.style("top", (d3.event.pageY - 15) + "px")
.style("display", "block")
.style("opacity", 1);
})
.on("mouseout", function(d) {
countryTooltip.style("opacity", 0)
.style("display", "none");
})
.on("mousemove", function(d) {
countryTooltip.style("left", (d3.event.pageX + 7) + "px")
.style("top", (d3.event.pageY - 15) + "px");
});
});//closing d3.csv here
//Country focus on option select
d3.select("select").on("change", function() {
var rotate = projection.rotate(),
focusedCountry = country(countries, this),
p = d3.geo.centroid(focusedCountry);
svg.selectAll(".focused").classed("focused", focused = false);
//Globe rotating
(function transition() {
d3.transition()
.duration(2500)
.tween("rotate", function() {
var r = d3.interpolate(projection.rotate(), [-p[0], -p[1]]);
return function(t) {
projection.rotate(r(t));
svg.selectAll("path").attr("d", path)
.classed("focused", function(d, i) { return d.id == focusedCountry.id ? focused = d : false; });
//svg.selectAll("circle").attr("d", data)
//.classed("focused", function(d, i) { return d.id == focusedCountry.id ? focused = d : false; });
};
})
})();
});
function country(cnt, sel) {
for(var i = 0, l = cnt.length; i < l; i++) {
if(cnt[i].id == sel.value) {return cnt[i];}
}
};
};
</script>
请帮忙。
提前谢谢
答案 0 :(得分:0)
这是一个使用点几何的选项:
.enter().append('path')
.attr('class', 'circle_el')
.attr('fill', function(d) {return d.fill; })
.datum(function(d) {
return {type: 'Point', coordinates: [d.lon, d.lat], radius: some_radius};
})
.attr('d', path);
这很酷,因为您将使用路径重绘同时更新圈子。此外,它会将投影视为一个球体,而不是显示应该位于球体不可见侧的圆圈。我从杰森戴维斯的post得到了这个想法。