簡體   English   中英

DataMaps /按標識符隱藏弧

[英]DataMaps / hide arcs by identifier

我使用DataMaps創建了一張世界地圖。

我的目標是基於一些API數據在地圖上異步顯示和隱藏弧。


我已經嘗試了什么

我每隔5秒調用一次API ,並將響應數據推送到地圖中。 (這將在未來被異步調用取代)

在下面的示例中, arcData array表示我的API響應。

我可以通過DOM manipulation訪問弧。 在我的情況下,我使用d3.selectAll('path.datamaps-arc').transition().duration(3500).style("opacity", 0); 慢慢淡出所有弧線然后刪除它們。

 var arcData = //Test Data [ { origin: { latitude: 52.520008, longitude: 13.404954 }, destination: { latitude: 37.618889, longitude: -122.375 } }, { origin: { latitude: 52.520008, longitude: 13.404954 }, destination: { latitude: 25.793333, longitude:-80.290556 } }, { origin: { latitude: 52.520008, longitude: 13.404954 }, destination: { latitude: 35.877778, longitude: -78.7875 } } ]; $(document).ready(function() { var map = new Datamap({ //create data map element: document.getElementById('container'), fills: { defaultFill: "#343a40", } }); //call API every 4 seconds [Workaround for this fiddle] setInterval(function() { //add arcs to map map.arc(arcData, {strokeWidth: 2, animationSpeed: 1000, strokeColor: '#b1dd00'}); // add arc Data //Remove all arcs [should be replaced by a function that asynchronously hides single arcs after x seconds] d3.selectAll('path.datamaps-arc').transition().duration(3500).style("opacity", 0); d3.selectAll('path.datamaps-arc').transition().delay(3500).remove(); }, 4000); }); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/topojson/1.6.9/topojson.min.js"></script> <script src="https://datamaps.github.io/scripts/datamaps.world.min.js"></script> <div id="container" style="position: relative; width: 500px; height: 300px;"></div> 


這個解決方案基本上有效

我的問題

所有弧都同時隱藏。 如果我將來異步調用API,當弧正在繪制時會出現沖突,同時觸發刪除過程。

我想要的是

我可以通過某個標識訪問每個弧的解決方案,並在完全繪制后單獨刪除它們。

通過DataMaps添加的所有弧實際上都是以JSON格式( datamaps.js#L356 )的data鍵入的:

var arcs = layer.selectAll('path.datamaps-arc').data( data, JSON.stringify ); 

請注意, DataMaps使用JSON.stringify作為關鍵功能 如果DataMaps提供了一種在這里使用自定義鍵功能的方法,那就太好了,但是...

雖然這些密鑰本身不是持久的,但足以確保我們只有一個弧用於一個相同的數據。 弧數據是弧標識符本身。

利用這些知識,我們可以通過比較它的數據來識別弧:

var selectedArcs = d3.selectAll('path.datamaps-arc').filter(function(data) {
   // compare data
   return data === someValue;
});

為了更進一步,我們實際上可以調整傳遞給DataMaps.arc的數據,以便它實際上保存我們的比較友好標識符。 origindestination字段是強制性的,但我們可以根據自己的喜好自由使用任何其他字段。

{
  id: 'some-unique-identifier',
  origin: {
    latitude: 52.520008,
    longitude: 13.404954
  },
  destination: {
    latitude: 37.618889,
    longitude: -122.375
  }
}

然后我們可以使用這個調整的字段來識別我們的弧:

var selectedArcs = d3.selectAll('path.datamaps-arc').filter(function(data) {
   return data.id === 'some-unique-identifier';
});

請記住, DataMaps使用其整個data值鍵入每個弧。 意味着具有相同id但不同origin和/或destination兩個數據將被視為兩個不同的弧。

這是使用原始示例的修改版本的簡單演示:

 var arcData = //Test Data [ { id: 123, origin: { latitude: 52.520008, longitude: 13.404954 }, destination: { latitude: 37.618889, longitude: -122.375 } }, { id: 'abc', origin: { latitude: 52.520008, longitude: 13.404954 }, destination: { latitude: 25.793333, longitude:-80.290556 } }, { id: 'xyz', origin: { latitude: 52.520008, longitude: 13.404954 }, destination: { latitude: 35.877778, longitude: -78.7875 } } ]; $(document).ready(function() { var map = new Datamap({ //create data map element: document.getElementById('container'), fills: { defaultFill: "#343a40", } }); function drawMap() { map.arc(arcData, {strokeWidth: 2, animationSpeed: 1000, strokeColor: '#b1dd00'}); }; function removeArc(id) { var all = d3.selectAll('path.datamaps-arc'); var sel = all.filter(function(data) { return data.id === id; }); sel.transition().duration(1000).style("opacity", 0).remove(); }; $('button').on('click', function(){ var id = $(this).data('arc'); if (id) { removeArc(id); } else { drawMap(); } }); drawMap(); }); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/topojson/1.6.9/topojson.min.js"></script> <script src="https://datamaps.github.io/scripts/datamaps.world.min.js"></script> <button type="button" data-arc="123">Remove Arc id:123</button> <button type="button" data-arc="abc">Remove Arc id:abc</button> <button type="button" data-arc="xyz">Remove Arc id:xyz</button> <button type="button">Redraw</button> <div id="container" style="position: relative; width: 500px; height: 300px;"></div> 

好吧,我試圖解決你的問題。 我所做的是,我為每個數據映射弧分配了唯一的ID。 它可以輕松訪問獨立弧,您可以相應地更改它們的過渡。

為了演示目的,我已經隨機延遲它並且它正常工作。 我將第一弧延遲了1000毫秒,第二弧延遲了2000毫秒,第三弧延遲了3000毫秒。 您可以實現自己的算法來根據需要延遲弧的轉換。 我在您可以參考的代碼中添加了注釋。

由於setInterval在每4000毫秒后運行,如果任何弧的延遲超過4000毫秒,那么您將能夠看到所有同時僅生成一次的弧,這是第一次。 在那一代弧之后會非常隨機,所以請記住它。

 var arcData = //Test Data [{ origin: { latitude: 52.520008, longitude: 13.404954 }, destination: { latitude: 37.618889, longitude: -122.375 } }, { origin: { latitude: 52.520008, longitude: 13.404954 }, destination: { latitude: 25.793333, longitude: -80.290556 } }, { origin: { latitude: 52.520008, longitude: 13.404954 }, destination: { latitude: 35.877778, longitude: -78.7875 } } ]; $(document).ready(function() { var map = new Datamap({ //create data map element: document.getElementById('container'), fills: { defaultFill: "#343a40", } }); //hide arc function which will take x amount of delay and arc-id which you want to delay. function hideArc(delay, arcId) { d3.select('#' + arcId).transition().duration(delay).style("opacity", 0); d3.select('#' + arcId).transition().delay(delay).remove(); } //call API every 4 seconds [Workaround for this fiddle] setInterval(function() { //add arcs to map map.arc(arcData, { strokeWidth: 2, animationSpeed: 1000, strokeColor: '#b1dd00' }); // add arc Data let arcIds = [];// it will hold all the unique arc-ids d3.selectAll('path.datamaps-arc')[0].forEach((ele, index) => { ele.setAttribute('id', 'datamap-arc-' + index); arcIds.push('datamap-arc-' + index);// pushing new generated ids to arcIds array }); //mapping of delay and arc-id, this part is replaceable, you can change it the way you want to change the delay of respective arc. let arcIdAndDelaymapping = arcIds.map((aercId, index) => { return { aercId, delay:1000*(index+1) } }) //Remove all arcs [should be replaced by a function that asynchronously hides single arcs after x seconds] //calling hideArc function with their respective delays. arcIdAndDelaymapping.forEach((arcMapping) => { hideArc(arcMapping.delay, arcMapping.aercId); }) }, 4000); }); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/topojson/1.6.9/topojson.min.js"></script> <script src="https://datamaps.github.io/scripts/datamaps.world.min.js"></script> <div id="container" style="position: relative; width: 500px; height: 300px;"></div> 

希望它能解決你的問題。 快樂編碼!! 謝謝你讓我探索數據地圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM