所以,我有旋转的Globe,有些国家强调,如果你鼠标悬停它们。 但问题是,远方国家不应该改变颜色,土地应该改变边界。 我想,原因是clipAngle,并尝试将其更改为不同的地图"那样:
projection.clipAngle(180);
// Draw the world
var world =
svg.selectAll('.lands').data([land]).enter().append('path').attr("class", "lands").attr('d', path);
// Draw the cities
var cities = svg.selectAll('.cities').data([points]).enter().append('path').attr("class","cities").attr('d', path);
projection.clipAngle(90);
//Draw the countries
d3.json("https://rawgit.com/Bramsiss/Globe/master/world-counries1.json", function(collection) {
var countries = svg.selectAll(".country").data(collection.features).enter().append("path").attr("d", path).attr("class", "country");
但它没有用。 接下来我想做两个投影whit clipAngle(对于相同地图的不同颜色),但这是个坏主意。
也许这太简单了,但我试着解决这个问题已经三天了,还没有得到答案......
此外,请在codepen(https://codepen.io/bramsis/pen/ZvzGdo)
中使用此功能答案 0 :(得分:1)
如果国家/地区“落后于”全球,您只需修改适用于您所在国家/地区的mouseover
功能。
countries
.on("mouseover", function(d) {
// we need a coordinate to work with
// this is just a quick and dirty method - see
// the answer for why this part is ambiguous...
var data =
d.geometry.coordinates[0][0].length == 2
? d.geometry.coordinates[0][0]
: d.geometry.coordinates[0][0][0];
// next using the coordinate we work out the angular distance
var ad = d3.geoDistance(data, [
-projection.rotate()[0],
projection.rotate()[1]
]);
// if the angle is less than Pi/2
// then the coordinate is in front of the horizon and the country
// is highlighted
if (ad < Math.PI/2) {
this.style.stroke = "rgba(193, 0, 32, 0.5)";
}
})
显然这有点粗糙并准备就绪,因为它只选择代表国家的第一个坐标......你需要考虑你所说的“远方” - 即整个国家,它的任何部分, 50%等等?一旦你定义了“远端”的意思,那么你可以使用这个方法迭代代表你感兴趣的部分的坐标集,看看它们是否在地平线前面。
查看working fork of your example
要了解我的意思,只使用一个坐标,鼠标悬停在南极上进行清晰演示 - 50%的时间会突出显示 - 尽管它的某些部分始终在视图中,计算所依据的确切坐标只有50%的时间才能看到。
编辑:
来自评论......
谢谢,它确实有效,但如果地球仪不仅可以旋转,那该怎么办? X坐标,但也是Y.
要围绕y轴和x轴旋转,只需要修改距离的计算。即。
// notice the negative phi value
// for reference the values are; lambda, phi, gamma
var ad = d3.geoDistance(data, [
-projection.rotate()[0],
-projection.rotate()[1],
0
]);
显然要看到这个工作,你需要实际沿Y轴旋转地球。 e.g。
// rotate the globe over the x and y axes
// i just use slightly different values here to "tumble" the globe
projection.rotate([rotate[0] + velocity[0] * dt, velocity[0] * dt]);
查看另一个working fork with rotation in multiple directions
也可以在projection rotate上阅读,因为它确实是你在这里想要实现的目标的关键。
答案 1 :(得分:1)
一种可能的解决方案是使用main :null
run :what?
将您的contries原始路径与另一层相同路径叠加。只有这些路径才会为附加到它们的.clipAngle(90)
和mouseover
事件获取事件处理程序。这样,只有面向前方的国家才会对这些鼠标事件作出反应。
以下代码段演示了一种可行的解决方案。它没有多大的魔力,因为你只需复制现有的逻辑来添加国家。为清晰起见,我使用mouseout
为部分添加了前缀。
frontXxx
请注意,根据comment对弗雷泽的答案提出的要求,如何轻松地绕多个轴旋转。
var frontProjection = d3.geoOrthographic()
.scale(radius)
.translate(translation)
.clipAngle(90);
var frontPath = d3.geoPath()
.projection(frontProjection)
.pointRadius(1);
// ...
// Inside the load() function.
var frontCountries = svg.selectAll(".frontCountry")
.data(collection.features)
.enter().append("path")
.attr("d", frontPath)
.attr("class", "frontCountry")
.on("mouseover", function() {
this.style.stroke = 'rgba(193, 0, 32, 0.5)';
})
.on("mouseout", function() {
this.style.stroke = 'rgba(0, 0, 0, 0)';
});
// ...
// Rotation
var frontFeature = svg.selectAll(".frontCountry");
timer = d3.timer(function() {
var dt = Date.now() - time;
// ...
frontProjection.rotate([rotate[0] + velocity[0] * dt, rotate[1] + velocity[1] * dt]);
frontFeature.attr("d", frontPath);
});
/* Set up */
/* ====== */
var timer;
var width = 1000,
height = 700,
radius = 325,
originalScale = height / 2,
scale = originalScale,
translation = [width / 2, height / 2],
scaleChange, rotation,
rotate = [100, -1],
velocity = [.009,.005],
time = Date.now();
var graticule = d3.geoGraticule();
// set up the main canvas and the projection
var svg = d3.select('#map').append('svg').attr("id", "world").attr('width',width).attr('height',height).append('g');
var projection = d3.geoOrthographic().scale(radius).translate(translation).clipAngle(180);
var frontProjection = d3.geoOrthographic().scale(radius).translate(translation).clipAngle(90);
var path = d3.geoPath().projection(projection).pointRadius(1);
var frontPath = d3.geoPath().projection(frontProjection).pointRadius(1);
svg.append("circle").attr("cx", width/2).attr("cy", height/2).attr("r", radius).classed('cir', true);
/* Data load */
/* ========= */
d3.queue()
.defer(d3.csv, 'https://rawgit.com/Bramsiss/Globe/master/c.csv')
.defer(d3.json, 'https://rawgit.com/jonataswalker/map-utils/master/data/json/world-110m.json')
.await(load);
function load(error, cities, world ) {
if (error) { console.log(error); }
var land = topojson.feature(world, world.objects.land),
grid = graticule();
var outerArray = [];
cities.forEach(function(el) {
var innerArray = [+el.Longitude, +el.Latitude];
outerArray.push(innerArray);
});
var points = {
type: "MultiPoint",
coordinates: outerArray
};
// Draw the world
var world = svg.selectAll('.lands').data([land]).enter().append('path').attr("class", "lands").attr('d', path);
// Draw the cities
var cities = svg.selectAll('.cities').data([points]).enter().append('path').attr("class","cities").attr('d', path);
//Countries
d3.json("https://rawgit.com/Bramsiss/Globe/master/world-counries1.json", function(collection) {
var countries = svg.selectAll(".country").data(collection.features).enter().append("path").attr("d", path).attr("class", "country");
var frontCountries = svg.selectAll(".frontCountry")
.data(collection.features)
.enter().append("path")
.attr("d", frontPath)
.attr("class", "frontCountry")
.on("mouseover", function() {
this.style.stroke = 'rgba(193, 0, 32, 0.5)';
})
.on("mouseout", function() {
this.style.stroke = 'rgba(0, 0, 0, 0)';
});
//Rotation
var feature = svg.selectAll(".cities, .country, .lands");
var frontFeature = svg.selectAll(".frontCountry");
timer = d3.timer(function() {
var dt = Date.now() - time;
projection.rotate([rotate[0] + velocity[0] * dt, rotate[1] + velocity[1] * dt]);
feature.attr("d", path);
frontProjection.rotate([rotate[0] + velocity[0] * dt, rotate[1] + velocity[1] * dt]);
frontFeature.attr("d", frontPath);
function rot(dt) {
return
}
});
});
}
.country {
fill: transparent;
stroke: rgba(0, 0, 0, 0);
stroke-width: 2px;
}
.frontCountry {
fill: darkolivegreen;
fill-opacity: 0.6;
stroke: rgba(0, 0, 0, 0);
stroke-width: 2px;
}
.lands {
fill: transparent;
stroke: rgba(0, 0, 0, 1);
stroke-width: 1px;
}
.cities {
stroke: #2F4F4F;
stroke-width: 12px;
fill: black;
opacity: 0.8;
}
.cir {
fill:none;
stroke:black;
}
我还forked你想要加入这些变化。