【发布时间】:2016-06-11 02:35:43
【问题描述】:
我需要一些帮助,从我创建的数组中获取数据,然后仅对数组中存在的国家/地区进行着色,将数组中不存在的其他国家/地区保留为默认颜色。我正在使用 D3 来完成所有这些工作,并且我很确定我可以通过 D3 实现我所需要的,但不确定如何实现。
我想做的是通过 data2 数组获取国家代码,并根据它们的排名将它们着色为深红色到绿色。
我的数组:
var data2 = [{name:"United Kingdom", country_code: 826, rank: 1},{name:"United States", country_code: 840, rank: 2},{name:"Sweden", country_code: 752, rank: 3},
{name:"Canada", country_code: 124, rank: 4},{name:"Germany", country_code: 276, rank: 5},{name:"South Korea", country_code: 410, rank: 6},
{name:"Australia", country_code: 036, rank: 7},{name:"Italy", country_code: 380, rank: 8},
{name:"Ireland", country_code: 372, rank: 9},{name:"Jamaica", country_code: 388, rank: 10},
{name:"India", country_code: 356, rank: 11},{name:"Mexico", country_code: 484, rank: 12},{name:"France", country_code: 250, rank: 13},
{name:" Japan", country_code: 392, rank: 14},{name:"Finland", country_code: 246, rank: 15},
{name:"Spain", country_code: 724, rank: 16},{name:"Russia", country_code: 643, rank: 17},
{name:"Philippines", country_code: 608, rank: 18},{name:"Romania", country_code: 642, rank: 19},
{name:"Ukraine", country_code: 804, rank: 20}]
目前,我只是为我的地图着色
var country = g.selectAll(".country").data(topo);
country.enter().insert("path")
.attr("class", "country")
.attr("d", path)
.attr("id", function(d,i) { return d.id; })
.attr("title", function(d,i) { return d.properties.name; })
.style("fill", function(d, i) {return d.properties.color; });
看到问题是,我正在使用一组数据来创建地图,并且想使用另一组数据 data2 来为特定国家/地区着色。
我尝试了以下方法,但没有成功。
var color = d3.scale.category10();
feature.data(data2.features)
.enter().append("path")
.attr("class", "feature")
.attr("d", path)
.style("fill", function (d,i) { return color(i) });
提前感谢任何提供帮助的人。
如有必要,我可以发布所有代码,但除非需要,否则我不想填满页面,
完整代码:
<!DOCTYPE html>
<meta charset="utf-8">
<title>D3 World Map Template | TechSlides</title>
<style>
.country:hover{
stroke: #fff;
stroke-width: 1.5px;
}
.text{
font-size:10px;
text-transform:capitalize;
}
#container {
margin:10px 10%;
border:2px solid #000;
border-radius: 5px;
height:100%;
overflow:hidden;
background: #F0F8FF;
}
.hidden {
display: none;
}
div.tooltip {
color: #222;
background: #fff;
padding: .5em;
text-shadow: #f5f5f5 0 1px 0;
border-radius: 2px;
box-shadow: 0px 0px 2px 0px #a6a6a6;
opacity: 0.9;
position: absolute;
}
.graticule {
fill: none;
stroke: #bbb;
stroke-width: .5px;
stroke-opacity: .5;
}
.equator {
stroke: #ccc;
stroke-width: 1px;
}
</style>
</head>
<body>
<h1>World Map Template with D3.js</h1>
<p>Responsive D3 World Map with zoom and pan limits, graticule and equator lines, optimized TopoJSON with country names and colors, geo translation functions, geo coordinate plotting functions for points and text, and much more. For a full list of features, please go <a href="http://techslides.com/d3-map-starter-kit/">back to article</a>.</p>
<div id="container"></div>
<script src="js/d3.min.js"></script>
<script src="js/topojson.v1.min.js"></script>
<script>
d3.select(window).on("resize", throttle);
var zoom = d3.behavior.zoom()
.scaleExtent([1, 9])
.on("zoom", move);
var width = document.getElementById('container').offsetWidth;
var height = width / 2;
var topo,projection,path,svg,g;
var graticule = d3.geo.graticule();
var tooltip = d3.select("#container").append("div").attr("class", "tooltip hidden");
setup(width,height);
function setup(width,height){
projection = d3.geo.mercator()
.translate([(width/2), (height/2)])
.scale( width / 2 / Math.PI);
path = d3.geo.path().projection(projection);
svg = d3.select("#container").append("svg")
.attr("width", width)
.attr("height", height)
.call(zoom)
.on("click", click)
.append("g");
g = svg.append("g");
}
d3.json("data/world-topo-min.json", function(error, world) {
var countries = topojson.feature(world, world.objects.countries).features;
topo = countries;
draw(topo);
});
function draw(topo) {
svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
g.append("path")
.datum({type: "LineString", coordinates: [[-180, 0], [-90, 0], [0, 0], [90, 0], [180, 0]]})
.attr("class", "equator")
.attr("d", path);
var country = g.selectAll(".country").data(topo);
country.enter().insert("path")
.attr("class", "country")
.attr("d", path)
.attr("id", function(d,i) { return d.id; })
.attr("title", function(d,i) { return d.properties.name; });
//offsets for tooltips
var offsetL = document.getElementById('container').offsetLeft+20;
var offsetT = document.getElementById('container').offsetTop+10;
//tooltips
country
.on("mousemove", function(d,i) {
var mouse = d3.mouse(svg.node()).map( function(d) { return parseInt(d); } );
tooltip.classed("hidden", false)
.attr("style", "left:"+(mouse[0]+offsetL)+"px;top:"+(mouse[1]+offsetT)+"px")
.html(d.properties.name);
})
.on("mouseout", function(d,i) {
tooltip.classed("hidden", true);
});
//EXAMPLE: adding some capitals from external CSV file
d3.csv("data/country-capitals.csv", function(err, capitals) {
capitals.forEach(function(i){
addpoint(i.CapitalLongitude, i.CapitalLatitude, i.CapitalName );
});
});
}
function redraw() {
width = document.getElementById('container').offsetWidth;
height = width / 2;
d3.select('svg').remove();
setup(width,height);
draw(topo);
}
function move() {
var t = d3.event.translate;
var s = d3.event.scale;
zscale = s;
var h = height/4;
t[0] = Math.min(
(width/height) * (s - 1),
Math.max( width * (1 - s), t[0] )
);
t[1] = Math.min(
h * (s - 1) + h * s,
Math.max(height * (1 - s) - h * s, t[1])
);
zoom.translate(t);
g.attr("transform", "translate(" + t + ")scale(" + s + ")");
//adjust the country hover stroke width based on zoom level
d3.selectAll(".country").style("stroke-width", 1.5 / s);
}
var throttleTimer;
function throttle() {
window.clearTimeout(throttleTimer);
throttleTimer = window.setTimeout(function() {
redraw();
}, 200);
}
//geo translation on mouse click in map
function click() {
var latlon = projection.invert(d3.mouse(this));
console.log(latlon);
}
//function to add points and text to the map (used in plotting capitals)
function addpoint(lat,lon,text) {
var gpoint = g.append("g").attr("class", "gpoint");
var x = projection([lat,lon])[0];
var y = projection([lat,lon])[1];
gpoint.append("svg:circle")
.attr("cx", x)
.attr("cy", y)
.attr("class","point")
.attr("r", 1.5);
//conditional in case a point has no associated text
if(text.length>0){
gpoint.append("text")
.attr("x", x+2)
.attr("y", y+2)
.attr("class","text")
.text(text);
}
}
var data2 = [{name:"United Kingdom", country_code: 826, rank: 1},{name:"United States", country_code: 840, rank: 2},{name:"Sweden", country_code: 752, rank: 3},
{name:"Canada", country_code: 124, rank: 4},{name:"Germany", country_code: 276, rank: 5},{name:"South Korea", country_code: 410, rank: 6},
{name:"Australia", country_code: 036, rank: 7},{name:"Italy", country_code: 380, rank: 8},
{name:"Ireland", country_code: 372, rank: 9},{name:"Jamaica", country_code: 388, rank: 10},
{name:"India", country_code: 356, rank: 11},{name:"Mexico", country_code: 484, rank: 12},{name:"France", country_code: 250, rank: 13},
{name:" Japan", country_code: 392, rank: 14},{name:"Finland", country_code: 246, rank: 15},
{name:"Spain", country_code: 724, rank: 16},{name:"Russia", country_code: 643, rank: 17},
{name:"Philippines", country_code: 608, rank: 18},{name:"Romania", country_code: 642, rank: 19},
{name:"Ukraine", country_code: 804, rank: 20}];
d3.json("world-map.json", function(json) {
//Merge the rank in data2 and GeoJSON in a single array
//Loop through once for each "rank" data value
for (var i = 0; i < data2.length; i++) {
//Grab country name
var data2CountryCode = data2[i].country_code;
console.log(data2CountryCode);
//Grab data value, and convert from string to float
var datarank = +data2[i].rank;
console.log(datarank);
//Find the corresponding country inside the GeoJSON
for (var j = 0; j < json.features.length; j++) {
//We'll check the official ISO country code
var jsonCountryCode = json.features[j].properties.un_a3;
console.log(jsonCountryCode);
if (data2CountryCode == jsonCountryCode) {
//Copy the data2 rank value into the GeoJSON, with the name "color"
json.features[j].properties.labelrank = datarank;
//Stop looking through the JSON
break;
}
}
}
var color = d3.scale.quantize()
.range(["Lime","GreenYellow","LawnGreen","LightGreen","LimeGreen","Green","DarkGreen","Yellow","Gold",
"GoldenRod","DarkGoldenRod","Orange"
,"DarkOrange","Coral","Red","OrangeRed","Tomato","Crimson","DarkRed","Brown"])
.domain([(d3.min(data2, function(d) { return d.rank; })),(d3.max(data2, function(d) { return d.rank; }))
]);
var country = g.selectAll(".country")
.data(json.features) //in my example, json.features
.enter()
.append("path")
.attr("d", path)
.style("fill", function(d) {
//Get data value
var value = d.properties.labelrank;
if (value) {
//If value exists…
return color(value);
} else {
//If value is undefined…
return "#ccc";
}
});
});
</script>
</body>
</html>
【问题讨论】:
标签: javascript d3.js colors