如何在 D3 TOPOJSON 地图加载后 运行 发挥作用
How to run function after D3 TOPOJSON map loads
我正在尝试 运行 一个基于数据对 TOPOJSON D3 地图的各个状态进行着色的函数。
但是,该函数在 SVG 中的状态 load/appear 之前保持 运行ning。构建地图的函数在文档就绪函数中调用。我已经尝试向状态添加一个事件侦听器,一个 .on 属性调用应该遮蔽状态并使用 window.load 的函数。但是遮蔽状态的函数在状态出现在屏幕上之前保持 运行ning,因此当试图通过它们的 id
找到每个状态时 returns 一个 NULL 值
.background {
fill: none;
pointer-events: all;
}
#states {
fill: #aaa;
}
#states .active {
fill: orange;
}
#state-borders {
fill: none;
stroke: #fff;
stroke-width: 1.5px;
stroke-linejoin: round;
stroke-linecap: round;
pointer-events: none;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script>
function buildmap(){
var width = 960,
height = 500,
centered;
var projection = d3.geo.albersUsa()
.scale(1070)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.on("click", clicked);
var g = svg.append("g");
d3.json("/mbostock/raw/4090846/us.json", function(error, us) {
if (error) throw error;
g.append("g")
.attr("id", "states")
.selectAll("path")
.data(topojson.feature(us, us.objects.states).features)
.enter().append("path")
.attr("d", path);
g.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("id", "state-borders")
.attr("d", path);
});
};
function colorstates(){
var mainstate = document.getElementById("texas")
mainstate.style.fill="blue"
}
$(document).ready(function((){
buildmap()
colorstates() //I have also used window.load and adding .on attribute to svg/d3
d3.json
是异步的。意思是它后面的所有代码都会运行立即,也就是代码不会等待[=12] =] 完成。
使用$(document).ready()
或window.load
不会有任何区别。只有在 d3.json
获取文件(顺便说一句,一个大文件)并绘制 SVG 之后,路径才会出现在 DOM 中。因此,您必须等待 d3.json
完成,这样您才能 select 这些路径。
解决方法:在d3.json
的底部调用你的函数:
d3.json("/mbostock/raw/4090846/us.json", function(error, us) {
if (error) throw error;
g.append("g")
.attr("id", "states")
.selectAll("path")
.data(topojson.feature(us, us.objects.states).features)
.enter().append("path")
.attr("d", path);
g.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) {
return a !== b;
}))
.attr("id", "state-borders")
.attr("d", path);
//calling colorstates inside d3.json
colorstates()
function colorstates() {
var mainstate = document.getElementById("texas")
mainstate.style.fill = "blue"
}
});
这样,当您调用 colorstates
函数时,元素就会在那里。
编辑:要通过 ID select 状态(即路径),您必须首先设置路径的 ID(现在,他们没有身份证):
g.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) {
return a !== b;
}))
.attr("id", d => "state" + d.id)
.attr("d", path);
在topoJSON
中,d.id
是数字,ID不能以数字开头(所以我用了"state" + d.id
)。德州的 id 是 48.
这是您的代码,正在运行:https://bl.ocks.org/anonymous/b2114787193d018fc094763a92872333
PS:您不需要在 D3 代码中使用 document.getElementById
。您会发现使用 D3 selectors 更容易且用途更广。
PS2:你的州边界应该 "state-borders" 作为 class
,而不是 id
:你 不能 对不同的元素具有相同的 ID。 ID 是唯一的。
我正在尝试 运行 一个基于数据对 TOPOJSON D3 地图的各个状态进行着色的函数。
但是,该函数在 SVG 中的状态 load/appear 之前保持 运行ning。构建地图的函数在文档就绪函数中调用。我已经尝试向状态添加一个事件侦听器,一个 .on 属性调用应该遮蔽状态并使用 window.load 的函数。但是遮蔽状态的函数在状态出现在屏幕上之前保持 运行ning,因此当试图通过它们的 id
找到每个状态时 returns 一个 NULL 值.background {
fill: none;
pointer-events: all;
}
#states {
fill: #aaa;
}
#states .active {
fill: orange;
}
#state-borders {
fill: none;
stroke: #fff;
stroke-width: 1.5px;
stroke-linejoin: round;
stroke-linecap: round;
pointer-events: none;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script>
function buildmap(){
var width = 960,
height = 500,
centered;
var projection = d3.geo.albersUsa()
.scale(1070)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.on("click", clicked);
var g = svg.append("g");
d3.json("/mbostock/raw/4090846/us.json", function(error, us) {
if (error) throw error;
g.append("g")
.attr("id", "states")
.selectAll("path")
.data(topojson.feature(us, us.objects.states).features)
.enter().append("path")
.attr("d", path);
g.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("id", "state-borders")
.attr("d", path);
});
};
function colorstates(){
var mainstate = document.getElementById("texas")
mainstate.style.fill="blue"
}
$(document).ready(function((){
buildmap()
colorstates() //I have also used window.load and adding .on attribute to svg/d3
d3.json
是异步的。意思是它后面的所有代码都会运行立即,也就是代码不会等待[=12] =] 完成。
使用$(document).ready()
或window.load
不会有任何区别。只有在 d3.json
获取文件(顺便说一句,一个大文件)并绘制 SVG 之后,路径才会出现在 DOM 中。因此,您必须等待 d3.json
完成,这样您才能 select 这些路径。
解决方法:在d3.json
的底部调用你的函数:
d3.json("/mbostock/raw/4090846/us.json", function(error, us) {
if (error) throw error;
g.append("g")
.attr("id", "states")
.selectAll("path")
.data(topojson.feature(us, us.objects.states).features)
.enter().append("path")
.attr("d", path);
g.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) {
return a !== b;
}))
.attr("id", "state-borders")
.attr("d", path);
//calling colorstates inside d3.json
colorstates()
function colorstates() {
var mainstate = document.getElementById("texas")
mainstate.style.fill = "blue"
}
});
这样,当您调用 colorstates
函数时,元素就会在那里。
编辑:要通过 ID select 状态(即路径),您必须首先设置路径的 ID(现在,他们没有身份证):
g.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) {
return a !== b;
}))
.attr("id", d => "state" + d.id)
.attr("d", path);
在topoJSON
中,d.id
是数字,ID不能以数字开头(所以我用了"state" + d.id
)。德州的 id 是 48.
这是您的代码,正在运行:https://bl.ocks.org/anonymous/b2114787193d018fc094763a92872333
PS:您不需要在 D3 代码中使用 document.getElementById
。您会发现使用 D3 selectors 更容易且用途更广。
PS2:你的州边界应该 "state-borders" 作为 class
,而不是 id
:你 不能 对不同的元素具有相同的 ID。 ID 是唯一的。