визуализировать гистограммы в JavaScript, используя SVG и 2D-массив из JSON - PullRequest
0 голосов
/ 05 февраля 2019

Последние 2 дня потратили на просмотр стека и другие примеры того, почему мои диаграммы не отображаются должным образом.

Я уверен, что чего-то не хватает в части масштабирования кода.Если я скопирую темную часть внизу оси X на графике в блокнот, то получу все элементы оси X.

Кто-нибудь может указать мне правильное направление?

<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.8.0/d3.min.js"></script>
  <script>
    document.addEventListener('DOMContentLoaded',function(){
        req.open("GET",'https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json',true);
        req.send();
        req.onload=function(){
          json=JSON.parse(req.responseText);
          document.getElementsByClassName('title')[0].innerHTML=json.name;
          dataset=json.data;
          
          const w = 500;
          const h = 300;
          const padding = 10;
          
          // create an array with all date names
          const dates = dataset.map(function(d) {
              return d[0];
          });
          
          const xScale = d3.scaleBand()
                          .rangeRound([padding, w-padding])
                          .padding([.02])
                          .domain(dates);
          console.log("Scale Bandwidth: " + xScale.bandwidth());
          
          const yScale = d3.scaleLinear()
                          .rangeRound([h-padding, padding])          
                          .domain(0,d3.max(dataset, (d)=>d[1]));
          console.log("Dataset Max Height: " + d3.max(dataset, (d)=>d[1]));
          
          const xAxis = d3.axisBottom(xScale);
          const yAxis = d3.axisLeft(yScale);
                    
          const svg = d3.select("body")
                        .append("svg")
                        .attr("width", w)
                        .attr("height", h);
          
          svg.append("g")
             .attr("transform", "translate(0," + (h - padding) + ")")
             .call(xAxis);
          svg.append("g")
             .attr("transform", "translate(" + padding + ",0)")
             .call(yAxis);          
          
          svg.selectAll("rect")
                      .data(dataset)
                      .enter()
                      .append("rect")
                      .attr("width",(d,i)=>xScale.bandwidth())
                      .attr("height",(d,i)=>(h-yScale(d[1])))
                      .attr("x", (d,i)=>xScale(d[0]))
                      .attr("y", (d,i)=>yScale(d[1]))
                      .attr("fill", "navy")
                      .attr("class", "bar");
        };
    });    
  </script>
  <h1 class="title">Title Will Go Here</h1> 
</body>

1 Ответ

0 голосов
/ 05 февраля 2019

D3 теперь использует Promises вместо асинхронных обратных вызовов для загрузки данных.Обещания упрощают структуру асинхронного кода, особенно в современных браузерах, которые поддерживают асинхронность и ожидание.

Изменения в D3 5.0

Кроме того, вы правы в том, что ваш yScale сломан. Линейным масштабам нужен диапазон и домен, каждому из которых передается массив из 2 значений.

    const yScale = d3.scaleLinear()
      .range([h - padding, padding])
      .domain([0, d3.max(dataset, (d) => d[1])]);

    document.addEventListener('DOMContentLoaded', async function() {

      const res = await d3.json("https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json");

      //console.log(res.data)
      const dataset = res.data

      const w = 500;
      const h = 300;
      const padding = 10;

      // create an array with all date names
      const dates = dataset.map(function(d) {
        return d[0];
      });
      
      const max = d3.max(dataset, function(d) { return d[1]} )

      const xScale = d3.scaleBand()
        .rangeRound([0, w]) 
        .padding([.02])
        .domain(dates);
      console.log("Scale Bandwidth: " + xScale.bandwidth());

      const yScale = d3.scaleLinear()
        .range([h - padding, padding])
        .domain([0, d3.max(dataset, (d) => d[1])]);
      console.log("Dataset Max Height: " + d3.max(dataset, (d) => d[1]));

      const xAxis = d3.axisBottom(xScale);
      const yAxis = d3.axisLeft(yScale);

      const svg = d3.select("body")
        .append("svg")
        .attr("width", w)
        .attr("height", h);

      svg.append("g")
        .attr("transform", "translate(0," + (h - padding) + ")")
        .call(xAxis);
      svg.append("g")
        .attr("transform", "translate(" + padding + ",0)")
        .call(yAxis);

      svg.selectAll("rect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("width", (d, i) => xScale.bandwidth())
        .attr("height", (d, i) => (h - yScale(d[1])) )
        .attr("x", (d, i) => xScale(d[0]))
        .attr("y", (d, i) => yScale(d[1]))
        .attr("fill", "navy")
        .attr("class", "bar");

    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.8.0/d3.min.js"></script>

Codepen

...