Hayden Allocca Hayden Allocca - 1 month ago 6
ASP.NET (C#) Question

d3 v4 how to add data labels to bar graph

i am working on a d3 graph and i can't seem to get the labels to position onto its corresponding bar in a bar graph. I am using d3 v4.


this is the desired outcome, the y positioning is ideal in my example however the x position will not move and the data labels are all stuck to the left

<!-- Wrap these elements in the necessary html and bootstrap classes to achieve the desired layout as depicted in the Assignment instructions -->
<div class="flex col-md-2" id="table">
<h2>Annual Sightings Table</h2>
<div class="flex-container" data-ng-app="UFOSightingsApp">
<div class="row">
<div data-ng-controller="UFOSightingsController">
<table class="table table-hover">
<th>Sighting Count</th>
<tr data-ng-repeat="s in sightings">



<div class="flex col-md-8 col-md-offset-2" id="graph">
<h2>Annual Sightings Graph</h2>
<svg width="100%" height="600px" style="border: 1px solid #000">

<script src="Scripts/d3/d3.js"></script>

var app = angular.module("UFOSightingsApp", []);

app.controller("UFOSightingsController", function ($scope, $http) {

$http.get("/api/UFOSightings").success(function (data) {
$scope.sightings = data;


var svg = d3.select("svg");

var svgWidth = svg.style("width");
var svgHeight = svg.style("height");
var width = svgWidth.substring(0, svgWidth.length - 2) - 0;
var height = svgHeight.substring(0, svgHeight.length - 2) - 65;

var xScale = d3.scaleBand()
.range([0, width])

var yScale = d3.scaleLinear()
.range([height, 0]);

var xAxis = d3.axisBottom()

var yAxis = d3.axisLeft()

d3.json("SightingData.json", function (error, data) {

if (error) throw error;

data.forEach(function (d) {
d.sightingCount = +d.sightingCount;
d.sightingYear = d.sightingYear;

xScale.domain(data.map(function (d) { return d.sightingYear; }));
yScale.domain([0, d3.max(data, function (d) { return d.sightingCount; })]);

//draw the bars
.attr("class", "bar")
.attr("x", function (d) { return xScale(d.sightingYear); })
.attr("width", xScale.bandwidth() - 2)
.attr("y", function (d) { return yScale(d.sightingCount); })
.attr("height", function (d) { return height - yScale(d.sightingCount); });

//label the bars
.text(function (d) { return d.sightingCount; })
.attr("x", function (d) { return xScale(d.sightingYear) + xScale.range() / 2; })
.attr("y", function (d) { return yScale(d.sightingCount) + 12; })
.style("fill", "white");

.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")

.attr("class", "y axis")
//.attr("transform", "rotate(-90)")
//.attr("y", -36)
//.attr("dy", ".71em")
//.style("text-anchor", "end")



the part i need to work for me that works in many online examples is where "//label the bars" is located


You're using scaleBand. So, instead of range(), it should be bandwidth():

        .text(function (d) { return d.sightingCount; })
        .attr("x", function (d) { return xScale(d.sightingYear) + xScale.bandwidth() / 2; })
        .attr("y", function (d) { return yScale(d.sightingCount) + 12; })
        .style("fill", "white");