2017-01-30 12 views
1

データに基づいてTOPOJSON D3マップの個々の状態をシェーディングする関数を実行しようとしています。D3 TOPOJSONマップのロード後に関数を実行する方法

ただし、SVGに状態がロード/表示される前に、関数は実行を継続します。マップを作成する関数は、文書準備関数で呼び出されます。私は状態にイベントリスナーを追加しようとしましたが、状態を陰にしてwindow.loadを使用した関数を呼び出す.on属性が追加されました。しかし、このように状態が画面に表示される前に実行し続ける状態を色合いや機能が

.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 

答えて

2

d3.jsonが非同期である自分のIDによってそれぞれの状態を見つけようとしてNULL値を返します。つまり、すぐにを実行するコード、つまりは、d3.jsonが完了するまでを待つことはありません。

$(document).ready()またはwindow.loadを使用しても差はありません。パスはd3.jsonがファイル(btw、大きなファイル)を取得してからSVGをペイントした後にのみDOMに表示されます。したがって、d3.jsonが完了するのを待たなければならないので、それらのパスを選択することができます。

ソリューションd3.jsonの一番下にあなたの関数を呼び出す:あなたはあなたのcolorstates関数を呼び出すとき

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" 
    } 

}); 

そうすれば、要素があるでしょう。

EDIT:IDによって(つまり、パスである)状態を選択するには、あなたが最初のパスのIDを設定する必要があります(今、彼らは何の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を使用しました)。 https://bl.ocks.org/anonymous/b2114787193d018fc094763a92872333

PS:テキサスidがここ48

働くあなたのコードは、ですあなたはD3コードでdocument.getElementByIdを使用する必要はありません。 D3セレクタを使用する方が簡単で多目的であることがわかります。

PS2:あなたの状態の境界線がないidとして、classとして「国家の境界線」を持っている必要があります:あなたはは異なる要素に同じIDを持つことはできません。 IDはユニークです。

+0

これでも、mainstateがnullとして返されます。関数を定義する前と後で、colorstates()をd3.jsonに移動しました。どちらもmainstateをnullとして返します。 – auto

+0

だから、別の*問題があります:ID = "texas"の要素がありません。どのようにIDを設定していますか? –

+0

topojsonからd3でフィーチャを作成すると、「テキサス」が作成されます。 colorstates()にアラートを追加し、地図がブラウザに表示される前に警告が実行されます。 – auto

関連する問題