Javascript 将数据值添加到D3.JS条形图中间或以上

Javascript 将数据值添加到D3.JS条形图中间或以上,javascript,csv,d3.js,charts,Javascript,Csv,D3.js,Charts,我正在尝试向d3.js条形图添加数据标签。每个栏应该有其数据标签在中间或以上。 例如,如果第一个条形图的值为730,则应显示730,依此类推 像这样: 可能吗 代码如下: <!DOCTYPE html> <head> <meta charset="utf-8"> <script src="../../d3.v4.min.js"></script> <style> body { font-family: Av

我正在尝试向d3.js条形图添加数据标签。每个栏应该有其数据标签在中间或以上。

例如,如果第一个条形图的值为730,则应显示730,依此类推

像这样:

可能吗

代码如下:

<!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 slider=document.getElementById(“sliderVal”);
var输出=document.getElementById(“maxVal”);
函数clearCanvas(){
d3.选择('svg').remove();
}
函数drawGraph(){//这需要整理,这样就不需要多次获取数据了!
//设置边距
var margin={顶部:60,右侧:100,底部:20,左侧:80},
宽度=550-margin.left-margin.right,
高度=370-margin.top-margin.bottom;
//解析month变量
var parseMonth=d3.timeParse(“%b”);
var formatMonth=d3.timeFormat(“%b”);
//设定范围
var x=d3.scaleBand().rangeRound([0,宽度])。填充(0.1)
变量y=d3.scaleLinear().range([height,0]);
//在“graph”div中创建svg画布
var svg=d3。选择(“图形”)
.append(“svg”)
.样式(“宽度”,宽度+边距。左侧+边距。右侧+“px”)
.样式(“高度”,高度+边距.顶部+边距.底部+“px”)
.attr(“宽度”,宽度+边距。左侧+边距。右侧)
.attr(“高度”,高度+边距。顶部+边距。底部)
.附加(“g”)
.attr(“转换”、“平移”(“+margin.left+”,“+margin.top+”)
.attr(“类”、“svg”);
//导入CSV数据
d3.csv(“https://raw.githubusercontent.com/rob360/x1/master/dataset_visits.csv,函数(错误,数据){
如果(错误)抛出错误;
//格式化数据
data.forEach(函数(d){
d、 月=月(d.月);
d、 S40401=+d.S40401;
d、 S40402=+d.S40402;
d、 S40403=+d.S40403;
});
var nest=[];//创建空数组
var keys=['S40401'、'S40402'、'S40403'];//数据的标题
//对于每个标题,将总和作为对象推送
键。forEach(函数(d,i){
//从数据中获取该键所有值的总和,即d
var sum=d3.sum(数据,函数(e){返回e[d]});
//使用此键值对创建对象
var obj={
键:d,//列名
值:sum//列的sum
}
push(obj);//将其作为嵌套数组中的对象推送
})
//缩放数据的范围
x、 域(nest.map(函数(d){return d.key;}));
y、 域([0,d3.max(嵌套,函数(d){返回d.value;})];
//检查200%的线是否在图表内
maxVal=+d3.select('#maxVal').text();
如果(maxVal*4.5>y.domain()[1]){
y、 域([0,maxVal*4.5*1.1]);
}
//设置x轴
var xaxis=svg.append(“g”)
.attr(“变换”、“平移(0)”、“高度+”)
.attr(“类”、“x轴”)
.call(d3.axisBottom(x)
//.滴答声(d3.时间月)
.tickSize(0,0)
//.tickFormat(d3.timeFormat(“%B”))
.tickSizeInner(0)
.1(10));
//添加Y轴
var yaxis=svg.append(“g”)
.attr(“类”、“y轴”)
.呼叫(d3.左(y)
.滴答声(5)
.tickSizeInner(0)
.1(6)
.tickSize(0,0));
svg.append(“文本”)
.attr(“变换”、“旋转(-90)”)
.attr(“y”,0-60)
.attr(“x”,0-(高度/2))
.attr(“dy”、“1em”)
.style(“文本锚定”、“中间”)
.文本(“访问”)
.attr(“类别”、“y轴标签”);
//划清界限
svg.selectAll(“.rect”)
.数据(嵌套)
.输入()
.append(“文本”)
.attr(“x”,函数(d){返回x(d.key)+3;})
.attr(“y”,函数(d){return(y(d.value));})//中心文本
.attr(“dy”、“1em”)
.text(函数(d){返回d.value;});
svg.selectAll(“.rect”)
.数据(嵌套)
.enter().append(“rect”)
.attr(“类”、“条”)
.attr(“x”,函数(d){console.log(d);返回x(d.key);})
.attr(“y”,函数(d){返回y(d.value);})
.attr(“宽度”,x.带宽())
.attr(“高度”,函数(d){返回高度-y(d.value);})
风险值阈值={
v0:maxVal*3,
v1:maxVal*4,
v2:maxVal*4.5
}
console.log(阈值);
//为第一个阈值画一条线
svg.append(“行”)
.style(“笔划”、“红色”)
.attr(“x1”,0)
.attr(“y1”,y(阈值.v0))
.attr(“x2”,宽度)
.attr(“y2”,y(阈值.v0));
//绘制第一个阈值的标签
svg.append(“文本”)
.attr(“类”、“我的文本”)
.attr(“x”,宽度+2)
.attr(“y”,y(阈值v0))
.attr(“主导基线”、“表意文字”)
.text(“0%≈ " + 阈值v0.toFixed(2));
//为第二个阈值画一条线
svg.append(“行”)
.style(“笔划”、“蓝色”)
.attr(“x1”,0)
.attr(“y1”,y(阈值.v1))
.attr(“x2”,宽度)
.attr(“y2”,y(阈值.v1));
//绘制第二个阈值的标签
svg.append(“文本”)
.attr(“类”、“我的文本”)
.attr(“x”,宽度+2)
.attr(“y”,y(阈值.v1))
.attr(“主导基线”、“表意文字”)
.text(“100%≈ “+阈值v1.toFixed(2));
//为第三个阈值画一条线
svg.append(“行”)
.style(“笔划”、“绿色”)
.attr(“x1”,0)
.attr(“y1”,y(阈值.v2))
.attr(“x2”,宽度)
.attr(“y2”,y(阈值v2));
//绘制第三个阈值的标签
svg.append(“文本”)
.attr(“类”、“我的文本”)
.attr(“x”,宽度+2)
.attr(“y”,y(阈值.v2))
.attr(“主导基线”、“表意文字”)
.text(“200%≈ “+threshol
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;});