首页 > 解决方案 > 如何根据 d3.js 中 api 的 json 数据进行编码?

问题描述

我是初学者,我正在学习 d3.js,但我无法弄清楚如何根据来自 api 的 json 格式的数据绘制图形或代码。这是我尝试过的事情之一,但我无法根据另一个 api 中的新数据进行更改。有谁能够帮助我?我在哪里进行更改?

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>

    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg width="960" height="500"></svg>
  </head>

    <style>

      body {
        text-align: center;
        margin-top: 5em;
        background-color: #74b9ff;
      }

      h1 {
        color: snow;
      }


    </style>


    <body>
    <h1>Bitcoin Prices in U.S. Dollars</h1>
    <script>


  var url = "https://min-api.cryptocompare.com/data/histoday?fsym=BTC&tsym=USD&limit=200&aggregate=3&e=CCCAGG";


  d3.json(url).get(function(error, d) {

    var data = d.Data;
    data.forEach(function(d){ d.time = new Date(d.time * 1000) });

    if (error) throw error;

    var svg = d3.select("svg"),
        margin = {top: 20, right: 20, bottom: 30, left: 50},
        width = +svg.attr("width") - margin.left - margin.right,
        height = +svg.attr("height") - margin.top - margin.bottom,
        g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var x = d3.scaleTime()
        .range([0, width])

    var y = d3.scaleLinear()
        .range([height, 0]);

    var line = d3.line()
        .x(function(d) { return x(d.time); })
        .y(function(d) { return y(d.close); });

    x.domain(d3.extent(data, function(d) { return d.time; }));
    y.domain(d3.extent(data, function(d) { return d.close; }));

    g.append("g")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x))
        .attr("stroke-width", 2)
        .attr("fill", "none")
        .style("font-size",".8em");

    g.append("g")
        .call(d3.axisLeft(y))
        .attr("stroke-width", 2)
        .style("font-size",".8em")
      .append("text")
        .attr("fill", "#000")
        .attr("transform", "rotate(-90)")
        .attr("y", 20)
        .attr("text-anchor", "end")
        .attr("font-size", "1.2em")
        .text("Price ($)")


    g.append("path")
        .datum(data)
        .attr("fill", "none")
        .attr("stroke", "#ffeaa7")
        .attr("stroke-linejoin", "round")
        .attr("stroke-linecap", "round")
        .attr("stroke-width", 2)
        .attr("d", line);

  });

    </script>
  </body>
</html>

我得到了上述代码的正确输出,但我想将 api 更改为https://blockchain.info/ticker

我可以在哪里进行更改以使其正常工作?

标签: javascriptjsond3.js

解决方案


因为它是比特币与其他硬币相比的转换率,所以将它们全部绘制在一张图中是没有意义的。这JPY将粉碎所有其他酒吧。

如果它们只是给定当前汇率的转换,为什么要使用不同的硬币购买/出售比特币。

如果你画一个硬币的值,你会得到下图

<!DOCTYPE html>
<meta charset="utf-8">
<style>

.bar {
  fill: steelblue;
}

.bar:hover {
  fill: brown;
}

.axis--x path {
  display: none;
}

</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var svg = d3.select("svg"),
    margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom;

var x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
    y = d3.scaleLinear().rangeRound([height, 0]);

var g = svg.append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

d3.json("https://blockchain.info/ticker", function(error, data) {
  if (error) throw error;

  data = data.EUR;

  var keys = ["15m", "last", "buy", "sell"];
  x.domain(keys);
  y.domain([0, d3.max(keys, function(k) { return data[k]; })]);

  g.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

  g.append("g")
      .attr("class", "axis axis--y")
      .call(d3.axisLeft(y))
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", "0.71em")
      .attr("text-anchor", "end")
      .text("price");

  g.selectAll(".bar")
    .data(keys)
    .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(k) { return x(k); })
      .attr("y", function(k) { return y(data[k]); })
      .attr("width", x.bandwidth())
      .attr("height", function(k) { return height - y(data[k]); });
});

</script>

也不好用。因为所有的变化都在前几个像素中。

您需要一种方法来记录 JSON 文件中特定硬币和图形随时间变化的值,就像您的原始数据集一样。

可以通过每 x 分钟获取一次数据,然后使用 enter/exit/removedata()调用修改图形或像这样重绘图形来完成。

在实际数据的DEBUG部分之前放置注释。并取消注释以下行

//setInterval(getData, 5 * 60 * 1000);

在这里,我为演示每 5 秒生成一次虚拟数据。

为防止超出内存data长度限制为 1000 个样本。

编辑

它现在在 x 轴上显示样本的日期。

<!DOCTYPE html>
<style>
.p15m { stroke: steelblue;}
.pbuy { stroke: red;}
.plast { stroke: green;}
.psell { stroke: orange;}
</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var svg = d3.select("svg"),
    margin = {top: 20, right: 20, bottom: 30, left: 50},
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom;

var data = [];

var x = d3.scaleTime()
    .range([0, width]);

var y = d3.scaleLinear()
    .rangeRound([height, 0]);

var line = d3.line()
    .x(function(d) { return x(d[0]); })
    .y(function(d) { return y(d[1]); });

function getData() {
   //DEBUG
   data.push( {"15m": Math.random()*100 + 100, "last": Math.random()*100 + 100, "buy": Math.random()*100 + 100, "sell": Math.random()*100 + 100, "date": new Date() } );
   updateGraph();
   return;
   // DEBUG END

  d3.json("https://blockchain.info/ticker", function(error, dataNew) {
    if (error) throw error;
    var d = dataNew.EUR;
    d.date = new Date();
    data.push();
    if (data.length > 1000) data = data.shift();
    updateGraph();
  });
}

getData();
setTimeout(getData, 5000);

//DEBUG
setInterval(getData, 5 * 1000);
//DEBUG END
//setInterval(getData, 5 * 60 * 1000);

function updateGraph() {
  if (data.length < 2) return;
  svg.select("g").remove(); // clean the graph
  var keys = ["15m", "last", "buy", "sell"];
  var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
  x.domain(d3.extent(data, d => d.date));
  var flat = [];
  data.map( d => keys.map(k => d[k]) ).forEach(e => { flat = flat.concat(e); });
  y.domain(d3.extent(flat , function(d) { return d; }));

  g.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x))
    .select(".domain")
      .remove();

  g.append("g")
      .call(d3.axisLeft(y))
    .append("text")
      .attr("fill", "#000")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", "0.71em")
      .attr("text-anchor", "end")
      .text("Price (EUR)");

  g.selectAll("g.key")
   .data(keys)
   .enter()
   .append("g")
   .attr("class", d => "key p" + d )
   .append("path")
      .datum(k => data.map( (d, i) => [d.date, d[k]]))
      .attr("fill", "none")
      .attr("stroke-linejoin", "round")
      .attr("stroke-linecap", "round")
      .attr("stroke-width", 1.5)
      .attr("d", line);
}
</script>


推荐阅读