简体   繁体   中英

d3 v4 axis not updating

I'm currently making a simple line chart that updates its values based on a series of input forms.

I can create and render the chart correctly, and can update the line upon user input, however my axis labels aren't updating in turn. I've tried following a few other examples here but to no avail, can someone please help me in fixing my updateData() function to update the axis labels in my code?

jsfiddle - https://jsfiddle.net/quirkules/0xktoLj7/1/

  //****** CREATE CHART ******

  //collect data from input fields
  var data = [];
  for (var i = 0; i < 10; i++) {
    data.push({
      x: d3.select('#cadenceThroughputData' + i).select('input').property('value'),
      y: d3.select('#cadenceLengthData' + i).select('input').property('value'),
    });
  }

  // set the dimensions and margins of the graph
  var margin = {top: 20, right: 20, bottom: 30, left: 50},
      width = d3.select('#output-chart').node().getBoundingClientRect().width - margin.left - margin.right,
      height = d3.select('#output-chart').node().getBoundingClientRect().height - margin.top - margin.bottom;

  // set the ranges
  var x = d3.scaleLinear().range([0, width]);
  var y = d3.scaleLinear().range([height, 0]);

  var x_axis = d3.axisBottom().scale(x);
  var y_axis = d3.axisLeft().scale(y);

  // define the line
  var valueline = d3.line()
    .x(d => { return x(d.x); })
    .y(d => { return y(d.y); });

  // append the svg obgect to the body of the page
  // appends a 'group' element to 'svg'
  // moves the 'group' element to the top left margin
  var svg = d3.select("#output-chart")
      .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 + ")");

  // format the data
  data.forEach(function(d) {
      d.x = +d.x;
      d.y = +d.y;
  });

  // Scale the range of the data
  x.domain([0, d3.max(data, d => { return d.x; })]);
  y.domain([0, d3.max(data, d => { return d.y; })]);

  // Add the valueline path.
  svg.append("path")
      .data([data])
      .attr("class", "line")
      .attr("d", valueline);

  // Add the X Axis
  svg.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(x_axis);

  // Add the Y Axis
  svg.append("g")
      .call(y_axis);

  function updataData(){
    //collect data from input fields again
    var data = [];
    for (var i = 0; i < 10; i++) {
      data.push({
        x: d3.select('#cadenceThroughputData' + i).select('input').property('value'),
        y: d3.select('#cadenceLengthData' + i).select('input').property('value'),
      });
    }

    // format the data
    data.forEach(function(d) {
        d.x = +d.x;
        d.y = +d.y;
    });

    // Scale the range of the data again
    x.domain([0, d3.max(data, d => { return d.x; })]);
    y.domain([0, d3.max(data, d => { return d.y; })]);

    // Select the section we want to apply our changes to
    var svg = d3.select("#output-chart").transition();

    // Make the changes
    // change the line
    svg.select(".line")
      .duration(750)
      .attr("d", valueline(data));
    // change the x axis
    svg.select(".x") 
      .duration(750)
      .call(x_axis);
    // change the y axis
    svg.select(".y") 
      .duration(750)
      .call(y_axis);
  }

  //****** END CREATE CHART ******

Minor changes:

Solution for the main issue ie axes not updating => You're calling select('.x') but you missed adding the classes while creating x and y axis.

    svg.append("g").attr('class', 'x')....


    svg.append("g").attr('class', 'y')...

Some additions to the code (maybe you can term them as my suggestions):

  1. Usually a line chart is just a simple line with no filled area shown. To do that, here's the change (to the path append) or you can add CSS:

     .style('fill', 'none') .style('stroke', '#000') 
  2. The .header doesn't need any padding. It looks messed up when resized. Removed .header { /* padding: 20px 0px 20px 0px; */ } .header { /* padding: 20px 0px 20px 0px; */ }

  3. Maybe you missed this but the y column input doesn't call updateData() on change.

     d3.select('#input-cadenceLengthData') ... .append('input') .on('input', updataData) 

Putting together all of the above, here's a fiddle: https://jsfiddle.net/nq1rfy7c/

Snippet:

  //****** SETUP DIVS ****** // Add the divs to the DOM $(document.body) .append('<div id="global-header"></div>') .append('<div id="input-cadenceSelect"></div>') .append('<div id="input-cadenceThroughputHeader"></div>') .append('<div id="input-cadenceLengthHeader"></div>') .append('<div id="input-cadenceType"></div>') .append('<div id="input-cadenceThroughputData"></div>') .append('<div id="input-cadenceLengthData"></div>') .append('<div id="output-chart"></div>') .append('<div id="output-summary"></div>') .append('<div id="global-footer"></div>'); //add text to #input-cadenceThroughputHeader d3.select('#input-cadenceThroughputHeader') .append('label') .text('X Value'); d3.select('#input-cadenceLengthHeader') .append('label') .text('Y Value'); for (var i = 0; i < 10; i++) { //add 10 #cadenceType divs to #input-cadenceType d3.select('#input-cadenceType') .append('div') .attr('class', 'header') .attr('id', 'cadenceType' + i) .style('position', 'absolute') .style('top', (i * 10) + '%') .style('width', '100%') .style('height', '10%') .style('display', 'table') .style('background', bandColour(i)) .append('label') .text((i + 1)); //add 10 #cadenceData divs to #input-cadenceData d3.select('#input-cadenceThroughputData') .append('div') .attr('id', 'cadenceThroughputData' + i) .style('position', 'absolute') .style('top', (i * 10) + '%') .style('width', '100%') .style('height', '10%') .style('background', bandColour(i)) .append('input') .on('input', updataData) .attr('size', '6') .attr('maxlength', '4') .style('height', '20px') .style('background', bandColour(i)) .attr('value', parseInt(Math.random() * 100)); //add 10 #cadenceLength divs to #input-cadenceLength d3.select('#input-cadenceLengthData') .append('div') .attr('id', 'cadenceLengthData' + i) .style('position', 'absolute') .style('top', (i * 10) + '%') .style('width', '100%') .style('height', '10%') .style('background', bandColour(i)) .append('input') .attr('size', '6') .attr('maxlength', '4') .style('height', '20px') .style('background', bandColour(i)) .on('input', updataData) .attr('value', parseInt(Math.random() * 10)); } function bandColour(i) { if (i % 2 > 0) { return '#333'; } else { return '#171213'; } } //****** END SETUP DIVS ****** //****** CREATE CHART ****** //collect data from input fields var data = []; for (var i = 0; i < 10; i++) { data.push({ x: d3.select('#cadenceThroughputData' + i).select('input').property('value'), y: d3.select('#cadenceLengthData' + i).select('input').property('value'), }); } // set the dimensions and margins of the graph var margin = { top: 20, right: 20, bottom: 30, left: 50 }, width = d3.select('#output-chart').node().getBoundingClientRect().width - margin.left - margin.right, height = d3.select('#output-chart').node().getBoundingClientRect().height - margin.top - margin.bottom; // set the ranges var x = d3.scaleLinear().range([0, width]); var y = d3.scaleLinear().range([height, 0]); var x_axis = d3.axisBottom().scale(x); var y_axis = d3.axisLeft().scale(y); // define the line var valueline = d3.line() .x(d => { return x(dx); }) .y(d => { return y(dy); }); // append the svg obgect to the body of the page // appends a 'group' element to 'svg' // moves the 'group' element to the top left margin var svg = d3.select("#output-chart") .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 + ")"); // format the data data.forEach(function(d) { dx = +dx; dy = +dy; }); // Scale the range of the data x.domain([0, d3.max(data, d => { return dx; })]); y.domain([0, d3.max(data, d => { return dy; })]); // Add the valueline path. svg.append("path") .data([data]) .attr("class", "line") .style('fill', 'none') .style('stroke', '#000') .attr("d", valueline); // Add the X Axis svg.append("g").attr('class', 'x') .attr("transform", "translate(0," + height + ")") .call(x_axis); // Add the Y Axis svg.append("g").attr('class', 'y') .call(y_axis); function updataData() { //collect data from input fields again var data = []; for (var i = 0; i < 10; i++) { data.push({ x: d3.select('#cadenceThroughputData' + i).select('input').property('value'), y: d3.select('#cadenceLengthData' + i).select('input').property('value'), }); } // format the data data.forEach(function(d) { dx = +dx; dy = +dy; }); x_axis = d3.axisBottom().scale(x); y_axis = d3.axisLeft().scale(y); // Scale the range of the data again x.domain([0, d3.max(data, d => { return dx; })]); y.domain([0, d3.max(data, d => { return dy; })]); // Select the section we want to apply our changes to var svg = d3.select("#output-chart").transition(); // Make the changes // change the line svg.select(".line") .duration(750) .attr("d", valueline(data)); // change the x axis svg.select(".x") .duration(750) .call(x_axis); // change the y axis svg.select(".y") .duration(750) .call(y_axis); } //****** END CREATE CHART ****** 
 body { font-family: sans-serif; color: white; background: #171213; } label { display: block; } input, textarea { color: white; font-size: 18px; font-weight: bold; text-align: center; border: 2px solid transparent; } #global-header { position: fixed; left: 0px; top: 0px; height: 5%; width: 100%; padding: 10px; box-sizing: border-box; text-align: center; font-size: 1.5em; font-family: Helvetica; color: white; } .header { color: #009DE0; font-size: 18px; font-weight: bold; text-align: center; display: table-cell; vertical-align: middle; /* padding: 20px 0px 20px 0px; */ } #input-cadenceType { position: fixed; box-sizing: border-box; border-left: 2px solid #009DE0; border-top: 2px solid #009DE0; border-bottom: 2px solid #009DE0; margin-left: 0%; top: 25%; width: 10%; height: 73%; } #input-cadenceThroughputHeader { position: fixed; color: #009DE0; font-size: 12px; font-weight: bold; text-align: center; box-sizing: border-box; border-left: 2px solid #009DE0; border-top: 2px solid #009DE0; margin-left: 10%; top: 20%; width: 10%; height: 5%; text-align: center; } #input-cadenceLengthHeader { position: fixed; color: #009DE0; font-size: 12px; font-weight: bold; text-align: center; box-sizing: border-box; border-left: 2px solid #009DE0; border-top: 2px solid #009DE0; margin-left: 20%; top: 20%; width: 10%; height: 5%; text-align: center; } #input-cadenceThroughputData { position: fixed; box-sizing: border-box; border-top: 2px solid #009DE0; border-left: 2px solid #009DE0; border-bottom: 2px solid #009DE0; margin-left: 10%; top: 25%; width: 10%; height: 73%; } #input-cadenceLengthData { position: fixed; box-sizing: border-box; border-top: 2px solid #009DE0; border-left: 2px solid #009DE0; border-bottom: 2px solid #009DE0; margin-left: 20%; top: 25%; width: 10%; height: 73%; } #input-simConstraint { position: fixed; margin-left: 30%; top: 5%; width: 35%; height: 20%; background: aqua; text-align: right; } #input-simDataHeader { position: fixed; margin-left: 65%; top: 5%; width: 35%; height: 5%; background: orange; text-align: center; } #input-simDataNoStoriesHeader { position: fixed; margin-left: 65%; top: 10%; width: 11.67%; height: 5%; background: green; text-align: center; } #input-simDataFocusHeader { position: fixed; margin-left: 76.67%; top: 10%; width: 11.67%; height: 5%; background: silver; text-align: center; } #input-simDataLengthHeader { position: fixed; margin-left: 88.34%; top: 10%; width: 11.67%; height: 5%; background: goldenrod; text-align: center; } #input-simDataNoStoriesValue { position: fixed; margin-left: 65%; top: 15%; width: 11.67%; height: 5%; background: pink; text-align: center; } #input-simDataFocusValue { position: fixed; margin-left: 76.67%; top: 15%; width: 11.67%; height: 5%; background: navy; text-align: center; } #output-chart { position: fixed; margin-left: 30%; top: 20%; width: 70%; height: 58%; background: red; text-align: right; } #global-footer { position: fixed; background: #171213; left: 0px; bottom: 0px; height: 2%; width: 100%; vertical-align: middle; text-align: right; font-size: 0.75em; font-family: Helvetica; color: white; } 
 <script src="https://d3js.org/d3.v4.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> 

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM