Я пытаюсь добавить метки данных на гистограмму 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 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;});