我正在尝试创建一个显示所有国家/地区名称的d3地图。
这个地球仪: globe map
当我尝试展示这些国家时,地球会变成这个烂摊子: mess globe
var app = angular.module("myapp", []);
app.directive("globe", function() {
return {
restrict : 'E',
scope : {
data: '=?'
},
template:
'<div class="globe-wrapper">' +
'<div class="globe"></div>' +
'<div class="info"></div>' +
'</div>',
link: link
};
function link(scope, element, attrs) {
var width = 500, height = width,
projection, path,
svg, features, graticule,
mapJson = 'https://gist.githubusercontent.com/GordyD/49654901b07cb764c34f/raw/27eff6687f677c984a11f25977adaa4b9332a2a9/countries-and-states.json',
states, stateSet, countries, countrySet, zoom;
projection = d3.geo.orthographic()
.translate([width / 2, height / 2])
.scale(250)
.clipAngle(90)
.precision(0.1)
.rotate([0, -30]);
path = d3.geo.path()
.projection(projection);
svg = d3.select(element[0]).select('.globe')
.append('svg')
.attr('width', width)
.attr('height', height)
.attr('viewBox', '0, 0, ' + width + ', ' + height);
features = svg.append('g');
features.append('path')
.datum({type: 'Sphere'})
.attr('class', 'background')
.attr('d', path);
graticule = d3.geo.graticule();
features.append('path')
.datum(graticule)
.attr('class', 'graticule')
.attr('d', path);
zoom = d3.geo.zoom()
.projection(projection)
.scaleExtent([projection.scale() * 0.7, projection.scale() * 8])
.on('zoom.redraw', function(){
d3.event.sourceEvent.preventDefault();
svg.selectAll('path').attr('d',path);
});
d3.json(mapJson, function(error, world) {
states = topojson.feature(world, world.objects.states).features;
countries = topojson.feature(world, world.objects.countries).features;
stateSet = drawFeatureSet('state', states);
countrySet = drawFeatureSet('country', countries);
d3.selectAll('path').call(zoom);
});
function drawFeatureSet(className, featureSet) {
var set = features.selectAll('.' + className)
.data(featureSet)
.enter()
.append('g')
.attr('class', className)
.attr('data-name', function(d) {
return d.properties.name;
})
.attr('data-id', function(d) {
return d.id;
});
set.append("text")
.attr("class", "country-label")
.attr("transform", function(d) { console.log("d", d); return "translate(" + path.centroid(d) + ")"; })
.text(function(d) { return d.properties.name; })
.attr("x", function(d){
return path.centroid(d)[0];
})
.attr("y", function(d){
return path.centroid(d)[1];
});
set.append('path')
.attr('class', 'land')
.attr('d', path);
set.append('path')
.attr('class', 'overlay')
.attr('d', path)
.attr('style', function(d) {
if (scope.data[d.id]) {
return 'fill-opacity: ' + (scope.data[d.id]/100);
}
})
.on('click', function(d) {
var val = (scope.data[d.id]) ? scope.data[d.id] : 0;
d3.select(element[0]).select('.info').html(d.properties.name + ': ' + val);
rotateToFocusOn(d);
});
return set;
}
function rotateToFocusOn(x) {
var coords = d3.geo.centroid(x);
coords[0] = -coords[0];
coords[1] = -coords[1];
d3.transition()
.duration(1250)
.tween('rotate', function() {
var r = d3.interpolate(projection.rotate(), coords);
return function(t) {
projection.rotate(r(t));
svg.selectAll('path').attr('d', path);
};
})
.transition();
}
}
});
app.controller("ctrl1",function($scope, $log) {
$scope.data = {};
});
app.run();
svg {
width: 100%
}
path {
fill: none;
stroke: black
}
.background {
fill: rgba(200,212,220,.5);
stroke-width: .8px;
stroke: black;
}
.graticule {
stroke: rgba(0,0,0, .2);
stroke-width: .5px;
}
.country {
cursor: pointer;
}
.country .land, .state .land {
fill: white;
stroke: rgba(0,0,0, .2);
stroke-width .3px;
}
.state .overlay {
fill: blue;
fill-opacity: 0;
}
.country .overlay {
fill: orange;
fill-opacity: 0;
}
.country-label {
fill: #777;
fill-opacity: .5;
font-size: 20px;
font-weight: 300;
text-anchor: middle;
}
<script src="https://www.workshape.io/js/geo/d3.geo.zoom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div ng-app="myapp">
<div ng-controller="ctrl1">
<globe data="data"></globe>
</div>
</div>
任何人都知道如何显示这些国家/地区的国家名称? 除了不在一起之外,在旋转地球时,名称会改变地点。
答案 0 :(得分:0)
试试这种方式
set.append("text")
.attr("class", "country-label")
.attr("transform", function(d) { console.log("d", d); return "translate(" + path.centroid(d) + ")"; })
.text(function(d) { return d.properties.name; })
.attr("dx", function (d) {
return "0.3em";
})
.attr("dy", function (d) {
return "0.35em";
})
.style('fill', 'black');