D3 js正交标记旋转
D3 js orthographic markers rotation
目前我有一个用 D3 制作的半功能正交地球仪。这是一张带有标记的地图。所有 "land" 区域都显示良好,可以通过 draggin 旋转,但 svg 标记不能。这是我当前的测试代码:
var width = 960,
height = 500,
sens = 0.25;
var proj = d3.geo.orthographic()
.scale(220)
.translate([width / 2, height / 2])
.clipAngle(90);
var path = d3.geo.path().projection(proj).pointRadius(function(d) { return 6 });
var svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height);
var g = svg.append('g');
queue()
.defer(d3.json, 'data/world-110m.json')
.defer(d3.json, 'data/generated.json')
.await(ready);
function ready(error, world, locations) {
g.append('path')
.datum({type: 'Sphere'})
.attr('class', 'water')
.attr('d', path);
g.selectAll('g.land')
.data(topojson.feature(world, world.objects.countries).features)
.enter().append('path')
.attr('class', 'land')
.attr('d', path)
.call(d3.behavior.drag()
.origin(function() {
var r = proj.rotate();
return {x: r[0] / sens, y: -r[1] / sens}; })
.on('drag', function(d) {
var rotate = proj.rotate();
proj.rotate([d3.event.x * sens, -d3.event.y * sens, rotate[2]]);
g.selectAll('.land').attr('d', path);
}));
var nodes = g.selectAll('g.node')
.data(locations)
.enter().append('g').attr('class', 'node')
.attr('transform', function(d) {
var proj_pos = proj([d.lon, d.lat]);
return 'translate(' + proj_pos[0] + ',' + proj_pos[1] + ')';
})
.attr('style', 'cursor: pointer')
.attr("d", path);
nodes.append("svg:image")
.attr('transform', 'translate(-24, -20)')
.attr('width', 20)
.attr('height', 24)
.classed('white',true)
.attr("href","data/marker.svg");
console.log(g.selectAll('g.node'));
}
在尝试使其以某种方式工作后,我只能在地球上剪辑 "points",但不能剪辑 SVG。似乎 svg 必须进入 'g' 标签,结果我的 'nodes' 在 'd' 标签中没有路径。
我需要:整个地图必须通过拖动操作旋转,SVG 裁剪到位置,在 'generated.json'
中指定
[
{
"lat": 62.782176,
"lon": 54.3214
},
{
"lat": -61.007975,
"lon": -5.05281
},
{
"lat": -78.166262,
"lon": 45.320536
}
]
有点郁闷,如果有人能帮助我,我将不胜感激。
更新节点的位置非常简单。不过,这里的技巧是确定标记何时旋转 "off" 地球(围绕地图背面)。我能想到的唯一方法是生成一个点路径以查看它是否未定义:
.on('drag', function(d) {
//update land like you've been doing
var rotate = proj.rotate();
proj.rotate([d3.event.x * sens, -d3.event.y * sens, rotate[2]]);
g.selectAll('.land').attr('d', path);
// for each node
nodes.each(function(d, i) {
var self = d3.select(this),
lon_lat = [d.lon, d.lat];
proj_pos = proj(lon_lat);
// check to see if it's still visible
var hasPath = path({
type: "Point",
coordinates: lon_lat
}) != undefined;
// if it is show it and update position
if (hasPath) {
self.style("display","inline");
self.attr("transform", 'translate(' + proj_pos[0] + ',' + proj_pos[1] + ')');
}
// otherwise hide it
else {
self.style("display","none")
}
});
}));
完整 running code.
目前我有一个用 D3 制作的半功能正交地球仪。这是一张带有标记的地图。所有 "land" 区域都显示良好,可以通过 draggin 旋转,但 svg 标记不能。这是我当前的测试代码:
var width = 960,
height = 500,
sens = 0.25;
var proj = d3.geo.orthographic()
.scale(220)
.translate([width / 2, height / 2])
.clipAngle(90);
var path = d3.geo.path().projection(proj).pointRadius(function(d) { return 6 });
var svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height);
var g = svg.append('g');
queue()
.defer(d3.json, 'data/world-110m.json')
.defer(d3.json, 'data/generated.json')
.await(ready);
function ready(error, world, locations) {
g.append('path')
.datum({type: 'Sphere'})
.attr('class', 'water')
.attr('d', path);
g.selectAll('g.land')
.data(topojson.feature(world, world.objects.countries).features)
.enter().append('path')
.attr('class', 'land')
.attr('d', path)
.call(d3.behavior.drag()
.origin(function() {
var r = proj.rotate();
return {x: r[0] / sens, y: -r[1] / sens}; })
.on('drag', function(d) {
var rotate = proj.rotate();
proj.rotate([d3.event.x * sens, -d3.event.y * sens, rotate[2]]);
g.selectAll('.land').attr('d', path);
}));
var nodes = g.selectAll('g.node')
.data(locations)
.enter().append('g').attr('class', 'node')
.attr('transform', function(d) {
var proj_pos = proj([d.lon, d.lat]);
return 'translate(' + proj_pos[0] + ',' + proj_pos[1] + ')';
})
.attr('style', 'cursor: pointer')
.attr("d", path);
nodes.append("svg:image")
.attr('transform', 'translate(-24, -20)')
.attr('width', 20)
.attr('height', 24)
.classed('white',true)
.attr("href","data/marker.svg");
console.log(g.selectAll('g.node'));
}
在尝试使其以某种方式工作后,我只能在地球上剪辑 "points",但不能剪辑 SVG。似乎 svg 必须进入 'g' 标签,结果我的 'nodes' 在 'd' 标签中没有路径。
我需要:整个地图必须通过拖动操作旋转,SVG 裁剪到位置,在 'generated.json'
中指定[
{
"lat": 62.782176,
"lon": 54.3214
},
{
"lat": -61.007975,
"lon": -5.05281
},
{
"lat": -78.166262,
"lon": 45.320536
}
]
有点郁闷,如果有人能帮助我,我将不胜感激。
更新节点的位置非常简单。不过,这里的技巧是确定标记何时旋转 "off" 地球(围绕地图背面)。我能想到的唯一方法是生成一个点路径以查看它是否未定义:
.on('drag', function(d) {
//update land like you've been doing
var rotate = proj.rotate();
proj.rotate([d3.event.x * sens, -d3.event.y * sens, rotate[2]]);
g.selectAll('.land').attr('d', path);
// for each node
nodes.each(function(d, i) {
var self = d3.select(this),
lon_lat = [d.lon, d.lat];
proj_pos = proj(lon_lat);
// check to see if it's still visible
var hasPath = path({
type: "Point",
coordinates: lon_lat
}) != undefined;
// if it is show it and update position
if (hasPath) {
self.style("display","inline");
self.attr("transform", 'translate(' + proj_pos[0] + ',' + proj_pos[1] + ')');
}
// otherwise hide it
else {
self.style("display","none")
}
});
}));
完整 running code.