D3 V4: Zoom & drag multi-series line chart - javascript

I am drawing charts with d3 4.2.2 in my Angular2 project. I created a multi series line chart and added zoom and drag properties. Now the chart is zooming on mouse scroll event but it zoom only X-axis and Y-axis. And it can be dragged only X-axis & Y-axis but chart cannot be dragged. When I do zooming or dragging those events are applying only to the two axis es but not for the chart. Following is what I am doing with my code.
// 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;
var zoom = d3.zoom()
.scaleExtent([1, 5])
.translateExtent([[0, -100], [width + 90, height + 100]])
.on("zoom", zoomed);
var svg = d3.select(this.htmlElement).append("svg")
.attr("class", "line-graph")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("pointer-events", "all")
.call(zoom);
var view = svg.append("rect")
.attr("class", "view")
.attr("x", 0.5)
.attr("y", 0.5)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.style("fill", "#EEEEEE")
.style("stroke", "#000")
.style("stroke-width", "0px");
// parse the date / time
var parseDate = d3.timeParse("%Y-%m-%d");
// set the ranges
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var z = d3.scaleOrdinal(d3.schemeCategory10);
// define the line
var line = d3.line()
.x( (d) => {
return x(d.date);
})
.y( (d) => {
return y(d.lookbookcount);
});
z.domain(d3.keys(data[0]).filter(function (key) {
return key !== "date";
}));
// format the data
data.forEach( (d)=> {
d.date = parseDate(d.date);
});
var lookBookData = z.domain().map(function (name) {
return {
name: name,
values: data.map( (d) => {
return {date: d.date, lookbookcount: d[name], name: name};
})
};
});
x.domain(d3.extent(data, (d) => {
return d.date;
}));
y.domain([
d3.min([0]),
d3.max(lookBookData, (c) => {
return d3.max(c.values,
(d) => {
return d.lookbookcount;
});
})
]);
z.domain(lookBookData.map( (c) => {
return c.name;
}));
var xAxis = d3.axisBottom(x)
.ticks(d3.timeDay.every(1))
.tickFormat(d3.timeFormat("%d/%m"));
var yAxis = d3.axisLeft(y)
.ticks(10);
// Add the X Axis
var gX = svg.append("g")
.style("font", "14px open-sans")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
var gY = svg.append("g")
.style("font", "14px open-sans")
.attr("class", "axis axis--x")
.call(yAxis)
.style("cursor", "ns-resize");
// Add Axis labels
svg.append("text")
.style("font", "14px open-sans")
.attr("text-anchor", "end")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.text("Sales / Searches");
svg.append("text")
.style("font", "14px open-sans")
.attr("text-anchor", "end")
.attr("dx", ".71em")
.attr("transform", "translate(" + width + "," + (height +
(margin.bottom)) + ")")
.text("Departure Date");
var chartdata = svg.selectAll(".chartdata")
.data(lookBookData)
.enter().append("g")
.attr("class", "chartdata");
chartdata.append("path")
.classed("line", true)
.attr("class", "line")
.attr("d", function (d) {
return line(d.values);
})
.style("fill", "none")
.style("stroke", function (d) {
return z(d.name);
})
.style("stroke-width", "2px");
chartdata.append("text")
.datum(function (d) {
return {
name: d.name, value: d.values[d.values.length - 1]
};
})
.attr("transform", function (d) {
return "translate(" +
x(d.value.date) + "," + y(d.value.lookbookcount) + ")";
})
.attr("x", 3)
.attr("dy", "0.35em")
.style("font", "14px open-sans")
.text(function (d) {
return d.name;
});
// add the dots with tooltips
chartdata.selectAll(".circle")
.data(function (d) {
return d.values;
})
.enter().append("circle")
.attr("class", "circle")
.attr("r", 4)
.attr("cx", function (d) {
console.log(d);
return x(d.date);
})
.attr("cy", function (d) {
return y(d.lookbookcount);
})
.style("fill", function (d) { // Add the colours dynamically
return z(d.name);
});
function zoomed() {
view.attr("transform", d3.event.transform);
gX.call(xAxis.scale(d3.event.transform.rescaleX(x)));
}
function resetted() {
svg.transition()
.duration(750)
.call(zoom.transform, d3.zoomIdentity);
}
Any suggestions would be highly appreciated.
Thank you

Related

text labels are wrong in grouped bar chart d3js

I am newbie in d3js, I do not know why all labels in the bar are wrong.
My code and captures are shown as below, then you can see that all labels are different from my data.
Anyone know what's going on in my text label section?
// set the dimensions and margins of the graph
var margin = { top: 10, right: 30, bottom: 40, left: 50 },
width = 700 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
const dataUrl = "https://raw.githubusercontent.com/yushinglui/IV/main/time_distance_status_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-2")
.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 + ")")
// List of subgroups = header of the csv files = soil condition here
var subgroups = data.columns.slice(1)
// List of groups = species here = value of the first column called group -> I show them on the X axis
var groups = d3.map(data, function (d) { return (d.startTime) })
// Add X axis
var x = d3.scaleBand()
.domain(groups)
.range([0, width])
.padding([0.2])
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickSize(0));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, 20])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
// Another scale for subgroup position?
var xSubgroup = d3.scaleBand()
.domain(subgroups)
.range([0, x.bandwidth()])
.padding([0.05])
// color palette = one color per subgroup
var color = d3.scaleOrdinal()
.domain(subgroups)
.range(['#98abc5', '#8a89a6'])
// Show the bars
svg.append("g")
.selectAll("g")
// Enter in data = loop group per group
.data(data)
.enter()
.append("g")
.attr("transform", function (d) { return "translate(" + x(d.startTime) + ",0)"; })
.selectAll("rect")
.data(function (d) { return subgroups.map(function (key) { return { key: key, value: d[key] }; }); })
.enter()
.append("rect")
.attr("x", function (d) { return xSubgroup(d.key); })
.attr("y", function (d) { return y(d.value); })
.attr("width", xSubgroup.bandwidth())
.attr("height", function (d) { return height - y(d.value); })
.attr("fill", function (d) { return color(d.key); })
// mouseover and mouseout animation
.on("mouseover", function (d) {
d3.select(this).style("fill", d3.rgb(color(d.key)).darker(2))
})
.on("mouseout", function (d) {
d3.select(this).style("fill", function (d) { return color(d.key); })
})
//axis labels
svg.append('text')
.attr('x', - (height / 2))
.attr('y', width - 650)
.attr('transform', 'rotate(-90)')
.attr('text-anchor', 'middle')
.style("font-size", "17px")
.text('Average Distance');
svg.append('text')
.attr('x', 300)
.attr('y', width - 240)
.attr('transform', 'rotate()')
.attr('text-anchor', 'middle')
.style("font-size", "17px")
.text('Start Time');
// legend
svg.append("circle").attr("cx", 200).attr("cy", 20).attr("r", 6).style("fill", "#98abc5")
svg.append("circle").attr("cx", 300).attr("cy", 20).attr("r", 6).style("fill", "#8a89a6")
svg.append("text").attr("x", 220).attr("y", 20).text("Present").style("font-size", "15px").attr("alignment-baseline", "middle")
svg.append("text").attr("x", 320).attr("y", 20).text("Absent").style("font-size", "15px").attr("alignment-baseline", "middle")
//text labels on bars -- all labels wrong!!
svg.append("g")
.selectAll("g")
// Enter in data = loop group per group
.data(data)
.enter()
.append("g")
.attr("transform", function (d) { return "translate(" + x(d.startTime) + ",0)"; })
.selectAll("text")
.data(function (d) { return subgroups.map(function (key) { return { key: key, value: d[key] }; }); })
.enter()
.append("text")
.text(function (d) { return y(d.value); })
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.attr("fill", "black")
.attr("text-anchor", "middle")
.attr("x", function (d) { return xSubgroup(d.key); })
.attr("y", function (d) { return y(d.value) + 10; })
});
My reference website:
http://plnkr.co/edit/9lAiAXwet1bCOYL58lWN?p=preview&preview
https://bl.ocks.org/bricedev/0d95074b6d83a77dc3ad
Your issue is that when you're appending the text, you inadvertently called the y function, which is used to get the y-location on where to insert the text. The numbers you're getting are actually y-location values, which seems completely random.
.text(function (d) { return y(d.value); }) // here is the issue
Change it to
.text(function (d) { return d.value; })
and it should work!

d3.js lollipop chart - animated

I am working on a d3 application - which features a bar chart with nodules on the top. I am keen to get this animated - so the bars grow to the point of rest and the nodules sprout like flowers.
So the nodules are either developed at the start and the bars just rise -- or the bars rise up and then the nodules flower.
//old js fiddle
http://jsfiddle.net/s1f4hzpu/1/
//current animation attempts
http://jsfiddle.net/9yvn8c4q/
var $this = $('.lollipopchart');
var data = [{
label: 'Toblerone',
value: 10,
},
{
label: 'Snickers',
value: 25,
},
{
label: 'Jawbreakers',
value: 60,
},
{
label: 'Gummi Worms',
value: 20,
},
];
var width = $this.data('width'),
height = $this.data('height');
var color = d3.scaleOrdinal()
.range(["#eb6383", "#fa9191", "#ffe9c5", "#b4f2e1"]);
data.forEach(function(d) {
d.total = +d.value;
});
var margin = {
top: 20,
right: 20,
bottom: 85,
left: 20
},
width = width - margin.left - margin.right,
height = height - margin.top - margin.bottom;
var x = d3.scaleBand()
.range([0, width])
.padding(0.9);
var y = d3.scaleLinear()
.range([height, 0]);
x.domain(data.map(function(d) {
return d.label;
}));
y.domain([0, d3.max(data, function(d) {
return d.total;
})]);
var svg = d3.select($this[0])
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr('class', 'lollipopchart')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var lollipop = svg.append('g').attr('class', 'lollipop');
var bars = lollipop
.append("g")
.attr('class', 'bars')
bars.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr('fill', function(d, i) {
return color(i);
})
.attr("x", function(d) {
return x(d.label);
})
.attr("width", x.bandwidth())
.attr("y", function(d) {
return y(d.value);
})
.attr("height", function(d) {
return height - y(d.total);
});
var lolliradian = 10;
var circles = lollipop
.append("g")
.attr('class', 'circles');
circles.selectAll("circle")
.data(data)
.enter()
.append("circle")
//.transition()
//.duration(1000)
.attr("cx", function(d) {
return (x(d.label) + x.bandwidth() / 2);
})
.attr("cy", function(d) {
return y(d.value);
})
.attr("r", lolliradian)
.attr('fill', function(d, i) {
return color(i);
})
var innercircles = lollipop
.append("g")
.attr('class', 'innercircles');
innercircles.selectAll("circle")
.data(data)
.enter()
.append("circle")
//.transition()
//.duration(1000)
.attr("cx", function(d) {
return (x(d.label) + x.bandwidth() / 2);
})
.attr("cy", function(d) {
return y(d.value);
})
.attr("r", lolliradian - 5)
.attr('fill', '#ffffff')
lollipop.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-65)");
lollipop.append("g")
.call(d3.axisLeft(y));
body {
background: #eeeeee;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<h1>LolliPop I</h1>
<div class="lollipopchart" data-width="300" data-height="300" />
Firstly, you don't need jQuery, you can do everything you want with regular d3.
Regardless, if you want to make the bars grow, you need to know that y=0 is the top and y=height is the bottom, so you need to actually decrease y as you increase height.
I also wouldn't draw a circle in front of another circle, but would use stroke and fill colours instead. If you make a stroke of 5 pixels wide, then it looks the same as in your example.
var data = [{
label: 'Toblerone',
value: 10,
},
{
label: 'Snickers',
value: 25,
},
{
label: 'Jawbreakers',
value: 60,
},
{
label: 'Gummi Worms',
value: 20,
},
];
var width = +d3.select(".lollipopchart").attr('data-width'),
height = +d3.select(".lollipopchart").attr('data-height');
var color = d3.scaleOrdinal()
.range(["#eb6383", "#fa9191", "#ffe9c5", "#b4f2e1"]);
data.forEach(function(d) {
d.total = +d.value;
});
var margin = {
top: 20,
right: 20,
bottom: 85,
left: 20
},
width = width - margin.left - margin.right,
height = height - margin.top - margin.bottom;
var x = d3.scaleBand()
.range([0, width])
.padding(0.9);
var y = d3.scaleLinear()
.range([height, 0]);
x.domain(data.map(function(d) {
return d.label;
}));
y.domain([0, d3.max(data, function(d) {
return d.total;
})]);
var svg = d3.select('.lollipopchart')
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr('class', 'lollipopchart')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var lollipop = svg.append('g').attr('class', 'lollipop');
var bars = lollipop
.append("g")
.attr('class', 'bars')
bars.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr('fill', function(d, i) {
return color(i);
})
.attr("x", function(d) {
return x(d.label);
})
.attr("width", x.bandwidth())
.attr("y", height)
.transition()
.duration(1500)
.attr("y", function(d) {
return y(d.value);
})
.attr("height", function(d) {
return height - y(d.total);
});
var lolliradian = 10;
var circles = lollipop
.append("g")
.attr('class', 'circles');
circles.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return (x(d.label) + x.bandwidth() / 2);
})
.attr("cy", height)
.attr("r", x.bandwidth() / 2)
.attr("fill", "white")
.attr("stroke-width", 5)
.attr('stroke', function(d, i) {
return color(i);
})
.transition()
.duration(1500)
.attr("cy", function(d) {
return y(d.value);
})
.on("end", function() {
d3.select(this)
.transition()
.duration(500)
.attr("r", lolliradian);
});
lollipop.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-65)");
lollipop.append("g")
.call(d3.axisLeft(y));
body {
background: #eeeeee;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<h1>LolliPop I</h1>
<div class="lollipopchart" data-width="300" data-height="300" />

Problems with grouped bar chart

I am new to d3 and trying to make a grouped bar chart following this and this websites.
The following is my code for the scales
x0 = d3.scaleTime()
.domain([
d3.min(dataset, function(d) {return d.date;}),
d3.max(dataset, function(d) {return d.date;})
])
.range([0,w]);
x1 = d3.scaleOrdinal()
.domain([dataset.WorldPopulation, dataset.InternetUser]);
// .rangeRound([0, x0.bandwidth()]);
y = d3.scaleLinear()
.domain([0, d3.max(dataset, function(d) {return d.WorldPopulation})])
.range([h,0]);
In the website above they use scaleOrdinal but I used scaleTime as x0. Therefore I'm not too sure if that works.
This is my code for the append(rect) for the bar chart
var date = svg.selectAll(".date")
.data(dataset)
.enter()
.append("g")
.attr("class", "g")
.attr("transform", function(d) {return "translate(" + x0(d.date) + ",0)";});
/* Add field1 bars */
date.selectAll(".bar.field1")
.data(d => [d])
.enter()
.append("rect")
.attr("class", "bar field1")
.style("fill","blue")
.attr("x", d => x0(d.WorldPopulation))
.attr("y", d => y(d.WorldPopulation))
.attr("width", x1.bandwidth())
.attr("height", d => {
return height - margin.top - margin.bottom - y(d.WorldPopulation)
});
/* Add field2 bars */
date.selectAll(".bar.field2")
.data(d => [d])
.enter()
.append("rect")
.attr("class", "bar field2")
.style("fill","red")
.attr("x", d => x0(d.InternetUser))
.attr("y", d => y(d.InternetUser))
.attr("width", x1.bandwidth())
.attr("height", d => {
return height - margin.top - margin.bottom - y(d.InternetUser)
});
And this is my csv file. Not too sure how to upload excel so I took a screenshot.
Any help provided will be appreciated. Feel free to request for any extra snippets of my code for clarification.
edit: After tweaking the code, no errors are shown but the svg is not produced either.
Using scaleBand for both x0 and x1, the following code works:
<script src="js/d3.v4.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 x0 = d3.scaleBand()
.rangeRound([0, width]).padding(.1);
var x1 = d3.scaleBand();
var y = d3.scaleLinear()
.range([height, 0]);
var xAxis = d3.axisBottom()
.scale(x0)
.tickSize(0);
var yAxis = d3.axisLeft()
.scale(y);
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("InternetUserStats.csv", function (error, data) {
var dates = data.map(function (d) { return d.date; });
var ymax = d3.max(data, function (d) { return Math.max(d.WorldPopulation, d.InternetUser); });
x0.domain(dates);
x1.domain(['WorldPopulations', 'InternetUsers']).rangeRound([0, x0.bandwidth()]);
y.domain([0, ymax]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
var date = svg.selectAll(".g")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function (d) { return "translate(" + x0(d.date) + ",0)"; });
/* Add field1 bars */
date/*.selectAll(".bar.field1")
.data(data)
.enter()*/
.append("rect")
.attr("class", "bar field1")
.style("fill", "blue")
.attr("x", function (d) { return x1('WorldPopulations'); })
.attr("y", function (d) { return y(+d.WorldPopulation); })
.attr("width", x0.bandwidth() / 2)
.attr("height", function (d) {
return height /*- margin.top - margin.bottom*/ - y(d.WorldPopulation)
});
/* Add field2 bars */
date/*.selectAll(".bar.field1")
.data(data)
.enter()*/
.append("rect")
.attr("class", "bar field2")
.style("fill", "red")
.attr("x", function (d) { return x1('InternetUsers'); })
.attr("y", function (d) { return y(d.InternetUser); })
.attr("width", x0.bandwidth() / 2)
.attr("height", function (d) {
return height /*- margin.top - margin.bottom*/ - y(d.InternetUser)
});
});
</script>
EDIT: the following code adds a legend that is based on your comment and your second link:
//This code goes after field2 bars are added.
/* Legend */
var legend = svg.selectAll(".legend")
.data(['WorldPopulations', 'InternetUsers']) //Bind an array of the legend entries
.enter().append("g")
.attr("class", "legend")
.attr("font-family", "sans-serif")
.attr("font-size", 13)
.style("text-anchor", "end")
.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", function (d) {
// Return "blue" for "WorldPopulations" and "red" for "InternetUsers":
return ((d === "WorldPopulations") ? "blue" : "red");
});
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
//.style("text-anchor", "end") //Already applied to .legend
.text(function (d) { return d; });

how to set color gradient in barchart using d3.js?

i have following code
d3.csv("data.csv", function(error, data) {
data.forEach(function(d) {
d.value = +d.value;
});
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 600 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);
var y = d3.scale.linear().range([height, 0]);
var y1 = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("#bar").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 + ")");
var yAxisRight = d3.svg.axis().scale(y1)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.date); })
.y(function(d) { return y1(d.avg_return); });
x.domain(data.map(function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.value; })]);
y1.domain([0, d3.max(data, function(d) {
return d.avg_return; })]);
/*for x axis*/
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)" );
/*for y axis*/
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Value ($)");
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.style("fill",function(d) { if (d.value >= 400) {return "green"} else if (d.value<=300) { return "red" } else { return 'yellow'} })
.attr("x", function(d) { return x(d.date); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
svg.append('path')
.datum(data)
.attr('class', 'sparkline')
.attr('d', line);
svg.append('circle')
.attr('class', 'sparkcircle')
.attr('cx', x(data[0].date))
.attr('cy', y1(data[0].avg_return))
.attr('r', 2.5);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + " ,0)")
.style("fill", "red")
.call(yAxisRight);
});
my csv file contains following data
date,value,avg_return
a,530,70
b,490,91
c,450,92
d,400,78
e,370,50
f,340,56
D,300,32
h,250,96
a9,200,73
i have use color gradient for this colors(#D73027,#FFFFBF,#1A9850).
how to use color gradient in bar chart..i have to sett colors based on the (value column)
From here : How to customize the color scale in a D3 line chart?
I have created your custom color scale :
var color = d3.scale.ordinal()
.range(["#D73027", "#FFFFBF" , "#1A9850"]);
And edited how you fill your bars :
.style("fill", function(d,i){
return color(i); //pass i to scale
})
Notice I pass i to the color scale. If there aren't enough colors in the scale it will wrap round and start again.
Working fiddle : https://jsfiddle.net/thatOneGuy/snjb4q92/2/
Edit
You say you want 'boundaries'. So what I have done, if its between 0 and 300, take first color, 300 and 400 takes second and 400 and 600 takes third.
Logic :
.style("fill", function(d, i) {
if (d.value >= 0 && d.value < 300) {
return color(0);
} else if (d.value >= 300 && d.value < 400) {
return color(1);
} else if (d.value >= 400 && d.value < 600) {
return color(2);
}
})
Updated fiddle : https://jsfiddle.net/thatOneGuy/snjb4q92/6/

Multiple Line Graph Labels - D3.js

I am trying to replicate the Multi-Series Line Chart example but I am unable to get the labels to show up at the end of the line or at all for that matter. The code is basically all the same as the example but a few words changed. The dataset is of county population and is formatted the same as in the example, earliest date at the top of the list and most recent date at the bottom of the list.
Anyone see anything I'm missing??
var margin = {top: 20, right: 80, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y%m%d").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.population); });
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("historicalpopulationTest.csv", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));
data.forEach(function(d) {
d.date = parseDate(d.date);
});
var counties = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {date: d.date, population: +d[name]};
})
};
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(counties, function(c) { return d3.min(c.values, function(v) { return v.population; }); }),
d3.max(counties, function(c) { return d3.max(c.values, function(v) { return v.population; }); })
]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", width)
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Year");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Population");
var county = svg.selectAll(".county")
.data(counties)
.enter().append("g")
.attr("class", "county");
county.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); });
county.append("text")
.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.population) + ")"; })
.attr("x", width)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
});
Graph looks like this
I think your problem is in the following code
county.append("text")
.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.population) + ")"; })
.attr("x", width)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
I haven't run your code, but it looks like you are translating the text to the end of the line and then moving the x position an additional 'width' number of pixels.
Try changing .attr("x", width) to .attr("x", 3)

Categories

Resources