我制作了一张d3.js
的地图,现在我想一个接一个地为几个国家着色:
到目前为止,我可以立刻改变所有国家的颜色。我尝试按照.transition().delay(500)
尝试做我想做的事,但它没有用。
到目前为止,这是我的代码:
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>
<script>
var w = 1000;
var h = 550;
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h);
var path = d3.geoPath()
.projection(d3.geoMercator()
//.scale(0)
//.translate([200, 2100])
);
var countries_visited= ['Spain','France','Germany','Poland', 'Finland']
d3.json(
"https://raw.githubusercontent.com/johan/world.geo.json/master/countries.geo.json",
function (error, json) {
//draw svg lines of the boundries
svg.append("g")
.attr("class", "black")
.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path)
.attr('fill', '#e7d8ad');;
d3.timeout(function() {
d3.selectAll('path')
//.transition().delay(500) //should color countries, one after the other
.attr('fill', colorCountry);
}, 500);
}
);
function colorCountry(country){
if (countries_visited.includes(country.properties.name)) {
return '#c8b98d';
} else { // why do I need a else (otherwise set to black
return '#e7d8ad';
};
};
</script>
</body>
&#13;
作为一个附带问题:为什么我需要colorCountry
中的else语句?如果我不添加fill
?
else
会发生变化的原因
答案 0 :(得分:3)
以下是您的代码的略微修改版本,它一个接一个地显示访问过的国家/地区:
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>
<script>
var w = 1000;
var h = 550;
var svg = d3.select("body").append("svg").attr("width", w).attr("height", h);
var path = d3.geoPath().projection(d3.geoMercator());
var countries_visited = ['Spain','France','Germany','Poland', 'Finland'];
d3.json(
"https://raw.githubusercontent.com/johan/world.geo.json/master/countries.geo.json",
function (error, json) {
svg.append("g")
.attr("class", "black")
.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("id", function(d) { return d.properties.name; })
.attr("d", path)
.attr('fill', '#e7d8ad');
var delay = 1000;
countries_visited.forEach( country => {
d3.selectAll('#' + country)
.transition().delay(delay)
.attr('fill', '#c8b98d');
delay += 500;
});
}
);
</script>
</body>
它包括创建几个独立的过渡。每个访问过的国家一个:
var delay = 1000;
countries_visited.forEach( country => {
d3.selectAll('#' + country)
.transition().delay(delay)
.attr('fill', '#c8b98d');
delay += 500;
});
每次过渡都有延迟,这会延迟国家的颜色。而且这是过渡本身的创造,增加了申请下一个国家的延迟。
我为每个路径(国家/地区)添加了id
,以便在转换过程中轻松选择它并应用新颜色。这是一种回答方问题的方法,只需选择要修改的元素,我们就可以修改已修改国家/地区的fill
属性。
答案 1 :(得分:3)
不要从Xavier的answer中删除,你也可以通过设置函数的延迟(而不是增量)来避免使用更多d3惯用法的循环:
d3.selectAll("path")
.filter(function(d) { return countries_visited.indexOf(d.properties.name) > -1 })
.transition()
.delay(function(d) { return countries_visited.indexOf(d.properties.name) * 500 + 1000; })
.attr("fill","#c8b98d");
这看起来像:
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>
<script>
var w = 1000;
var h = 550;
var svg = d3.select("body").append("svg").attr("width", w).attr("height", h);
var path = d3.geoPath().projection(d3.geoMercator());
var countries_visited = ['Spain','France','Germany','Poland', 'Finland'];
d3.json(
"https://raw.githubusercontent.com/johan/world.geo.json/master/countries.geo.json",
function (error, json) {
svg.append("g")
.attr("class", "black")
.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("id", function(d) { return d.properties.name; })
.attr("d", path)
.attr('fill', '#e7d8ad');
d3.selectAll("path")
.filter(function(d) { return countries_visited.indexOf(d.properties.name) > -1 })
.transition()
.delay(function(d) { return countries_visited.indexOf(d.properties.name) * 500 + 1000; })
.attr("fill","#c8b98d");
});
</script>
</body>
&#13;