I need to put a d3 chart on a HTML div using bootstrap but I can't.
I managed to attach it on body, but I don't know why I cant inside a div.
I'm using a code like this for the script:
var chart1 = d3.select("#chart1")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
and a simple way for html:
<div id="chartline1"></div>
Here is all the code:
<!DOCTYPE html>
<html>
<head>
<title>Linee1</title>
</head>
<meta charset="utf-8">
<body>
<script type="text/javascript" src="d3/d3.js"></script>
<script src="js/bootstrap.js"></script>
<script src="js/jquery.min.js"></script>
<link rel="stylesheet" href="css/style.css">
<script>
var margin = {top: 130, right: 40, bottom: 45, left: 150},
width = 1000 - margin.left - margin.right,
height = 505 - margin.top - margin.bottom;
var parseDate = d3.time.format("%d-%b-%y").parse;
var formatTime = d3.time.format("%e %B");
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(3);
var valueline = d3.svg.line()
.interpolate("linear-open")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
var valueline2 = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.open); });
var div = d3.select("#chartline1").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var chart1 = d3.select("#chartline1")
.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 + ")");
function make_x_axis() {
return d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5)
}
function make_y_axis() {
return d3.svg.axis()
.scale(y)
.orient("left")
.ticks(3)
}
// Get the data
d3.tsv("data/data2.tsv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
d.open = +d.open;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return Math.max(d.close, `d.open); })]);`
//grid
chart1.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat("")
)
chart1.append("g")
.attr("class", "grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat("")
)
chart1.append("g") // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.style("font-size", "12px") ;
chart1.append("text") // text label for the x axis
.attr("transform",
"translate(" + (width/2) + " ," + (height+margin.bottom-3) + ")")
.style("text-anchor", "middle")
.text("Tempo");
chart1.append("g") // Add the Y Axis
.attr("class", "y axis")
.call(yAxis)
.style("font-size", "12px");
chart1.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 70 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Valore");
chart1.append("path")
.attr("class", "line")
.attr("d", valueline(data))
.style("stroke-width", 5);
chart1.append("path")
.attr("class", "line")
.style("stroke", "#6f6f6f")
.attr("d", valueline2(data))
.style("stroke-width", 5);
;
//tooltip line 1
chart1.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 5.5)
.style("fill", "#fff8ee")
.style("opacity", 1) // set the element opacity
.style("stroke", "#f93") // set the line colour
.style("stroke-width", 3.5)
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.close); })
.on("mouseover", function(d) {
d3.select(this).attr("r", 8).style("fill", "#f93").style("opacity", 1) ;
div.transition()
.duration(70)
.style("opacity", .8)
;
div .html(formatTime(d.date) + "<br/>" + d.close)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 64) + "px");
})
.on("mouseout", function(d) {
d3.select(this).attr("r", 5.5).style("fill", "#fff8ee");
div.transition()
.duration(200)
.style("opacity", 0) });
//tooltio line2
chart1.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 5.5)
.style("fill", "#fff8ee")
.style("opacity", 1) // set the element opacity
.style("stroke", "#6f6f6f") // set the line colour
.style("stroke-width", 3.5)
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.open); })
.on("mouseover", function(d) {
d3.select(this).attr("r", 8).style("fill", "#6f6f6f").style("opacity", 1) ; //il punto cambia al mousover (bellissmo)
div.transition()
.duration(70)
.style("opacity", .7)
.style("border", "1px");
div .html(formatTime(d.date) + "<br/>" + d.close)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 64) + "px");
})
.on("mouseout", function(d) {
d3.select(this).attr("r", 5.5).style("fill", "#fff8ee");
div.transition()
.duration(200)
.style("opacity", 0);
});
//title
chart1.append("text")
.attr("x", (width / 6))
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.style("font-size", "20px")
.style("text-decoration", "none")
.text("Modello 1: Serie (pochi dati) ");
});
</script>
<div id="chartline1" ></div>
</body>
</html>
You must declare your div before you call the script. Put the script after it or encapsulate it in a function and call it on load.
<!DOCTYPE html>
<html>
<head>
<title>Linee1</title>
<meta charset="utf-8">
<script type="text/javascript" src="d3/d3.js"></script>
<script src="js/bootstrap.js"></script>
<script src="js/jquery.min.js"></script>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="chartline1" ></div>
</body>
<script>
var margin = {top: 130, right: 40, bottom: 45, left: 150},
width = 1000 - margin.left - margin.right,
height = 505 - margin.top - margin.bottom;
var parseDate = d3.time.format("%d-%b-%y").parse;
var formatTime = d3.time.format("%e %B");
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(3);
var valueline = d3.svg.line()
.interpolate("linear-open")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
var valueline2 = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.open); });
var div = d3.select("#chartline1").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var chart1 = d3.select("#chartline1")
.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 + ")");
function make_x_axis() {
return d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5)
}
function make_y_axis() {
return d3.svg.axis()
.scale(y)
.orient("left")
.ticks(3)
}
// Get the data
d3.tsv("data/data2.tsv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
d.open = +d.open;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return Math.max(d.close, `d.open); })]);`
//grid
chart1.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat("")
)
chart1.append("g")
.attr("class", "grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat("")
)
chart1.append("g") // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.style("font-size", "12px") ;
chart1.append("text") // text label for the x axis
.attr("transform",
"translate(" + (width/2) + " ," + (height+margin.bottom-3) + ")")
.style("text-anchor", "middle")
.text("Tempo");
chart1.append("g") // Add the Y Axis
.attr("class", "y axis")
.call(yAxis)
.style("font-size", "12px");
chart1.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 70 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Valore");
chart1.append("path")
.attr("class", "line")
.attr("d", valueline(data))
.style("stroke-width", 5);
chart1.append("path")
.attr("class", "line")
.style("stroke", "#6f6f6f")
.attr("d", valueline2(data))
.style("stroke-width", 5);
;
//tooltip line 1
chart1.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 5.5)
.style("fill", "#fff8ee")
.style("opacity", 1) // set the element opacity
.style("stroke", "#f93") // set the line colour
.style("stroke-width", 3.5)
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.close); })
.on("mouseover", function(d) {
d3.select(this).attr("r", 8).style("fill", "#f93").style("opacity", 1) ;
div.transition()
.duration(70)
.style("opacity", .8)
;
div .html(formatTime(d.date) + "<br/>" + d.close)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 64) + "px");
})
.on("mouseout", function(d) {
d3.select(this).attr("r", 5.5).style("fill", "#fff8ee");
div.transition()
.duration(200)
.style("opacity", 0) });
//tooltio line2
chart1.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 5.5)
.style("fill", "#fff8ee")
.style("opacity", 1) // set the element opacity
.style("stroke", "#6f6f6f") // set the line colour
.style("stroke-width", 3.5)
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.open); })
.on("mouseover", function(d) {
d3.select(this).attr("r", 8).style("fill", "#6f6f6f").style("opacity", 1) ; //il punto cambia al mousover (bellissmo)
div.transition()
.duration(70)
.style("opacity", .7)
.style("border", "1px");
div .html(formatTime(d.date) + "<br/>" + d.close)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 64) + "px");
})
.on("mouseout", function(d) {
d3.select(this).attr("r", 5.5).style("fill", "#fff8ee");
div.transition()
.duration(200)
.style("opacity", 0);
});
//title
chart1.append("text")
.attr("x", (width / 6))
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.style("font-size", "20px")
.style("text-decoration", "none")
.text("Modello 1: Serie (pochi dati) ");
});
</script>
</html>
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
Here is the template for my Django where I am visualizing training using D3:
.line {
fill: none;
stroke: gray;
stroke-width: 2px;
}
<meta charset="utf-8">
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var real = {{values.real0|safe}}, pred = {{values.got0|safe}};
var margin = {top: 20, right: 20, bottom: 110, left: 50},
margin2 = {top: 430, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
height2 = 500 - margin2.top - margin2.bottom;
var x = d3.scaleLinear().range([0, width]).domain([0, Object.keys(real).length]),
x2 = d3.scaleLinear().range([0, width]).domain([0, Object.keys(real).length]),
y = d3.scaleLinear().range([height, 0]).domain([0, 1]),
y2 = d3.scaleLinear().range([height2, 0]).domain([0, 1]);
var xAxis = d3.axisBottom(x),
xAxis2 = d3.axisBottom(x2),
yAxis = d3.axisLeft(y);
var brush = d3.brushX()
.extent([[0, 0], [width, height2]])
.on("brush", brushed);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var formain = d3.line()
.x(function(d,i) { return x(i); })
.y(function(d) { return y(d); });
var forbrush = d3.line()
.x(function(d,i) { return x2(i); })
.y(function(d) { return y2(d); });
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
// Real starts
var color = d3.scaleLinear()
.domain([0, 0.5, 1])
.range(["red", "dodgerblue", "lime"]);
// x.domain(d3.extent(data, function(d) { return d.date; }));
// y.domain([0, d3.max(data, function(d) { return d.price; })+200]);
// x2.domain(x.domain());
// y2.domain(y.domain());
// append scatter plot to main chart area
var dots = focus.append("g");
dots.attr("clip-path", "url(#clip)");
dots.selectAll("dot")
.data(real)
.enter().append("circle")
.attr('class', 'dot')
.attr("r",5)
.style("opacity", .5)
.attr("cx", function(d,i) { return x(i); })
.attr("cy", function(d) { return y(d); })
.attr("fill",(function (d) { return color(d) }));
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
focus.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text(Object.keys({{values|safe}}));
// console.log(Object.keys({{values|safe}}));
svg.append("text")
.attr("transform",
"translate(" + ((width + margin.right + margin.left)/2) + " ," +
(height + margin.top + margin.bottom) + ")")
.style("text-anchor", "middle")
.text("index");
// append scatter plot to brush chart area
var dots = context.append("g");
dots.attr("clip-path", "url(#clip)");
dots.selectAll("dot")
.data(real)
.enter().append("circle")
.attr('class', 'dotContext')
.attr("r",3)
.style("opacity", .5)
.attr("cx", function(d,i) { return x2(i); })
.attr("cy", function(d) { return y2(d); })
.attr("fill",(function (d) { return color(d) }));
context.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
focus.append("path")
.data([real])
.attr("class", "line")
.attr("d", formain);
context.append("path")
.data([real])
.attr("class", "line")
.attr("d", forbrush);
//create brush function redraw scatterplot with selection
function brushed() {
var selection = d3.event.selection;
x.domain(selection.map(x2.invert, x2));
focus.selectAll(".dot")
.attr("cx", function(d,i) { return x(i); })
.attr("cy", function(d) { return y(d); });
context.selectAll(".line")
.attr("cx", function(d,i) { return x(i); })
.attr("cy", function(d) { return y(d); });
focus.select(".axis--x").call(xAxis);
context.select(".axis--x").call(xAxis2);
}
</script>
The output I received is something like the following:
What I want is the the magnifier focus should display the respective contents of the line and the dots. Plus I want to have the line in the background and dots on the foreground.
Please help me modify the sample for my use. There is some attribute I guess I am missing.
The sample csv need is : Sample Csv
Try to change the few thing and it will work. see below:
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
focus.append("path")
.data([real])
.attr("class", "line")
.attr("d", formain);
context.append("path")
.data([real])
.attr("class", "line")
.attr("d", forbrush);
Place it just as mentioned.
Change the brushed() function like the following:
function brushed() {
var selection = d3.event.selection;
x.domain(selection.map(x2.invert, x2));
focus.selectAll(".dot")
.attr("cx", function(d,i) { return x(i); })
.attr("cy", function(d) { return y(d); });
focus.selectAll(".line")
.attr("d",formain)
}
See the output of mine. It worked.:
Hope this will help you.
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");
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);
})