I am using D3 charting library to create charts with Angular-cli. D3 version is 4.2.2. I create a multi-line chart and here is I am trying to add legend to the chart. Following code is my code look like.
import {Directive, ElementRef, HostListener, Renderer} from '#angular/core';
import * as D3 from 'd3';
#Directive({
selector: 'bar-graph'
})
export class BarGraphDirective {
private htmlElement:HTMLElement;
constructor(private elementRef:ElementRef, private renderer: Renderer) {
this.htmlElement = this.elementRef.nativeElement;
console.log(this.htmlElement);
console.log(D3);
let d3:any = D3;
var data = [{
"date": "2016-10-01",
"sales": 110,
"searches": 67
}, ...];
// set the dimensions and margins of the graph
var margin = {
top: 20,
right: 80,
bottom: 30,
left: 50
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// parse the date / time
var parseDate = d3.timeParse("%Y-%m-%d");
var formatTime = d3.timeFormat("%e %B");
// set the ranges
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var sales = function (d) {
return d["sales"];
}
var searches = function (d) {
return d.searches;
}
// define the line
var line = d3.line()
.x(function (d) {
return x(d.date);
})
.y(function (d) {
return y(d.sales);
});
var svg = d3.select(this.htmlElement).append("svg")
.attr("class", "bar-graph")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var color = d3.scaleOrdinal(d3.schemeCategory10);
var tooltip = d3.select("body").append("div")
.style("opacity", 0);
// format the data
data.forEach(function (d) {
d.date = parseDate(d.date);
});
x.domain(d3.extent(data, function (d) {
return d.date;
}));
y.domain([0, d3.max(data, function (d) {
return d.sales > d.searches ? d.sales : d.searches;
})]);
// Add the line path.
svg.append("path")
.attr("class", "line")
.style("fill", "none")
.attr("d", line(data))
.style("stroke", "orange")
.style("stroke-width", "2px");
// change line to look at searches
line.y(function (d) {
return y(d.searches);
});
// Add the second line path.
svg.append("path")
.attr("class", "line")
.style("fill", "none")
.attr("d", line(data))
.style("stroke", "steelblue")
.style("stroke-width", "2px");
// Add sales to the scatterplot
svg.selectAll(".sales-circle")
.data(data)
.enter().append("circle")
.attr('class', 'sales-circle')
.attr("r", 4)
.attr("cx", function (d) {
return x(d.date);
})
.attr("cy", function (d) {
return y(d.sales);
})
.style("fill", "orange");
// Add searches to the scatterplot
svg.selectAll(".searches-circle")
.data(data)
.enter().append("circle")
.attr("r", 4)
.attr('class', 'searches-circle')
.attr("cx", function (d) {
return x(d.date);
})
.attr("cy", function (d) {
return y(d.searches);
})
.style("fill", "steelblue")
.on("mouseover", function (d) {
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html(formatTime(d["date"]) + "<br/> Searches: " + d["searches"])
.style("left", (d3.event.pageX + 5) + "px")
.style("top", (d3.event.pageY - 28) + "px")
.classed("tooltip", true);
})
.on("mouseout", function (d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
// draw legend
var legend = svg.selectAll("g")
.data(data)
.enter().append("g")
.attr("class", "legend");
// draw legend colored rectangles
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
// draw legend text
legend.append("text")
.style("font", "14px open-sans")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text("Sales");
// Add the X Axis
svg.append("g")
.style("font", "14px open-sans")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickFormat(d3.timeFormat("%d/%m")));
// Add the Y Axis
svg.append("g")
.style("font", "14px open-sans")
.call(d3.axisLeft(y));
// Add Axis labels
svg.append("text")
.style("font", "14px open-sans")
.attr("text-anchor", "middle")
.attr("transform", "translate(" + (-margin.left / 2) + "," + (height / 2) + ")rotate(-90)")
.text("Sales / Searches");
svg.append("text")
.style("font", "14px open-sans")
.attr("text-anchor", "middle")
.attr("transform", "translate(" + (width / 2) + "," + (height + (margin.bottom)) + ")")
.text("Date");
}
}
My chart looks like below. It shows only one item in the legend. How to add both items (sales & searches) to the legend.
Any suggestion are highly appreciated.
Thanks You
Add this in the code for adding new rect and text:
legend.append("rect")
.attr("x", width - 18)
.attr("y", 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", "steelblue");
// draw legend text
legend.append("text")
.style("font", "14px open-sans")
.attr("x", width - 24)
.attr("y", 18)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text("Searches");
Related
I do not know why the tooltip does not appear. Here is my code:
// set the dimensions and margins of the graph
var margin = { top: 20, right: 30, bottom: 50, left: 90 }
var width = 460 - margin.left - margin.right
var height = 2000 - margin.top - margin.bottom;
const dataUrl = "https://raw.githubusercontent.com/yushinglui/IV/main/course_distance_v2.csv"
//fetch the data
d3.csv(dataUrl)
.then((data) => {
// append the svg object to the body of the page
var svg = d3.select("#graph-1")
.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 + ")");
// Add X axis
var x = d3.scaleLinear()
.domain([0, 60])
.range([0, width]);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
// Y axis
var y = d3.scaleBand()
.range([0, height])
.domain(data.map(function (d) { return d.CourseCode; }))
.padding(0.1);
svg.append("g")
.call(d3.axisLeft(y))
// create tooltip element
const tooltip = d3.select("body")
.append("div")
.attr("class", "d3-tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.style("padding", "15px")
.style("background", "rgba(0,0,0,0.6)")
.style("border-radius", "5px")
.style("color", "#fff")
.text("a simple tooltip");
//Bars
let bars = svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", function (d) { return 1; })
.attr("y", function (d) { return y(d.CourseCode); })
.attr("width", function (d) { return x(d.AverageDistance); })
.attr("height", function (d) { return y.bandwidth(); })
.attr("fill", "orange");
.on("mouseover", function (d, i) {
tooltip.html(`CourseName: ${d.CourseName}`).style("visibility", "visible");
d3.select(this)
.attr("fill", "orangered");
})
.on("mousemove", function () {
tooltip
.style("top", (event.pageY - 10) + "px")
.style("left", (event.pageX + 10) + "px");
})
.on("mouseout", function () {
tooltip.html(``).style("visibility", "hidden");
d3.select(this).attr("fill", "orange");
});
//axis labels
svg.append('text')
.attr('x', -(height / 2))
.attr('y', width - 410)
.attr('transform', 'rotate(-90)')
.attr('text-anchor', 'middle')
.text('Course Code');
svg.append('text')
.attr('x', 150)
.attr('y', 1970)
.attr('transform', 'rotate()')
.attr('text-anchor', 'middle')
.text('Average Distance (Miles)');
//text labels on bars
svg.selectAll(null)
.data(data)
.enter()
.append("text")
.text(function (d) { return d.AverageDistance; })
.attr("x", function (d) { return x(d.AverageDistance) + 15; })
.attr("y", function (d) { console.log(d); return y(d.CourseCode) + y.bandwidth() * (0.5 + 0.1); })
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.attr("fill", "black")
.attr("text-anchor", "middle");
})
my reference website:
https://perials.github.io/responsive-bar-chart-with-d3/
https://observablehq.com/#bsaienko/animated-bar-chart-with-tooltip
https://blockbuilder.org/1Cr18Ni9/bfadecc96183c48d13b7b90bcf358a61
http://bl.ocks.org/katirg/5f168b5c884b1f9c36a5
I have created a stacked bar chart which works fine but I wanted to filter out the bars which are of very small length so that the chart looks good. Here is my code:-
<!DOCTYPE html>
<style>
.axis .domain {
}
</style>
<svg width="3000" height="700"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 200, left: 60},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleBand()
.rangeRound([0, 700])
.paddingInner(0.55)
.align(0.5);
var y = d3.scaleLinear()
.rangeRound([height,0]);
var z = d3.scaleOrdinal()
.range(["pink","purple"]);
//.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
d3.csv("pivot2.csv", function(d, i, columns) {
for (i = 1, t = 0; i < columns.length; ++i)
t += d[columns[i]] = +d[columns[i]];
d.total = t;
return d;
}, function(error, data) {
if (error) throw error;
var keys = data.columns.slice(1);
data.sort(function(a, b) { return b.total - a.total; });
x.domain(data.map(function(d) { if(d.total>2000){return d.Name;} }));
y.domain([0, d3.max(data, function(d) { return d.total; })]).nice();
z.domain(keys);
g.append("g")
.selectAll("g")
.data(d3.stack().keys(keys)(data))
.enter().append("g")
.attr("fill", function(d) {return z(d.key); })
.selectAll("rect")
.data(function(d) { return d;})
.enter().append("rect")
.attr("x", function(d) { return x(d.data.Name); })
.attr("y", function(d) { return y(d[1]) ; })
.attr("height",0)
.transition()
.duration(50)
.delay(function (d, i) { return i*100; })
.attr("height", function(d) { return y(d[0]) - y(d[1]); })
.attr("width",20)
//.attr("width", x.bandwidth())
g.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(1))
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-65)");
//.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis")
.call(d3.axisLeft(y).ticks(null, "s"))
.append("text")
.attr("x", 2)
.attr("y", y(y.ticks().pop()) + 0.2)
.attr("dy", "0.32em")
.attr("fill", "#000")
.attr("font-weight", "bold")
.attr("text-anchor", "start")
//.text("Duration");
var legend = g.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "end")
.selectAll("g")
.data(keys.slice().reverse())
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x",1500)
//.attr("x", width - 20)
.attr("width", 19)
.attr("height",0)
.transition()
.duration(200)
.delay(function (d, i) { return i*50; })
.attr("height", 19)
.attr("fill", z);
legend.append("text")
.attr("x",1490)
.attr("font-size","20px")
//.attr("x", width - 30)
.attr("y", 9.5)
.attr("dy", "0.32em")
.text(function(d) { return d; });
});
svg.append("text")
.attr("transform",
"translate(" + (width/2) + " ," +
(height + margin.top + 200) + ")")
.style("text-anchor", "middle")
.style("font-size","28px")
.style("fill","green")
.text("Customer Name");
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y",-5)
.attr("x",-200)
//.attr("y", 0 - margin.left)
//.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.style("fill","green")
.style("font-size","28px")
.text("Machine Duration By Mode");
</script>
As you can see I have applied an "IF" condition
data.sort(function(a, b) { return b.total - a.total; });
x.domain(data.map(function(d) { if(d.total>2000){return d.Name;} }));
y.domain([0, d3.max(data, function(d) { return d.total; })]).nice();
z.domain(keys);
But the problem is that all the remaining rectangles are being appended in the bottom left corner above the "Locust Valley Central School District" as you can see in the screenshot I have provided. Please help me to remove these extra rectangles.Screenshot for extra rectangles in the stacked bar chart
Map function here:
data.map(function(d) { if(d.total>2000){return d.Name;} })
Doesn't actually change data array, it returns a new array instead, which is used to initialize x.domain only.
Then you use unchanged data to create rectangles:
g.append("g")
.selectAll("g")
.data(d3.stack().keys(keys)(data))
.enter().append("g")
.attr("fill", function(d) {return z(d.key); })
.selectAll("rect")
.data(function(d) { return d;})
.enter().append("rect")
And it creates redundant rectangles with empty x coordinate. To fix this, you need to filter your data first:
data = data.filter(function(d) {
if (d.total > 2000) {
return true
}
})
And then use it to set x.domain (without any conditions here):
x.domain(data.map(function(d) { return d.Name }))
The rest of the code remains the same.
I have a bar chart that updates based on the results selected in a drop-down menu. When I change the selcetion, I get negaitve "y" values. It seems that my domain does not get updated with the new data. When I hard code the domain, my "y" are what I expect them to be. Anyone knows why ? Any other other comments (formatting, etc) welcomed.
var new_data;
//Create SVG margins and patting for the interior
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
//Create Scale
var xScale = d3
.scale
.ordinal()
.rangeRoundBands([margin.left, width], .1);
;
var yScale = d3
.scale
.linear()
.range([height, 0])
;
var xAxis = d3
.svg
.axis()
.scale(xScale)
.orient("bottom")
.tickPadding([5])
;
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(10)
;
//Create SVG with the above specs
var svg = d3.select("#container")
.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 + ")")
;
svg
.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
;
svg
.append("g")
.attr("class", "y axis")
.append("text") // just for the title (ticks are automatic)
.attr("transform", "rotate(-90)") // rotate the text!
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("frequency")
;
var temp = svg
.append("g")
.attr("class", "domx")
;
d3.csv("data3.csv", function(error, csv_data) {
// Filter the dataset to only get dept_1
var new_data = csv_data.filter(function(d) {
return d['dept'] == 'dept_1';
});
// function to handle histogram.
function histoGram(new_data){
//Create Scales
xScale
.domain(new_data.map(function(d) {return d.Pos;}))
;
yScale
// .domain([0, d3.max(new_data, function(d) { return d.Value; })])
.domain([0, d3.max(new_data, function(d) { return d.Value; })])
// .domain([0, 20])
;
svg
.select(".x.axis")
.transition()
.duration(1500)
.call(xAxis)
;
svg
.select(".y.axis")
.transition()
.duration(1500)
.call(yAxis)
;
// Data Join
var MyGroups = temp
.selectAll("g")
.data(new_data);
;
var MyGroupsEnter = MyGroups
.enter()
.append("g")
;
//Update
MyGroups
.attr("class", "update")
;
//Enter
MyGroupsEnter
.append("rect")
.attr("class", "enter")
.attr("x", function(d) { return xScale(d.Pos); })
.attr("y", function(d) { return (yScale(d.Value));})
.attr("width", xScale.rangeBand())
.attr("height", function(d) { return (height - yScale(d.Value)); })
.text(function(d) { return d.Value; })
.attr("fill", function(d) {return "rgb(0, 0, 0)";})
.style("fill-opacity", 0.2)
;
MyGroupsEnter
.append("text")
.attr("class", "text")
.text(function(d) { return d.Value; })
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "black")
.attr("text-anchor", "middle")
.attr("x", function(d) { return xScale(d.Pos) + xScale.rangeBand()/2; })
.attr("y", function(d) { return yScale(d.Value) - 10; })
;
//Enter + Update
MyGroups
.transition()
.duration(1500)
.select("rect")
.attr("x", function(d) { return xScale(d.Pos); })
.attr("width", xScale.rangeBand())
.attr("y", function(d) { return (yScale(d.Value));})
.attr("height", function(d) { return (height - yScale(d.Value)); })
.text(function(d) { return d.Value; })
.style("fill-opacity", 1) // set the fill opacity
.attr("fill", function(d) {return "rgb(0, 0, " + (d.Value * 30) + ")";})
;
MyGroups
.transition()
.duration(1500)
.select("text")
.attr("class", "text")
.text(function(d) { return d.Value; })
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "black")
.attr("text-anchor", "middle")
.attr("x", function(d) { return xScale(d.Pos) + xScale.rangeBand()/2; })
.attr("y", function(d) { return yScale(d.Value) - 8; })
;
MyGroups
.exit()
.transition()
.duration(1500)
.remove()
;
}
histoGram(new_data);
var options = ["dept_1","dept_2","dept_3"];
var dropDown = d3
.select("#sel_button")
.append("select")
.attr("name", "options-list")
.attr("id", "id-name");
var options = dropDown
.selectAll("option")
.data(options)
.enter()
.append("option");
options
.text(function (d) { return d; })
.attr("value", function (d) { return d; });
d3.select("#id-name")
.on("change", function() {
var value = d3.select(this).property("value");
var new_data2 = csv_data.filter(function(d) {
return d['dept'] == value;
});
histoGram(new_data2);
});
});
Here is the data:
dept,Pos,Value
dept_1,d1_p1,1
dept_1,d1_p10,10
dept_1,d1_p11,11
dept_1,d1_p12,12
dept_2,d2_p1,1.5
dept_2,d2_p2,3
dept_2,d2_p3,4.5
dept_2,d2_p4,6
dept_2,d2_p5,7.5
dept_2,d2_p6,9
dept_2,d2_p7,10.5
dept_2,d2_p8,12
dept_2,d2_p9,13.5
dept_2,d2_p10,15
dept_2,d2_p11,16.5
dept_2,d2_p12,17.5
dept_2,d2_p13,18.5
dept_3,d3_p1,5
dept_3,d3_p2,7
dept_3,d3_p3,10
Firgured out what was my problem. I hadn't defined the format of the values. The max function was returning the maximum number out of character values (9). I added the following piece of code prior to the domain function and everything now works fines.
csv_data.forEach(function(d) {
d.dept = d.dept;
d.Pos = d.Pos;
d.Value = +d.Value;
});
I am completely new to d3.
I have the following CSV:
HeaderAttempts HeaderGoals FreekickAttempts FreekickGoals Team
5 2 3 2 Team A
2 2 12 1 Team A
8 2 13 5 Team B
4 3 6 2 Team B
7 2 10 1 Team C
6 5 13 7 Team C
8 7 9 3 Team C
I am trying to create a scatter plot where x axis will have attempts and y axis will have the goals.
i have been able to create a scatter plot for the header attempts and goals by using the following code:
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var axisNames = {
HeaderAttempts: 'HeaderAttempts',
HeaderGoals: 'HeaderGoals',
FreekickAttempts: 'FreekickAttempts',
FreekickGoals: 'FreekickGoals'
};
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("body").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 + ")");
d3.csv("FootballData.csv", function(error, data) {
data.forEach(function(d) {
d.HeaderAttempts = +d.HeaderAttempts;
d.HeaderGoals = +d.HeaderGoals;
d.FreekickAttempts = +d.FreekickAttempts;
d.FreekickGoals = +d.FreekickGoals;
});
x.domain(d3.extent(data, function(d) { return d.HeaderAttempts; })).nice();
y.domain(d3.extent(data, function(d) { return d.HeaderGoals; })).nice();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("attempts");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("goals")
var tooltip = d3.select("body").append("div") // tooltip code
.attr("class", "tooltip")
.style("opacity", 0);
var circlesH = svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.HeaderAttempts); })
.attr("cy", function(d) { return y(d.HeaderGoals); })
.style("fill", function(d) { return color(d.Team); })
.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", 1.0);
tooltip.html(d.HeaderAttempts+" ,"+ d.HeaderGoals)
.style("left", (d3.event.pageX + 5) + "px")
.style("top", (d3.event.pageY - 18) + "px");
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
var circlesF = svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.FreekickAttempts); })
.attr("cy", function(d) { return y(d.FreekickGoals); })
.style("fill", function(d) { return color(d.Team); })
.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", 1.0);
tooltip.html(d.FreekickAttempts+" ,"+ d.FreekickGoals)
.style("left", (d3.event.pageX + 5) + "px")
.style("top", (d3.event.pageY - 18) + "px");
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
d3.selectAll("[name=v]")
.on("change", function() {
var selected = this.value;
display = this.checked ? "inline" : "none";
svg.selectAll(".dot")
.filter(function(d) {return selected == d.Team;})
.attr("display", display);
});
});
</script>
<div id="filter">
<b>team Filter:</b>
<br>
<input name='v' value="Team A" type="checkbox" checked>Team A
</input>
<br>
<input name="v" value="Team B" type="checkbox" checked >Team B
</input>
<br>
<input name="v" value="Team C" type="checkbox" checked >Team C
</input>
</div>
I know this wasnt going to work but had to give it a shot.
Now i have no idea how to proceed.
This is actually a truncated data and i still have 4 more columns:
PenaltyAttempts, PenaltyGoals, CornerAttempts, CornerGoals
Your approach of making separate graphs and overlapping in this is not really correct.
Better way is to make your dataset as per your requirement.
data.forEach(function(d) {
d.HeaderAttempts = +d.HeaderAttempts;
d.HeaderGoals = +d.HeaderGoals;
d.FreekickAttempts = +d.FreekickAttempts;
d.FreekickGoals = +d.FreekickGoals;
var attempts = d.HeaderAttempts + d.FreekickAttempts;//calculate all attempts of a team
var goals = d.HeaderGoals + d.FreekickGoals;//calculate all goals of a team
//make your data set like this
all.push({
team: d.Team,
attempts: attempts,
goals: goals
});
});
Then use this all object to make your domains
x.domain(d3.extent(all, function(d) { return d.attempts; })).nice();
y.domain(d3.extent(all, function(d) { return d.goals; })).nice();
Even points can be made easily like this:
svg.selectAll(".dot")
.data(all)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function(d) {console.log(d,"s");return x(d.attempts); })
.attr("cy", function(d) { return y(d.goals); })
.style("fill", function(d) { return color(d.team); })
Working code here
Hope this helps!
I have been trying to add labels to my bar chart as described in this question:
Adding label on a D3 bar chart
However, I can get the labels to display, but not over the appropriate bar (they are all lined up over/ on the first bar). Any help would be greatly appreciated. Here is my code:
var cdata = { title: "Sample Chart", Pod: 10, WOSNF : 201.57, SNFW: 8.89, YTDTarget: 15.14, AnnualTarget: 22.10, Max: 250 }
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// Parse the categories
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);
var y = d3.scale.linear().range([height, 30]);
y.domain([0, 30]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
var svg = d3.select("body").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 + ")");
d3.csv("data2.csv", function(error, data) {
data.forEach(function(d) {
d.value = +d.value;
console.log(d.value);
});
x.domain(data.map(function(d) { return d.Category; }));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.style("text-anchor", "end")
.attr("x", width/2)
.attr("y", 30)
.attr("dx", ".71em")
.attr("transform", "translate(40,20)" )
;
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "translate(" + (width / 2) + ",-25)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "middle")
.style("font-size", "14pt")
.text("Sample Chart");
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.style("fill", "steelblue")
.style("fill-opacity", "0.5")
.attr("x", function(d) { return x(d.Category); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.value) - 1;})
.attr("height", function(d) { return height - y(d.value);})
var yTextPadding = 20;
svg.selectAll("bartext")
.data(data)
.enter().append("text")
.attr("class", "bartext")
.attr("text-anchor", "middle")
.attr("fill", "black")
.attr("x", function(d, i) {
return x.rangeBand()/2;
})
.attr("y", function(d) {
return y(d.value);
})
.text(function(d){
return d.value;
});
});
var G3 = svg.append("g")
G3.append("line")
.attr("y1", y(cdata["YTDTarget"])-1)
.attr("y2", y(cdata["YTDTarget"])-1)
.attr("x1", 0)
.attr("x2", 500)
.attr("stroke-width", 2)
.attr("stroke", "black");
G3.append("text")
.attr("x",10)
.attr("y", y(cdata["YTDTarget"])+10)
.style("fill", "black")
.style("text-anchor", "start")
.text("RU YTD Target - " + cdata["YTDTarget"]);
var G4 = svg.append("g")
G4.append("line")
.attr("y1", y(cdata["AnnualTarget"])-1)
.attr("y2", y(cdata["AnnualTarget"])-1)
.attr("x1", 0)
.attr("x2", 500)
.attr("stroke-width", 2)
.attr("stroke", "black");
G4.append("text")
.attr("x", 10)
.attr("y", y(cdata["AnnualTarget"])+10)
.style("fill", "black")
.style("text-anchor", "start")
.text("RU Annual Target - " + cdata["AnnualTarget"]);
And here is the data:
Category,value
"Group1",27.2
"Group2",24.6
"Group3",27.1
The elements following the parsing of the data are to draw lines across the graph for reference.
Thanks!
You're currently setting the x position of the labels to half the width of the first bar (so they all end up on the left.
You want the x position of the bartext to start at the same spot as the current bar and add half the width of the bar:
.attr("x", function(d, i) {
return x(d.Category) + (x.rangeBand() / 2);
})