我已经使用DataMaps创建了世界 map 。

我的目标是根据一些API数据异步显示和隐藏 map 上的弧。

我已经尝试过什么

我每5秒钟调用一次API,然后将响应数据推送到 map 中。
(将来将由异步调用替换)

在下面的示例中,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添加的所有弧均由其data以JSON格式(datamaps.js#L356)设置键:

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';
});



这是使用原始示例的修改版本的简单演示:

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>

关于javascript - DataMaps/按标识符隐藏弧,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55413415/

10-11 12:32