【问题标题】:How to switch csv dataset of d3.js graph to another csv by clicking on button如何通过单击按钮将 d3.js 图形的 csv 数据集切换到另一个 csv
【发布时间】:2019-05-14 10:39:46
【问题描述】:

我见过这个漂亮的 d3 仪表板。我想知道是否可以通过单击按钮将 csv 文件切换到另一个文件。

这可能吗?

这是仪表板的链接:

http://bl.ocks.org/farazshuja/4a582fdeaa1f46f885ffa1776346fdec

解析csv文件的部分,需要通过点击按钮更改为“data2.csv”。

<script>
var freqData;
d3.csv("data.csv", function(data) {
   freqData = data.map(function(d) { return {
        State: d.State, 
        freq: {
            low: +d.low,
            mid: +d.mid,
            high: +d.high
        }}
    });
  dashboard('#dashboard',freqData);
});


</script>

我想像这个例子一样切换 csv 文件:http://bl.ocks.org/enjalot/1525346

<script>
var prices_csv = function()
{
    var parse = d3.time.format("%m/%d/%Y").parse;
    d3.csv("prices.csv", function(prices)
    {
        //prices is an array of json objects containing the data in from the csv
        console.log("prices:", prices)
        data = prices.map(function(d)
        {
            //each d is one line of the csv file represented as a json object
            console.log("d", d)
            month = parse(d.month).getMonth();
            console.log("month:", d.month, month)
            //we slice the dollar sign off then convert to a number with the + sign
            //slicing works like "$216".slice(1) gives you 216, 
            //you can also give it a range like "$216 asdf".slice(1,4) gives you 216
            p = d.price
            price = +p.slice(1)
            console.log("price:", p, price);
            return {"month": month, "value":price} ;
        })
        console.log("data", data)
        bars(data);
    })
}
</script>

我尝试像示例中那样对其进行调整,但到目前为止没有成功。我是 javascript 和 d3.js 的纯初学者,因此我希望有人可以帮助我。

更新:

第一部分(通过按钮更改数据文件 (csv))似乎效果很好。 然而,还有另一个挑战。结构如下: 有一个包含各种仪表板的 div。仪表板加载“对象”作为外部文件。通过使用带有两个按钮“2018”和“2019”的树形菜单,我希望根据所选年份在仪表板中显示 data1“d1”或 data2“d2”。

这是 2018 年第一个加载 div“sales1”的菜单按钮。 “sales1”通过对象加载各种外部 html 文件。在那里,只应加载“d1”(仪表板文件中的 2018 年数据):

<li><a href="#" type="#sales1" id="buttonsales1">units FTP</a></li>

<script>
$(document).ready(function(){
    $("#buttonsales1").click(function(){
        $("#sales1").toggle();
        $("#startscreen").hide();
        $("#sales2").hide();
    });
});
</script>

在 2018 年的第一个菜单按钮下方,应该有 2019 年的第二个菜单按钮。单击时,它会加载相同的 div“sales1”,但这次外部仪表板文件显示 data2“d2”(2019 年的数据)。

这是通过对象加载仪表板的 div“sales1”:

<div id="sales1">   

    <div id="left">

        <div class="label" data-toggle="toggle" data-target="#sales1desbox2">
        <h2>units sold sales region center</h2>
        <p>by months and sales rep.</p>
        </div>

            <!-- START: Label description. -->
            <div id="sales1desbox2" class="togglebox">
                <div class="description">
                by month and sales region.
                </div>
            </div>
            <!-- END: Label description. -->
    <!-- This is the first dashboard -->        
    <object class="ltrl" type="text/html" data="sales/1/dashboard_center_sales.html">
    </object>
    </div>

    <div id="right">

        <div class="label" data-toggle="toggle" data-target="#sales1desbox3">
        <h2>units sold sales region east</h2>
        <p>by months and sales rep.</p>
        </div>

            <!-- START: Label description. -->
            <div id="sales1desbox3" class="togglebox">
                <div class="description">
                by month and sales region.
                </div>
            </div>
            <!-- END: Label description. -->
    <!-- This is the second dashboard -->       
    <object class="ltrl" type="text/html" data="sales/1/dashboard_east_sales.html">
    </object>
    </div>

</div>
<!-- END: div "sales1" -->

调整后的仪表板现在如下所示:

<style>
....
....
....
</style>
<body>
<!-- here are the buttons to control the two csv data sets.  -->

  <button id="d1">Data 1</button><button id="d2">Data 2</button><br />

  <div id='dashboard'>
</div>
<script src="http://d3js.org/d3.v3.min.js"></script>
 <script>
    // here are the event listeners to control the buttons
    d3.select("#d1").on("click", function(d, i) {
      data1();
    });
    d3.select("#d2").on("click", function(d, i) {
      data2();
    });
    function dashboard(id, fData) {
      var barColor = "steelblue";

....其余部分相同,直到从两个不同的csv中解析数据的部分:

<!-- Here the data data1 (d1) for 2018 -->

<script>
var freqData;
function data1() {
  clearDashboard();
  d3.csv("data.csv", function(data) {
    filteredData = data.filter(function(row) {
        return row['KPI'] == 'A';
    });
    freqData = filteredData.map(function(d) { 
        return {
            Month: d.Month, 
            freq: {
                S40411: +d.S40411,
                S40412: +d.S40412,
                S40413: +d.S40413,
                S40414: +d.S40414
            }
        };
    });
    dashboard('#dashboard',freqData);
});
}
    // calls the data1 onload
    data1();
    //clears the dashboard used in data1 and data2
    function clearDashboard() {
      var myNode = document.getElementById("dashboard");
      while (myNode.firstChild) {
        myNode.removeChild(myNode.firstChild);
      }
    }

    <!-- Here the data data2 (d2) for 2019 -->

    function data2() {
  clearDashboard();
  d3.csv("data2.csv", function(data) {
    filteredData = data.filter(function(row) {
        return row['KPI'] == 'A';
    });
    freqData = filteredData.map(function(d) { 
        return {
            Month: d.Month, 
            freq: {
                S40411: +d.S40411,
                S40412: +d.S40412,
                S40413: +d.S40413,
                S40414: +d.S40414
            }
        };
    });
    dashboard('#dashboard',freqData);
});
}
</script>

</body>

为了更直观,我创建了一个小的grafic

更新 2:

有一个带有 2018 年和 2019 年按钮的菜单。 它看起来像这样:

2018 单位 FTP 2019 单位 FTP

两者的数据结构相同,但数据不同。因此,外部仪表板文件中现在有两个不同的函数:函数 data1() 和函数 data2(),每个函数引用不同的 csv 文件(2018、2019)。

第一个按钮“2018, Units FTP”将 div 称为“sales1”:

<li><a href="#" type="#sales1" id="buttonsales1">units FTP</a></li>

第二个按钮的作用与 2019 年相同。那么区别在哪里?

Div“sales1”包含嵌入了对象标签的各种仪表板:

<div id="sales1">
<object class="ltrl" type="text/html" data="sales/0/dashboard_east_sales.html"></object>
…
…
…
</div>

我希望第二个按钮使用相同的仪表板调用相同的 div“sales1”,但不是默认选择“function data1()”,而是应该在仪表板 (dashboard_east_sales.html) 中调用“function data2()”。

更新 3:

我制作了一个 Codepen 来准确展示我想要实现的目标:

这是通过对象标签嵌入仪表板的 index.html: https://codepen.io/robx360/pen/wbpoQM

这是仪表板文件本身: https://codepen.io/robx360/pen/pmpNWN

如您所见,索引文件中的按钮应该会触发数据集的更改。截至目前,这些按钮位于仪表板文件中。这就是我想要改变的。

更新 4:

<!–– those buttons shall have the functionality of the buttons within the dashboard file that is embedded with object tag ––>
<li><a href="#" type="#sales1" id="buttonsales1">units FTP 2018</a></li>
<li><a href="#" type="#sales1" id="buttonsales1">units FTP 2019</a></li>


<!-- This part is currently located in the external Dashboard file (dashboard.html) -->

<!-- here are the buttons to control the two csv data sets -->
  <button id="d1">Data 1 (should be units FTP 2018)</button>
  <button id="d2">Data 2 (should be units FTP 2019)</button>


<!–– The event listeners must point to the object tag ID "dashboard1", how? ––>

 <script>
    // here are the event listeners to control the buttons
    d3.select("#d1").on("click", function(d, i) {
      data1();
    });
    d3.select("#d2").on("click", function(d, i) {
      data2();
    });

</script>   

    <div id="sales1">   

    <div id="right">

    <object id="dashboard1" style="width:900px; height:600px; type="text/html" data="dashboard.html">
    </object>
    </div>

</div>

【问题讨论】:

    标签: javascript csv d3.js


    【解决方案1】:

    当然可以 :) 您可以像第二个示例一样将两个按钮添加到第一个示例的代码中。我假设 csv 文件是相似的,并且图表是相同的,只是数据会有所不同。如果您希望拥有不同的图表,您可以添加更多逻辑。我已经制定了一个示例来帮助您入门。

    ...styles
    
    <body>
    
      <!-- here are the buttons to control the two csv data sets -->
      <button id="d1">Data 1</button><button id="d2">Data 2</button><br />
    
      <div id="dashboard"></div>
      <script src="http://d3js.org/d3.v3.min.js"></script>
    
      <script>
        // here are the event listeners to control the buttons
        d3.select("#d1").on("click", function(d, i) {
          data1();
        });
        d3.select("#d2").on("click", function(d, i) {
          data2();
        });
        function dashboard(id, fData) {
          var barColor = "steelblue";
    
    ....continue with all of the code from the first example....
    

    用这两个函数替换结束脚本来控制两个csv文件的加载,以及清除前一个csv创建的节点的函数。

    <script>
        var freqData;
        function data1() {
          clearDashboard();
          d3.csv("data.csv", function(data) {
            freqData = data.map(function(d) {
              return {
                State: d.State,
                freq: {
                  low: +d.low,
                  mid: +d.mid,
                  high: +d.high
                }
              };
            });
            dashboard("#dashboard", freqData);
          });
        }
        // calls the data1 onload
        data1();
        //clears the dashboard used in data1 and data2
        function clearDashboard() {
          var myNode = document.getElementById("dashboard");
          while (myNode.firstChild) {
            myNode.removeChild(myNode.firstChild);
          }
        }
        function data2() {
          clearDashboard();
          d3.csv("./data2.csv", function(data) {
            freqData = data.map(function(d) {
              return {
                State: d.State,
                freq: {
                  low: +d.low,
                  mid: +d.mid,
                  high: +d.high
                }
              };
            });
            dashboard("#dashboard", freqData);
          });
        }
      </script>
    </body>
    
    

    编辑:

    要拥有两个仪表板,您将仪表板重命名为仪表板1 并添加另一个名为仪表板2

    <div id="dashboard1"></div>
    <div id="dashboard2"></div>
    

    然后在你的 data1 和 data2 函数中,你定位那些 div

    ...
    
    dashboard("#dashboard1", freqData); 
    ...
    
    dashboard("#dashboard2", freqData);
    

    编辑 clearDashboard 函数以接受将确定要清除的 div 的参数

    function clearDashboard(dashboard) {
          var myNode = document.getElementById(dashboard);
          while (myNode.firstChild) {
            myNode.removeChild(myNode.firstChild);
          }
        }
    

    并将该函数的参数设置为 div 以清除

    ...
    
    clearDashboard("dashboard1");
    ...
    
    clearDashboard("dashboard2");
    
    

    【讨论】:

    • 非常适合第一部分。我更新了第二部分的问题,因为如果文件是通过对象从外部加载的,如何切换数据集仍然不清楚。
    • 你可以创建两个 div #dashboard1 和 #dashboard2 并且你必须创建两个 clearDashboard 函数来清除那些新创建的 div
    • 好的。如何指定一个仪表板只显示 data1 和另一个 data2?你能用代码做一个例子吗?
    • 无法正常工作。我不知道我在这里错过了什么。
    • 您要求某人在一个问题中解决您的整个项目。您需要将每个问题分解成更小的部分。如果您被困在如何定位通过对象标签嵌入的 html 文件,这与原始问题完全不同,您可以开始一个新线程或对该主题进行更多搜索。另一个很好的技术是制作一个小的测试文件来尝试特定的问题,例如从对象标签定位 html 文件。希望能有所帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-23
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 2020-03-02
    相关资源
    最近更新 更多