带有世界地图的 AmCharts multiCSV 数据加载器

AmCharts multiCSV dataloader with Worldmap

我有很多 CSV 文件,

我需要从他们那里创建 dataSetSelector

在 select 我需要得到 table

但是我在 table.

的末尾变得不确定

和基于 selected 数据的世界地图

地图底部的条形图

所以需要得到类似

的东西

  1. 此外,屏幕必须根据用户屏幕尺寸自动调整
  2. 然后将鼠标悬停在每个图表栏上以在地图上突出显示相同的值,如果可能的话 table 项上的相同值
  3. 在图表上的压力栏上 select 使用此值映射区域,如果可能的话在 table 项上使用相同的值
  4. valueLegend 最小值必须是来自 tables 的最小值也作为最大值
  5. 如果 table 中有重复的国家字段,那么在 table 中只显示一个国家并突出显示此行或将 * 放入国家名称(最好显示弹出窗口将鼠标悬停在所有重复值上),在地图上将所有重复项放入由换行符分隔的描述部分,并使用 *
  6. 显示值

我做什么 codepen.io

当我第一天学习 AmCharts 时,我无法获取 dataSetSelector 并将来自多个 csv 文件的数据放入其中。我也找不到如何将股票图表与地图和 table.

结合起来的信息

所以请帮助实现我的想法。

我将在 2-4 中重点介绍 AmCharts 特定的内容,因为这是问题的重点。我也只会为 AmCharts 版本 3.x 提供一个解决方案。您应该能够从那里处理 1 和 5,因为您可以调整 CSS 以更好地容纳 1 并添加您需要满足 5 的任何逻辑。

先解决容易的部分

  • dataSetSelector 是股票图表 属性。为地图和系列图表重现此功能的唯一方法是使用 <option> 标签和 JavaScript 编写您自己的 <select> 以在更改时触发所需的加载操作。
  • 股票图表只允许基于日期的数据。它不能用于 category/x 轴只是像屏幕截图中那样的字符串的图表,因此它不适合您。

考虑到以上情况,您需要设置和定位下拉菜单、table 和 chart/map div,并将代码添加到 link 所有内容。

此布局的一些基本 HTML 和 CSS

HTML:

<div id="container">
  <div id="selector-table-div">
    <select id="data-selector">
      <option value="path/to/csv-1">Dataset 1</option>
      <option value="path/to/csv-2">Dataset 2</option>
    </select>
    <div id="datatable"></div>
  </div>
  <div id="mapdiv"></div>
  <div id="chartdiv"></div>
</div>

CSS:

#mapdiv {
  width: 70%;
  height: 400px;
  float: left;
}
#chartdiv {
  width: 100%;
  height: 250px;
}
#selector-table-div {
  width: 20%;
  height: 450px;
  float: left;
}

您要靠自己的力量使它对高度的响应更加灵敏。为了简洁起见,我省略了 datatable 内容并突出显示了行。

在您的 JS 中,您需要附加一个 change 事件以在 selected 不同的下拉项时触发页面更新:

document
  .getElementById("data-selector")
  .addEventListener("change", function(e) {
    updatePage(e.target.value); //update page calls AmCharts.loadFile, updates/creates the table, map and chart with new data
  });

由于您计划在同一页面上同时使用图表和地图,因此您需要使用 amcharts.jsammap_amcharts_extension.js。在同一页面中使用 amcharts.jsammaps.js 会导致图表和地图出现错误,因为这两个文件会覆盖彼此的方法。您的柱形图需要 serial.js:

<script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="https://www.amcharts.com/lib/3/ammap_amcharts_extension.js"></script>
<script src="https://www.amcharts.com/lib/3/serial.js"></script>
<!-- other stuff omitted -->

由于您希望地图与数据相关联,因此您需要提供一种将每一行映射到地图区域的简单方法。将 ISO 3166-2 国家/地区代码添加到您的 CSV 将极大地简化流程:

country,visits,country_code
USA,2025,US
China,1882,CN
Japan,1809,JP
...

从那里,您可以使用新创建的 country_code 列设置地图区域作为 MapArea id 以激活地图上的区域:

  var areas = data.map(function(row) {
      return {
        id: row.country_code, //use ISO code for area ids
        value: row.visits
      };
    });
  // ...
  AmCharts.makeChart("mapdiv", {
    // ..
    dataProvider: {
      map: "worldLow",
      areas: areas
    }
  });

要捕获 min/max 并将其分配给该区域,只需循环遍历数据并使用 Math.min/Math.max:

  var minValue = Number.MAX_VALUE;
  var maxValue = Number.MIN_VALUE;
  data.forEach(function(row) {
    minValue = Math.min(minValue, row.visits);
    maxValue = Math.max(maxValue, row.visits);
  });
  // ...
  AmCharts.makeChart("mapdiv", {
    // ..
    valueLegend: {
      minValue: minValue,
      maxValue: maxValue
      // ...
    }
  });      

您还需要在单独的函数中调整您的 map/chart 创建代码,这些函数知道何时创建新的 map/chart 或更新现有的:

var map, chart;
// ...
function updateMap(data) {
  // ...
  if (map) {
     //makeChart here
  }
  else {
    map.dataProvider.areas = areas;
    map.valueLegend.minValue = minValue;
    map.valueLegend.maxValue = maxValue;
    map.validateData(); // update map
  }

对于地图,您还需要确保不仅在初始化时调用地图标签放置代码,而且在更新地图时调用:

function updateMap(data) {
  // ...
  if (map) {
     //makeChart here
  }
  else {
     // data update here
  }
  updateLabel(); //update labels - same code as before

创建图表非常简单。您可以将 clickGraphItem and rollOverGraphItem 事件添加到 select 相应的地图区域并突出显示 click/hover 上的 table 行:

   chart = AmCharts.makeChart("chartdiv", {
      type: "serial",
      dataProvider: data,
      // ...
      listeners: [
        {
          event: "clickGraphItem",
          method: handleBarInteraction
        }, {
          event: "rollOverGraphItem",
          method: handleBarInteraction 
        }
      ]

function handleBarInteraction(e) {
  map.selectObject(map.getObjectById(e.item.dataContext.country_code));
  var selected = document.querySelector(".selected");

  if (selected) {
    selected.classList.remove("selected");
  }
  document
    .getElementById(e.item.dataContext.country_code)
    .classList.add("selected");
}

您的未定义行可能来自您的 CSV 中的额外换行符。在创建 table、地图和图表之前,您可以简单地检查最后一项并将其从数组中弹出:

var data = AmCharts.parseCSV(response, {
   // ...
});

if (data[data.length -1].country === undefined) {
  data.pop();
}

这里有一个complete codepen with all of the above plus some restructured code. Note that the labels are placed in weird places. The example you pulled the label code from定义的异常经纬度变量,供您针对特定区域设置。您需要计算出这些值。