Добавьте значения данных на гистограмму D3.js в середине или выше - PullRequest
0 голосов
/ 07 ноября 2019

Я пытаюсь добавить метки данных на гистограмму d3.js. Каждый столбец должен иметь свои метки данных либо посередине, либо выше.

Например, первый столбец должен отображать 730, если его значение равно 730 и т. Д. *

Вот так:

enter image description here

Возможно ли это?

Это код:

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="../../d3.v4.min.js"></script>
  <style>
body {
  font-family: Avenir, Helvetica, sans-serif;
  font-size: 12px;
  width: 530px;
  margin: 10px auto;
}
.bar {
  fill: orange;
  opacity: 0.7;
}
.myText {
  font-family: "Helvetica";
  font-size: 10px;
}

.slidecontainer {
  padding: 10px;
  width: 50%; /* Width of the outside container */
}

/* The slider itself */
.slider {
  -webkit-appearance: none; /* Override default CSS styles */
  appearance: none;
  width: 50%; /* Full-width */
  height: 25px; /* Specified height */
  background: #d3d3d3; /* Grey background */
  outline: none; /* Remove outline */
  opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */
  -webkit-transition: 0.2s; /* 0.2 seconds transition on hover */
  transition: opacity 0.2s;
  vertical-align: middle;
}

/* Mouse-over effects */
.slider:hover {
  opacity: 1; /* Fully shown on mouse-over */
}

/* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */
.slider::-webkit-slider-thumb {
  -webkit-appearance: none; /* Override default look */
  appearance: none;
  width: 25px; /* Set a specific slider handle width */
  height: 25px; /* Slider handle height */
  background: #4caf50; /* Green background */
  cursor: pointer; /* Cursor on hover */
}

.slider::-moz-range-thumb {
  width: 25px; /* Set a specific slider handle width */
  height: 25px; /* Slider handle height */
  background: #4caf50; /* Green background */
  cursor: pointer; /* Cursor on hover */
}
  </style>
</head>

<body>
  <div class="slidecontainer">
    0 <input type="range" min="1" max="163" value="163" class="slider" id="sliderVal"> 163
    <p>Threshold Line Value: <span id="maxVal"></span></p>
  </div>
  <div id="graph"></div>

<script>
var slider = document.getElementById("sliderVal");
var output = document.getElementById("maxVal");

function clearCanvas() {
  d3.select('svg').remove();
}

function drawGraph() { // this needs tidying up so you don't need to get data more than once!

    // Set the margins
  var margin = {top: 60, right: 100, bottom: 20, left: 80},
    width = 550 - margin.left - margin.right,
    height = 370 - margin.top - margin.bottom;

  // Parse the month variable
  var parseMonth = d3.timeParse("%b");
  var formatMonth = d3.timeFormat("%b");

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


  // Create the svg canvas in the "graph" div
  var svg = d3.select("#graph")
          .append("svg")
          .style("width", width + margin.left + margin.right + "px")
          .style("height", height + margin.top + margin.bottom + "px")
          .attr("width", width + margin.left + margin.right)
          .attr("height", height + margin.top + margin.bottom)
          .append("g")
          .attr("transform","translate(" + margin.left + "," + margin.top + ")")
          .attr("class", "svg");

  // Import the CSV data
  d3.csv("../dataset_visits.csv", function(error, data) {
    if (error) throw error;

     // Format the data
    data.forEach(function(d) {
        d.Month = parseMonth(d.Month);
        d.S40411 = +d.S40411;
        d.S40412 = +d.S40412;
        d.S40413 = +d.S40413;
        d.S40414 = +d.S40414;
    });

  var nest = [];//create empty array
  var keys = ['S40411','S40412','S40413','S40414']; //the headers for your data
  //for each header push the sum as an object
  keys.forEach(function (d, i) {
    //get the sumfrom your data for all the values of this key i.e. d
    var sum = d3.sum (data, function(e){ return e[d] }); 
    //create an object with this key value pair
    var obj = {
      key: d, //column name
      value: sum //sum for the column
    }
    nest.push(obj); //push this as an object in the nest array
  })

  console.log(nest)
    // Scale the range of the data
    x.domain(nest.map(function(d) { return d.key; }));
    y.domain([0, d3.max(nest, function(d) { return d.value; })]);

    // check that 200% line will be within chart
    maxVal = +d3.select('#maxVal').text();
    if ( maxVal * 4.5 > y.domain()[1]) {
      y.domain([0,maxVal*4.5*1.1]);
    }

    // Set up the x axis
    var xaxis = svg.append("g")
         .attr("transform", "translate(0," + height + ")")
         .attr("class", "x axis")
         .call(d3.axisBottom(x)
            //.ticks(d3.timeMonth)
            .tickSize(0, 0)
            //.tickFormat(d3.timeFormat("%B"))
            .tickSizeInner(0)
            .tickPadding(10));

    // Add the Y Axis
     var yaxis = svg.append("g")
         .attr("class", "y axis")
         .call(d3.axisLeft(y)
            .ticks(5)
            .tickSizeInner(0)
            .tickPadding(6)
            .tickSize(0, 0));

   // yaxis.select(".domain").style("display","none")

    // Add a label to the y axis
    svg.append("text")
          .attr("transform", "rotate(-90)")
          .attr("y", 0 - 60)
          .attr("x", 0 - (height / 2))
          .attr("dy", "1em")
          .style("text-anchor", "middle")
          .text("Visits")
          .attr("class", "y axis label");

    // Draw the bars
    svg.selectAll(".rect")
        .data(nest)
        .enter()
        .append("rect")
            .attr("class", "bar")
            .attr("x", function(d) { return x(d.key); })
            .attr("y", function(d) { return y(d.value); })
            .attr("width", x.bandwidth())
            .attr("height", function(d) { return height - y(d.value); });

    // Three lines and labels for the thresholds 0%, 100%, 200% target achievement -->

    var thresholds = {
      v0: maxVal*3,
      v1: maxVal*4,
      v2: maxVal*4.5
    }
    console.log(thresholds);
    // Draw the line for the first threshold
    svg.append("line")
      .style("stroke", "red")
        .attr("x1", 0)
        .attr("y1", y(thresholds.v0))
        .attr("x2", width)
        .attr("y2", y(thresholds.v0));

    // Draw the label for the first threshold
    svg.append("text")
      .attr("class", "myText")
      .attr("x", width + 2)
        .attr("y", y(thresholds.v0))
        .attr("dominant-baseline", "ideographic")
        .text("0% ≈ " + thresholds.v0.toFixed(2));

    // Draw the line for the second threshold
    svg.append("line")
      .style("stroke", "blue")
        .attr("x1", 0)
        .attr("y1", y(thresholds.v1))
        .attr("x2", width)
        .attr("y2", y(thresholds.v1));

    // Draw the label for the second threshold
    svg.append("text")
      .attr("class", "myText")
      .attr("x", width + 2)
        .attr("y", y(thresholds.v1))
        .attr("dominant-baseline", "ideographic")
        .text("100% ≈ " + thresholds.v1.toFixed(2));
    // Draw the line for the third threshold
    svg.append("line")
      .style("stroke", "green")
        .attr("x1", 0)
        .attr("y1", y(thresholds.v2))
        .attr("x2", width)
        .attr("y2", y(thresholds.v2));

    // Draw the label for the third threshold
    svg.append("text")
      .attr("class", "myText")
      .attr("x", width + 2)
        .attr("y", y(thresholds.v2))
        .attr("dominant-baseline", "ideographic")
        .text("200% ≈ " + thresholds.v2.toFixed(2));

  })
}

// Update the current slider value (each time you drag the slider handle)
slider.oninput = function() {
  clearCanvas();
  output.innerHTML = this.value;
  drawGraph();
}

// initial call

output.innerHTML = slider.value;
drawGraph();
</script>

</body>

Каждая строка должна отображать своюзначение в баре или выше.

Существует еще одна запись , которая претендует на то, чтобы решить эту проблему. В их скрипке он отлично работает!

Я пытаюсь адаптировать и вставить этот код, но он не работает:

var text = chart.selectAll(".text")
    .data(data)
  .enter()
  .append("text")
    .attr("class","text");

var labels = text.attr("x", function (d) {
        return xScale(d.year) + xScale.rangeBand()/2;
    })
    .attr("y", function (d) {return yScale(d.tickets);})
    .text(function (d) { return d.tickets;});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...