Как создать оси axLeft c в D3. js - PullRequest
0 голосов
/ 07 января 2020

Я новичок в D3. js и создал график, который показывает историю продаж некоторых продавцов.

В таблице ниже показан общий результат продаж за год, диаграмма показывает месячную эволюцию продаж. Когда я нажимаю на таблицу и меняю продавца, график тоже меняется, но разница между значениями продаж очень велика для каждого продавца. Поскольку ось Y зафиксирована, когда я нажимаю на второго продавца, линии графика практически слипаются.

Может сказать мне, как я могу сделать динамику оси Y c, чтобы, когда я нажмите на второго продавца, максимальная продажная стоимость этого продавца отображается.

Я надеюсь, что смогу объяснить.

//#region Criando Tabela de Vendedores
var newMapVendedores = [{
    "vendnm": "CHARNECA",
    "Vendas_Ano": 236009.2299999998,
    "Vendas_Ant": 282753.77999999997
  },
  {
    "vendnm": "JOÃO LUIS",
    "Vendas_Ano": 57286.04999999996,
    "Vendas_Ant": 70260.31
  },
]

$(document).ready(function() {
  $("#tableVendedores").append('<tfoot><th></th><th></th><th></th></tfoot>');
  var table = $('#tableVendedores').DataTable({
    "data": newMapVendedores,
    "columns": [{
        "data": "vendnm",
        title: 'Vendedor'
      },
      {
        "data": "Vendas_Ano",
        title: 'Vendas Ano'
      },
      {
        "data": "Vendas_Ant",
        title: 'Vendas Ant'
      },
    ],
    "bLengthChange": false,
    "bPaginate": false,
    "bFilter": false,
    "info": false,
  });

  $('#tableVendedores').on('click', 'tr', function() {
    var data = table.row(this).data();
  });
});

//#endregion

//#region GRÁFICO         

var codes = ["VENDAS_ANO", "VENDAS_ANT"];
$('span.values').html(codes.join(', '));

modalitySelected = document.querySelector('input[name=modality-selector]:checked').value;

var data = null;
var filtered_data = null;

var margin = {
  top: 30,
  right: 20,
  bottom: 50,
  left: 50
};
var width = 600 - margin.left - margin.right;
var height = 300 - margin.top - margin.bottom;
var duration = 250;

var lineOpacity = "0.25";
var lineOpacityHover = "0.85";
var otherLinesOpacityHover = "0.1";
var lineStroke = "1.5px";
var lineStrokeHover = "2.5px";

var circleOpacity = '0.85';
var circleOpacityOnLineHover = "0.25";
var circleRadius = 3;
var circleRadiusHover = 6;

var month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

var x = d3.scaleBand().range([0, width]).domain(month).padding(1);
var y = d3.scaleLinear().range([height, 0]).domain([0, 65000]);

var color = d3.scaleOrdinal(d3.schemeCategory10);

var xAxis = d3.axisBottom(x).ticks(12);
var yAxis = d3.axisLeft(y);

var svg = d3.select("#line-chart-container")
  .append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.append("text")
  .attr("x", width / 2)
  .attr("y", 5)
  .style("text-anchor", "middle")
  .style("font-size", "16px")
  .text("Monthly Sales Evolution");
var g = null;

var line = d3.line()
  .x(function(d) {
    return x(d.month);
  })
  .y(function(d) {
    return y(d.value);
  });
// .curve(d3.curveBasis);

let lines = svg.append('g')
  .attr('class', 'lines');

var mouseG = svg.append("g") // this the black vertical line to folow mouse
  .attr("class", "mouse-over-effects");

mouseG.append("path")
  .attr("class", "mouse-line")
  .style("stroke", "black")
  .style("stroke-width", "1px")
  .style("opacity", "0");

// get data
d3.queue()
  .defer(d3.json, 'http://www.json-generator.com/api/json/get/cjsmAgXIVu?indent=2')
  .await(makeLineChart);

function makeLineChart(error, data) {

  if (error) {
    console.log(error);
  }

  color.domain(d3.keys(data[0])
    .filter(function(key) {
      return key == "CODE";
    })
  );

  createAxis();
  updateChart(data);

  // radio button change
  d3.selectAll("input[name='modality-selector']")
    .on("change", function() {
      modalitySelected = document.querySelector('input[name=modality-selector]:checked').value;
      clearChart();
      createAxis();
      updateChart(data);
    });

} // end makeLineChart function

/**
 * Create (if is the firts time) or updates the line chart, 
 * based on radio button selection.
 */
function updateChart(data) {

  // filter data
  filtered_data = data.filter(function(d) {
    return d.MODALITY == modalitySelected && codes.includes(d.CODE);
  });

  // first we need to corerce the data into the right formats
  filtered_data = filtered_data.map(function(d) {
    return {
      code: d.CODE,
      month: d.MONTH,
      modality: d.MODALITY,
      value: +d.VALUE
    };
  });

  filtered_data = d3.nest()
    .key(function(d) {
      return d.code;
    })
    .entries(filtered_data);

  var codesArray = svg.selectAll(".code")
    .data(filtered_data, function(d) {
      return d.key;
    })
    .enter()
    .append("g")
    .attr("class", "code")
    .on("mouseover", function(d, i) {
      codesArray.append("text")
        .attr("class", "title-text")
        .style("fill", color(d.key))
        .text('')
        .attr("text-anchor", "middle")
        .attr("x", 200)
        .attr("y", 20);
    })
    .on("mouseout", function(d) {
      codesArray.select(".title-text").remove();
    })

  codesArray.append("path")
    .attr("class", "line")
    .attr("d", function(d) {
      // console.log(d)
      return line(d.values);
    })
    .style("stroke", function(d) {
      return color(d.key);
    })
    .style('opacity', lineOpacity)

  /* Add circles in the line */
  codesArray.selectAll("circle-group")
    .data(filtered_data, function(d) {
      return d.key;
    })
    .enter()
    .append("g")
    .style("fill", function(d, i) {
      return color(d.key);
    })
    .selectAll("circle")
    .data(d => d.values).enter()
    .append("g")
    .attr("class", "circle")
    .append("circle")
    .attr("cx", function(d) {
      return x(d.month)
    })
    .attr("cy", d => y(d.value))
    .attr("r", circleRadius)
    .style('opacity', circleOpacity)

}

function createAxis() {

  g = svg.append("g")
    .attr("class", "chartGroup")

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

  g.append("g")
    .attr("class", "axis y")
    .call(yAxis);
}

/**
 * Remove old chart (axis and lines).
 */
function clearChart() {
  d3.select(".chartGroup").remove();
  d3.selectAll(".code").remove();
}
<head>
  <meta charset="utf-8">
  <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.css">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

  <script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
  <script src='https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
  <script src="https://d3js.org/topojson.v2.min.js"></script>
  <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.js"></script>
  <title>Index 9</title>
</head>

<style>
  svg {
    font-family: Sans-Serif, Arial;
  }
  
  .line {
    stroke-width: 1.5;
    fill: none;
  }
  
  .axis path {
    stroke: black;
  }
  
  .text {
    font-size: 12px;
  }
  
  .title-text {
    font-size: 12px;
  }
  
  table {
    font-family: Arial, Helvetica, sans-serif;
    border-collapse: collapse;
    font-size: 12px !important;
    margin-left: 10px;
    margin-top: 10px;
    /* width: 300px !important; */
  }
  
  .table td {
    padding: .0rem;
  }
  
  tr {
    line-height: 25px;
  }
  
  .axis path,
  .axis line {
    fill: none;
    stroke: grey;
    stroke-width: 1;
    shape-rendering: crispEdges;
  }
  
  th,
  td {
    border: 1px solid #cccccc;
    padding: 0px;
    text-align: center;
  }
  
  input {
    visibility: hidden;
  }
  
  label {
    cursor: pointer;
    margin-bottom: .0rem;
  }
  
  hr {
    margin-top: -5px;
    border-width: 1px;
    border-color: black;
  }
</style>

<body>

  <div style="width: 600px; margin-left: 10px;">
    <div id="line-chart-container"></div>
    <hr>
    <div style="width: 600px;" id="modality-selector-container">
      <form id="modality-selector">
        <div class="row table">
          <div class="col-6">
            <h7 style="margin-left: 10px;">Sales</h7>
            <table id="tableSales" class="table table-hover">
              <thead>
                <tr>
                  <th>Sale</th>
                  <th>Current Year</th>
                  <th>Last Year</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td>
                    <input type="radio" name="modality-selector" id="rb-charneca" value="charneca" checked />
                    <label for="rb-charneca">CHARNECA</label>
                  </td>
                  <td>236.009,23</td>
                  <td>282.753,78</td>
                </tr>
                <tr>
                  <td>
                    <input type="radio" name="modality-selector" id="rb-loule" value="loule" />
                    <label for="rb-loule">JOÃO LUIS</label>
                  </td>
                  <td>57.286,14</td>
                  <td>70.260,50</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </form>
    </div>
  </div>
</body>

Большое спасибо заранее.

1 Ответ

0 голосов
/ 07 января 2020

.domain([min, max]) используется для определения диапазона для каждой оси. В вашем случае он был установлен один раз на [0..65000]. Вам нужно обновлять его каждый раз при обновлении графика.

Это строки, которые я добавил к вам updateChart() функция:

  filtered_data_values = filtered_data.map(function(d) {
    return +d.value;
  });
  y.domain([0, Math.max(...filtered_data_values)]);

//#region Criando Tabela de Vendedores
var newMapVendedores = [{
    "vendnm": "CHARNECA",
    "Vendas_Ano": 236009.2299999998,
    "Vendas_Ant": 282753.77999999997
  },
  {
    "vendnm": "JOÃO LUIS",
    "Vendas_Ano": 57286.04999999996,
    "Vendas_Ant": 70260.31
  },
]

$(document).ready(function() {
  $("#tableVendedores").append('<tfoot><th></th><th></th><th></th></tfoot>');
  var table = $('#tableVendedores').DataTable({
    "data": newMapVendedores,
    "columns": [{
        "data": "vendnm",
        title: 'Vendedor'
      },
      {
        "data": "Vendas_Ano",
        title: 'Vendas Ano'
      },
      {
        "data": "Vendas_Ant",
        title: 'Vendas Ant'
      },
    ],
    "bLengthChange": false,
    "bPaginate": false,
    "bFilter": false,
    "info": false,
  });

  $('#tableVendedores').on('click', 'tr', function() {
    var data = table.row(this).data();
  });
});

//#endregion

//#region GRÁFICO         

var codes = ["VENDAS_ANO", "VENDAS_ANT"];
$('span.values').html(codes.join(', '));

modalitySelected = document.querySelector('input[name=modality-selector]:checked').value;

var data = null;
var filtered_data = null;

var margin = {
  top: 30,
  right: 20,
  bottom: 50,
  left: 50
};
var width = 600 - margin.left - margin.right;
var height = 300 - margin.top - margin.bottom;
var duration = 250;

var lineOpacity = "0.25";
var lineOpacityHover = "0.85";
var otherLinesOpacityHover = "0.1";
var lineStroke = "1.5px";
var lineStrokeHover = "2.5px";

var circleOpacity = '0.85';
var circleOpacityOnLineHover = "0.25";
var circleRadius = 3;
var circleRadiusHover = 6;

var month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

var x = d3.scaleBand().range([0, width]).domain(month).padding(1);
var y = d3.scaleLinear().range([height, 0]).domain([0, 65000]);

var color = d3.scaleOrdinal(d3.schemeCategory10);

var xAxis = d3.axisBottom(x).ticks(12);
var yAxis = d3.axisLeft(y);

var svg = d3.select("#line-chart-container")
  .append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.append("text")
  .attr("x", width / 2)
  .attr("y", 5)
  .style("text-anchor", "middle")
  .style("font-size", "16px")
  .text("Monthly Sales Evolution");
var g = null;

var line = d3.line()
  .x(function(d) {
    return x(d.month);
  })
  .y(function(d) {
    return y(d.value);
  });
// .curve(d3.curveBasis);

let lines = svg.append('g')
  .attr('class', 'lines');

var mouseG = svg.append("g") // this the black vertical line to folow mouse
  .attr("class", "mouse-over-effects");

mouseG.append("path")
  .attr("class", "mouse-line")
  .style("stroke", "black")
  .style("stroke-width", "1px")
  .style("opacity", "0");

// get data
d3.queue()
  .defer(d3.json, 'http://www.json-generator.com/api/json/get/cjsmAgXIVu?indent=2')
  .await(makeLineChart);

function makeLineChart(error, data) {

  if (error) {
    console.log(error);
  }

  color.domain(d3.keys(data[0])
    .filter(function(key) {
      return key == "CODE";
    })
  );

  createAxis();
  updateChart(data);

  // radio button change
  d3.selectAll("input[name='modality-selector']")
    .on("change", function() {
      modalitySelected = document.querySelector('input[name=modality-selector]:checked').value;
      clearChart();
      createAxis();
      updateChart(data);
    });

} // end makeLineChart function

/**
 * Create (if is the firts time) or updates the line chart, 
 * based on radio button selection.
 */
function updateChart(data) {

  // filter data
  filtered_data = data.filter(function(d) {
    return d.MODALITY == modalitySelected && codes.includes(d.CODE);
  });

  // first we need to corerce the data into the right formats
  filtered_data = filtered_data.map(function(d) {
    return {
      code: d.CODE,
      month: d.MONTH,
      modality: d.MODALITY,
      value: +d.VALUE
    };
  });

  filtered_data_values = filtered_data.map(function(d) {
    return +d.value;
  });
  y.domain([0, Math.max(...filtered_data_values)]);

  filtered_data = d3.nest()
    .key(function(d) {
      return d.code;
    })
    .entries(filtered_data);

  var codesArray = svg.selectAll(".code")
    .data(filtered_data, function(d) {
      return d.key;
    })
    .enter()
    .append("g")
    .attr("class", "code")
    .on("mouseover", function(d, i) {
      codesArray.append("text")
        .attr("class", "title-text")
        .style("fill", color(d.key))
        .text('')
        .attr("text-anchor", "middle")
        .attr("x", 200)
        .attr("y", 20);
    })
    .on("mouseout", function(d) {
      codesArray.select(".title-text").remove();
    })

  codesArray.append("path")
    .attr("class", "line")
    .attr("d", function(d) {
      // console.log(d)
      return line(d.values);
    })
    .style("stroke", function(d) {
      return color(d.key);
    })
    .style('opacity', lineOpacity)

  /* Add circles in the line */
  codesArray.selectAll("circle-group")
    .data(filtered_data, function(d) {
      return d.key;
    })
    .enter()
    .append("g")
    .style("fill", function(d, i) {
      return color(d.key);
    })
    .selectAll("circle")
    .data(d => d.values).enter()
    .append("g")
    .attr("class", "circle")
    .append("circle")
    .attr("cx", function(d) {
      return x(d.month)
    })
    .attr("cy", d => y(d.value))
    .attr("r", circleRadius)
    .style('opacity', circleOpacity)

}

function createAxis() {

  g = svg.append("g")
    .attr("class", "chartGroup")

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

  g.append("g")
    .attr("class", "axis y")
    .call(yAxis);
}

/**
 * Remove old chart (axis and lines).
 */
function clearChart() {
  d3.select(".chartGroup").remove();
  d3.selectAll(".code").remove();
}
<head>
  <meta charset="utf-8">
  <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.css">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

  <script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
  <script src='https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
  <script src="https://d3js.org/topojson.v2.min.js"></script>
  <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.js"></script>
  <title>Index 9</title>
</head>

<style>
  svg {
    font-family: Sans-Serif, Arial;
  }
  
  .line {
    stroke-width: 1.5;
    fill: none;
  }
  
  .axis path {
    stroke: black;
  }
  
  .text {
    font-size: 12px;
  }
  
  .title-text {
    font-size: 12px;
  }
  
  table {
    font-family: Arial, Helvetica, sans-serif;
    border-collapse: collapse;
    font-size: 12px !important;
    margin-left: 10px;
    margin-top: 10px;
    /* width: 300px !important; */
  }
  
  .table td {
    padding: .0rem;
  }
  
  tr {
    line-height: 25px;
  }
  
  .axis path,
  .axis line {
    fill: none;
    stroke: grey;
    stroke-width: 1;
    shape-rendering: crispEdges;
  }
  
  th,
  td {
    border: 1px solid #cccccc;
    padding: 0px;
    text-align: center;
  }
  
  input {
    visibility: hidden;
  }
  
  label {
    cursor: pointer;
    margin-bottom: .0rem;
  }
  
  hr {
    margin-top: -5px;
    border-width: 1px;
    border-color: black;
  }
</style>

<body>

  <div style="width: 600px; margin-left: 10px;">
    <div id="line-chart-container"></div>
    <hr>
    <div style="width: 600px;" id="modality-selector-container">
      <form id="modality-selector">
        <div class="row table">
          <div class="col-6">
            <h7 style="margin-left: 10px;">Sales</h7>
            <table id="tableSales" class="table table-hover">
              <thead>
                <tr>
                  <th>Sale</th>
                  <th>Current Year</th>
                  <th>Last Year</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td>
                    <input type="radio" name="modality-selector" id="rb-charneca" value="charneca" checked />
                    <label for="rb-charneca">CHARNECA</label>
                  </td>
                  <td>236.009,23</td>
                  <td>282.753,78</td>
                </tr>
                <tr>
                  <td>
                    <input type="radio" name="modality-selector" id="rb-loule" value="loule" />
                    <label for="rb-loule">JOÃO LUIS</label>
                  </td>
                  <td>57.286,14</td>
                  <td>70.260,50</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </form>
    </div>
  </div>
</body>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...