【问题标题】:d3.js updating from v3 to v5d3.js 从 v3 更新到 v5
【发布时间】:2018-10-14 21:31:12
【问题描述】:

我正在尝试编辑其他人用 d3.js v3 到 v5 编写的代码,以获取包含我的数据集的交互式响应表。谁能告诉我们为什么它不起作用,尽管我认为我已经编辑了需要完成的行?谢谢你。 http://bl.ocks.org/AMDS/4a61497182b8fcb05906这是原始代码。

<title>D3.js Sortable & Responsive Table</title>

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<!--[if !IE]><!-->
<style>
* { 
  margin: 0; 
  padding: 0; 
 }
 body { 
   font: 14px/1.4 Georgia, Serif; 
 }
#page-wrap {
  margin: 50px;
}
p {
 margin: 20px 0; 
}

/* 
Generic Styling, for Desktops/Laptops 
*/
table { 
    width: 100%; 
    border-collapse: collapse; 
}
/* Zebra striping */
tr:nth-of-type(odd) { 
    background: #eee; 
}
th { 
    background: #333; 
    color: white; 
    font-weight: bold; 
    cursor: s-resize;
    background-repeat: no-repeat;
    background-position: 3% center;
}
td, th { 
    padding: 6px; 
    border: 1px solid #ccc; 
    text-align: left; 
}

th.des:after {
  content: "\21E9";
}

th.aes:after {
  content: "\21E7";
}

/* 
Max width before this PARTICULAR table gets nasty
This query will take effect for any screen smaller than 760px
and also iPads specifically.
*/
@media 
only screen and (max-width: 760px),
(min-device-width: 768px) and (max-device-width: 1024px)  {

    /* Force table to not be like tables anymore */
    table, thead, tbody, th, td, tr { 
        display: block; 
    }

    /* Hide table headers (but not display: none;, for accessibility) */
    thead tr { 
        position: absolute;
        top: -9999px;
        left: -9999px;
    }

    tr { border: 1px solid #ccc; }

    td { 
        /* Behave  like a "row" */
        border: none;
        border-bottom: 1px solid #eee; 
        position: relative;
        padding-left: 50%; 
    }

    td:before { 
        /* Now like a table header */
        position: absolute;
        /* Top/left values mimic padding */
        top: 6px;
        left: 6px;
        width: 45%; 
        padding-right: 10px; 
        white-space: nowrap;
    }

    /*
    Label the data
    */
    td:before {
      content: attr(data-th) ": ";
      font-weight: bold;
      width: 6.5em;
      display: inline-block;
    }
}

/* Smartphones (portrait and landscape) ----------- */
@media only screen
and (min-device-width : 320px)
and (max-device-width : 480px) {
    body { 
        padding: 0; 
        margin: 0; 
        width: 320px; }
    }

/* iPads (portrait and landscape) ----------- */
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
    body { 
        width: 495px; 
    }
}

</style>
<!--<![endif]-->

<div id="page-wrap">

<h1>D3.js Sortable & Responsive Table</h1>

<p>Click the table header to sort data according to that column</p>

</div>
<script type="text/javascript" src="http://d3js.org/d3.v5.min.js"></script>
<script type="text/javascript">
  d3.csv("E2allProcEff.csv".then(function(data) {
      d3.tsv(tsv, type).then(function(data) {



      var sortAscending = true;
      var table = d3.select('#page-wrap').append('table');
      var titles = d3.keys(data[0]);
      var headers = table.append('thead').append('tr')
                       .selectAll('th')
                       .data(titles).enter()
                       .append('th')
                       .text(function (d) {
                            return d;
                        })
                       .on('click', function (d) {
                           headers.attr('class', 'header');

                           if (sortAscending) {
                             rows.sort(function(a, b) { return b[d] < a[d]; });
                             sortAscending = false;
                             this.className = 'aes';
                           } else {
                             rows.sort(function(a, b) { return b[d] > a[d]; });
                             sortAscending = true;
                             this.className = 'des';
                           }

                       });

      var rows = table.append('tbody').selectAll('tr')
                   .data(data).enter()
                   .append('tr');
      rows.selectAll('td')
        .data(function (d) {
            return titles.map(function (k) {
                return { 'value': d[k], 'name': k};
            });
        }).enter()
        .append('td')
        .attr('data-th', function (d) {
            return d.name;
        })
        .text(function (d) {
            return d.value;
        });
        })
  });
</script>

【问题讨论】:

  • 看起来错误可能来自加载数据的脚本顶部 - tsvtype 定义在哪里,为什么要加载 csv 然后加载 tsv文件?您还缺少 csv 文件名称后的右括号 ())。

标签: javascript html d3.js


【解决方案1】:

我删除了前两行,由于d3.csv("E2allProcEff.csv".then 中缺少) 和两种不同方法的数据冗余加载,导致解析器错误:

d3.csv("E2allProcEff.csv".then(function(data) {
  d3.tsv(tsv, type).then(function(data) {

以及底部的大括号/括号组。当我创建一些数据对象时,表格显示正常:

var data = ['Blues','Greens','Greys','Purples','Reds','Oranges'].map( s => {
  var obj = { colours: s };
  d3['scheme' + s ][5].forEach( (c,i) => obj['position_' +  i] = c )
  return obj
} )

var sortAscending = true;
var table = d3.select('#page-wrap').append('table');
var titles = d3.keys(data[0]);
var headers = table.append('thead').append('tr')
  .selectAll('th')
  .data(titles).enter()
  .append('th')
  .text(function(d) {
    return d;
  })
  .on('click', function(d) {
    headers.attr('class', 'header');

    if (sortAscending) {
      rows.sort(function(a, b) {
        return b[d] < a[d];
      });
      sortAscending = false;
      this.className = 'aes';
    } else {
      rows.sort(function(a, b) {
        return b[d] > a[d];
      });
      sortAscending = true;
      this.className = 'des';
    }

  });

var rows = table.append('tbody').selectAll('tr')
  .data(data).enter()
  .append('tr')

rows.selectAll('td')
  .data(function(d) {
    return titles.map(function(k) {
      return {
        'value': d[k],
        'name': k
      };
    });
  })
  .enter()
  .append('td')
  .attr('data-th', function(d) {
    return d.name;
  })
  .text(function(d) {
    return d.value;
  });
* { 
  margin: 0; 
  padding: 0; 
 }
 body { 
   font: 14px/1.4 Georgia, Serif; 
 }
#page-wrap {
  margin: 50px;
}
p {
 margin: 20px 0; 
}

/* 
Generic Styling, for Desktops/Laptops 
*/
table { 
    width: 100%; 
    border-collapse: collapse; 
}
/* Zebra striping */
tr:nth-of-type(odd) { 
    background: #eee; 
}
th { 
    background: #333; 
    color: white; 
    font-weight: bold; 
    cursor: s-resize;
    background-repeat: no-repeat;
    background-position: 3% center;
}
td, th { 
    padding: 6px; 
    border: 1px solid #ccc; 
    text-align: left; 
}

th.des:after {
  content: "\21E9";
}

th.aes:after {
  content: "\21E7";
}

/* 
Max width before this PARTICULAR table gets nasty
This query will take effect for any screen smaller than 760px
and also iPads specifically.
*/
@media 
only screen and (max-width: 760px),
(min-device-width: 768px) and (max-device-width: 1024px)  {

    /* Force table to not be like tables anymore */
    table, thead, tbody, th, td, tr { 
        display: block; 
    }

    /* Hide table headers (but not display: none;, for accessibility) */
    thead tr { 
        position: absolute;
        top: -9999px;
        left: -9999px;
    }

    tr { border: 1px solid #ccc; }

    td { 
        /* Behave  like a "row" */
        border: none;
        border-bottom: 1px solid #eee; 
        position: relative;
        padding-left: 50%; 
    }

    td:before { 
        /* Now like a table header */
        position: absolute;
        /* Top/left values mimic padding */
        top: 6px;
        left: 6px;
        width: 45%; 
        padding-right: 10px; 
        white-space: nowrap;
    }

    /*
    Label the data
    */
    td:before {
      content: attr(data-th) ": ";
      font-weight: bold;
      width: 6.5em;
      display: inline-block;
    }
}

/* Smartphones (portrait and landscape) ----------- */
@media only screen
and (min-device-width : 320px)
and (max-device-width : 480px) {
    body { 
        padding: 0; 
        margin: 0; 
        width: 320px; }
    }

/* iPads (portrait and landscape) ----------- */
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
    body { 
        width: 495px; 
    }
}
<script type="text/javascript" src="http://d3js.org/d3.v5.min.js"></script>

<div id="page-wrap"></div>

您只需要添加加载 csv 数据的代码,就完成了:

d3.csv("E2allProcEff.csv").then( function(data) {

  var sortAscending = true;
  var table = d3.select('#page-wrap').append('table');
  var titles = d3.keys(data[0]);

  [... snip ...]

  rows.selectAll('td')
    .data(function (d) {
        return titles.map(function (k) {
            return { 'value': d[k], 'name': k};
        });
    }).enter()
    .append('td')
    .attr('data-th', function (d) {
        return d.name;
    })
    .text(function (d) {
        return d.value;
    });

})

【讨论】:

  • 谢谢,但我不确定为什么它不适合我。 'd3.csv("E2allProcEff.csv").then( function(data) {' 这行是否足以让我加载我的 csv 数据?或者我应该添加一行来读取和存储数据,例如,' var data= data.csvparse(data)'? 当我转到网页上的控制台时,它说“跨源请求仅支持 HTTP”,“Fetch API 无法加载文件://~~/Downloads/E2allprocEFF.csv由于访问控制检查”和“未处理的承诺拒绝:TypeError:跨源请求仅支持 HTTP。”
  • 您不需要读取和存储数据——d3.csv('filename').then( function(data) { 就是这样做的。阅读d3.fetch 上的文档,因为在 d3 v5 中获取和解析数据的工作方式不同。您当前的错误是因为您尝试使用 file: 协议访问文档,而 Fetch API 不允许这样做。最快的解决方法是在您的计算机上运行一个小服务器——例如2ality.blogspot.com/2015/10/http-server-nodejs.html
【解决方案2】:

遇到了相同的示例,但排序不起作用。经过一番研究,我发现这是由于排序功能不好(如Sorting in JavaScript: Shouldn't returning a boolean be enough for a comparison function?中所述)

我的固定版本:http://bl.ocks.org/prusswan/cdc289db753810a3c537f8eb2603bda8

还有一个使用 d3 的排序助手的更清洁的修复:

rows.sort(function(a, b) { 
  //return b[d] < a[d]; // this is bad
  //return b[d] < a[d] ? 1 : b[d] == a[d] ? 0 : -1; // this is a valid fix
  return d3.ascending(a[d], b[d]); // this is more idiomatic
});

有趣的是,原来的“坏”版本可以在我的手机浏览器上运行,但不能在我的桌面 Chrome 上运行,所以手机浏览器可能正在使用某种怪癖模式......

【讨论】:

    猜你喜欢
    • 2020-07-31
    • 2019-07-10
    • 1970-01-01
    • 2018-09-07
    • 2018-04-12
    • 2016-12-27
    • 2020-06-28
    • 2020-10-26
    • 1970-01-01
    相关资源
    最近更新 更多