我创造了一个有圆圈和拖动的地球仪。问题是圆圈出现在地球的远端。我希望隐藏这些圈子。
我的bl.ock可以在这里找到: http://bl.ocks.org/anonymous/dc2d4fc810550586d40d4b1ce9088422/40c6e199a5be4e152c0bd94a13ea94eba41f004b
例如,我希望我的地球功能像这样:https://bl.ocks.org/larsvers/f8efeabf480244d59001310f70815b4e
我已经看过像这样的解决方案:How to move points in an orthogonal map?但它对我来说并不适用。由于d [0]和d [1]似乎未定义,因此这些点就会消失。
我也尝试过使用这样的方法:http://blockbuilder.org/tlfrd/df1f1f705c7940a6a7c0dca47041fec8但这似乎也不起作用。这里的问题似乎是他使用json作为他的数据,而我的圈子数据独立于json。
我发现的只有一个类似的例子:来自Curran的https://bl.ocks.org/curran/115407b42ef85b0758595d05c825b346,但我并不真正理解他的代码。他的方法与我的方法完全不同。
这是我的JavaScript代码:
(function(){
var h = 600;
var w = 900;
var i = 0;
var map = void 0;
var world = void 0;
var US = void 0;
var margin = {
top: 10,
bottom: 40,
left: 0,
right: 30
};
var circleScale = d3.scaleSqrt()
.domain([0, 4445])
.range([0.5, 10])
var width = w - margin.left - margin.right;
var height = h - margin.top - margin.bottom;
var dragging = function(d){
var c = projection.rotate();
projection.rotate([c[0] + d3.event.dx/6, c[1] - d3.event.dy/6])
map.selectAll('path').attr('d', path);
map.selectAll(".circles").attr("cx", function(d){
var coords = projection([d.Longitude_imp, d.Latitude_imp])
return coords[0];
})
.attr("cy", function(d){
var coords = projection([d.Longitude_imp, d.Latitude_imp])
return coords[1];
})
}
var drag = d3.drag()
.on("drag", dragging)
var projection = d3.geoOrthographic().clipAngle(90);
var path = d3.geoPath().projection(projection);
var svg = d3.select("body")
.append("svg")
.attr("id", "chart")
.attr("width", w)
.attr("height", h)
d3.json("world.json", function(json){
d3.csv("arms_transfer_2012_2016_top - arms_transfer_2012_2016_top.csv", function(error, data){
var countries = topojson.feature(json, json.objects.countries).features
var US = countries[168]
map = svg.append('g').attr('class', 'boundary');
world = map.selectAll('path').data(countries);
US = map.selectAll('.US').data([US]);
Circles = map.selectAll(".circles").data(data)
console.log(countries[168])
world.enter()
.append("path")
.attr("class", "boundary")
.attr("d", path)
US.enter()
.append("path")
.attr("class", "US")
.attr("d", path)
.style("fill", "lightyellow")
.style("stroke", "orange")
Circles.enter()
.append("circle")
.attr("class", "circles")
.attr("r", function(d){
return circleScale(d.Millions)
})
.attr("cx", function(d){
var coords = projection([d.Longitude_imp, d.Latitude_imp])
return coords[0];
})
.attr("cy", function(d){
var coords = projection([d.Longitude_imp, d.Latitude_imp])
return coords[1];
})
.style("fill", "#cd0d0e")
svg.append("rect")
.attr("class", "overlay")
.attr("width", w)
.attr("height", h)
.call(drag)
})
})
})();
答案 0 :(得分:3)
有几种不同的方法可以实现这一点,但其中一种更简单的方法是计算投影质心(由旋转确定)与阻力事件中的圆心之间的角距:
map.selectAll("circle")
.style("display", function(d) {
var circle = [d.Longitude_imp, d.Latitude_imp];
var rotate = projection.rotate(); // antipode of actual rotational center.
var center = [-rotate[0], -rotate[1]]
var distance = d3.geoDistance(circle,center);
return (distance > Math.PI/2 ) ? 'none' : 'inline';
})
取每个点的中心并使用projection.rotate()获得旋转中心 - 请注意旋转值与居中点相反。旋转[10,-20]使地图居中于[-10,20],您可以将地图移动到您的下方。有了这两点,我们可以使用d3.geoDistance()来计算弧度中两点之间的距离,因此使用Math.PI / 2 - 它给出了90度以外的点,对于我们隐藏的这些点,其余的我们秀。
这可以在你的代码中加入更好的代码,但我将它分开来显示发生的事情更清楚。
这是一个示例block - 拖动触发,我没有将逻辑应用于初始加载。
如Gerardo Furtado所述,另一种方法是使用路径显示圆圈 - 使用path.pointRadius设置每个点的圆的大小。您可以使用以下格式追加路径,而不是附加一个圆圈:
Circles.enter()
.append("path")
.attr("class", "circles")
.attr("d",createGeojsonPoint)
在更新/拖动时:
map.selectAll('.circles').attr('d',createGeojsonPoint);
此方法使用正交的剪裁角度,以便在距离投影中心超过90度时(通过旋转确定)隐藏要素。您的createGeojsonPoint函数需要设置半径并返回一个有效的geojson对象:
var createGeojsonPoint = function(d) {
console.log(d);
path.pointRadius(circleScale(d.Millions)); // set point radius
return path({"type":"Point","coordinates":[d.Longitude_imp,d.Latitude_imp]}) // create geojson point, return path data
}
总之,经过必要的修改后,您的代码可能会显示like this。