I'm trying to run multiple "stacked-to-grouped" d3 bar charts on one page. I can get the charts to render, but have not been successful in getting the two charts to toggle between the options in unison.
I'm guessing that this might have to do with calling the "change" function more than once (since I'm calling it in the rendering of both charts), but I'm not sure how to place it outside of the charts and enable it to have access to what it needs. Thought it might have something to do with "each", but I'm not sure.
Here's a link to the jsfiddle that I've created: http://jsfiddle.net/1amsknh2/
And here's the js for the charts:
$( document ).ready(function() {
chart1();
});
function chart1(){
var stack = d3.layout.stack(),
layers = [
[
{"x":0,"y":1.5,"y0":0,"name":"cat1","color":"#B7A4DB"},
{"x":1,"y":1.5,"y0":0,"name":"cat2","color":"#B7A4DB"},
{"x":2,"y":1.5,"y0":0,"name":"cat3","color":"#B7A4DB"}
],
[
{"x":0,"y":2.5,"y0":1.5,"name":"cat1","color":"#85E6B5"},
{"x":1,"y":1.5,"y0":1.5,"name":"cat2","color":"#85E6B5"},
{"x":2,"y":1.0,"y0":1.5,"name":"cat3","color":"#85E6B5"}
]
];
n = 2, // number of layers
m = layers.length, // number of samples per layer
mb = ['cat1', 'cat2', 'cat3']
yGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y; }); }),
yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });
var margin = {top: 40, right: 10, bottom: 20, left: 40},
width = 400 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(mb)
.rangeRoundBands([0, width], .08);
var y = d3.scale.linear()
.domain([0, yStackMax])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(0)
.tickPadding(6)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
var svg = d3.select("#chart1").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 layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer");
// .style("fill", function(d) { return x(d.color); });
var rect = layer.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("x", function(d) { return x(d.name); })
.attr("y", height)
.attr("width", x.rangeBand())
.attr("height", 0)
.style("fill", function(d) { return d.color; });
rect.transition()
.delay(function(d, i) { return i * 10; })
.attr("y", function(d) { return y(d.y0 + d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); })
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.select("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
// .attr("y", 6)
.attr("dy", ".71em")
// .style("text-anchor", "middle")
.text("Amount");
d3.selectAll("input").on("change", change);
var timeout = setTimeout(function() {
d3.select("input[value=\"grouped\"]").property("checked", true).each(change);
}, 2000);
function change() {
clearTimeout(timeout);
console.log(1)
if (this.value === "grouped") transitionGrouped();
else transitionStacked();
svg.select("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
// .attr("y", 6)
.attr("dy", ".71em")
// .style("text-anchor", "middle")
.text("Contribution Amount");
}
function transitionGrouped() {
y.domain([0, yGroupMax]);
rect.transition()
.duration(500)
.delay(function(d, i) { return i * 10; })
.attr("x", function(d, i, j) { return x(d.name) + x.rangeBand() / n * j; })
.attr("width", x.rangeBand() / n)
.transition()
.attr("y", function(d) { return y(d.y); })
.attr("height", function(d) { return height - y(d.y); });
}
function transitionStacked() {
y.domain([0, yStackMax]);
rect.transition()
.duration(500)
.delay(function(d, i) { return i * 10; })
.attr("y", function(d) { return y(d.y0 + d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); })
.transition()
.attr("x", function(d) { return x(d.name); })
.attr("width", x.rangeBand());
}
chart2();
}
function chart2(){
var stack = d3.layout.stack(),
layers = [
[
{"x":0,"y":0.5,"y0":0,"name":"cat1","color":"#B7A4DB"},
{"x":1,"y":1.5,"y0":0,"name":"cat2","color":"#B7A4DB"},
{"x":2,"y":1.0,"y0":0,"name":"cat3","color":"#B7A4DB"}
],
[
{"x":0,"y":2.5,"y0":0.5,"name":"cat1","color":"#85E6B5"},
{"x":1,"y":1.5,"y0":1.5,"name":"cat2","color":"#85E6B5"},
{"x":2,"y":1.0,"y0":1.0,"name":"cat3","color":"#85E6B5"}
]
];
n = 2, // number of layers
m = layers.length, // number of samples per layer
mb = ['cat1', 'cat2', 'cat3']
yGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y; }); }),
yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });
var margin = {top: 40, right: 10, bottom: 20, left: 40},
width = 400 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(mb)
.rangeRoundBands([0, width], .08);
var y = d3.scale.linear()
.domain([0, yStackMax])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(0)
.tickPadding(6)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
var svg = d3.select("#chart2").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 layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer");
var rect = layer.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr("x", function(d) { return x(d.name); })
.attr("y", height)
.attr("width", x.rangeBand())
.attr("height", 0)
.style("fill", function(d) { return d.color; });
rect.transition()
.delay(function(d, i) { return i * 10; })
.attr("y", function(d) { return y(d.y0 + d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); })
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.select("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
// .attr("y", 6)
.attr("dy", ".71em")
// .style("text-anchor", "middle")
.text("Contribution Amount");
d3.selectAll("input").on("change", change);
function change() {
console.log(2);
if (this.value === "grouped") transitionGrouped();
else transitionStacked();
svg.select("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
// .attr("y", 6)
.attr("dy", ".71em")
// .style("text-anchor", "middle")
.text("Amount");
}
function transitionGrouped() {
y.domain([0, yGroupMax]);
rect.transition()
.duration(500)
.delay(function(d, i) { return i * 10; })
.attr("x", function(d, i, j) { return x(d.name) + x.rangeBand() / n * j; })
.attr("width", x.rangeBand() / n)
.transition()
.attr("y", function(d) { return y(d.y); })
.attr("height", function(d) { return height - y(d.y); });
}
function transitionStacked() {
y.domain([0, yStackMax]);
rect.transition()
.duration(500)
.delay(function(d, i) { return i * 10; })
.attr("y", function(d) { return y(d.y0 + d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); })
.transition()
.attr("x", function(d) { return x(d.name); })
.attr("width", x.rangeBand());
}
}
After struggling here and there, finally I made one fiddle for you.check it once.I hope you are looking for this http://jsfiddle.net/jxbyf82u/
In this fiddle Observe these line
d3.selectAll("input").on("change", change1);
chart1.change1 = change1;
and I'm calling this function from chart2()'s change() function by passing input value i.e. like below
chart1.change1(this.value);
If it is not what you are looking for, then ask what you want.Okay
Related
I start with d3 using version 3.
I created a grouped bar chart that looks like this:
I added a drop-down list that contains all the genders (Woman (femme), Couple...).
I'm blocked because I can't highlight the bars that correspond to a certain gender when I choose from the drop-down list.
I found on the internet that I could use this code:
d3.select('#inds')
.on("change", function () {
var sect = document.getElementById("inds");
var section = sect.options[sect.selectedIndex].value;
//some code here
});
the "Section" part contains my selected gender
I would like that when I select, for example torque, that the bars corresponding to the torque remain in color and the others are in gray.
This is the all code :
source : https://bl.ocks.org/hydrosquall/7966e9c8e8414ffcd8b5
Highlight : https://bl.ocks.org/bricedev/0d95074b6d83a77dc3ad
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 600,
height = 250 ;
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.ordinal()
.range(["#54E868", "#54CCE8", "#6395FF", "#50FFC5"]);
var xAxis = d3.svg.axis()
.scale(x0)
.tickSize(0)
.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("../CSV/GenreOrigine.csv", function(error, data) {
if (error) throw error;
//Couples, Famille...
var genreNames = d3.keys(data[0]).filter(function(key) { return key !== "Origine"; });
data.forEach(function(d) {
//Valeur pour chacune des origines par rapport au genre
d.genres = genreNames.map(function(name) { return {name: name, value: +d[name]}; });
});
x0.domain(data.map(function(d) { return d.Origine; }));
x1.domain(genreNames).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) { return d3.max(d.genres, function(d) { return d.value; }); })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0.3)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Nombre de personnes");
svg.select('.y').transition().duration(500).delay(1300).style('opacity','1');
var Origine = svg.selectAll(".Origine")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x0(d.Origine) + ",0)"; });
Origine.selectAll("rect")
.data(function(d) { return d.genres; })
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d.name); })
.style("fill", function(d) { return color(d.name) })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.on("mouseover", function(d) {
d3.select(this).style("fill", d3.rgb(color(d.name)).darker(2));
})
.on("mouseout", function(d) {
d3.select(this).style("fill", color(d.name));
});
Origine.selectAll("rect")
.transition()
.delay(function (d) {return Math.random()*1000;})
.duration(1000)
var legend = svg.selectAll(".legend")
.data(genreNames.slice().reverse())
.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.select('#inds')
.on("change", function () {
var sect = document.getElementById("inds");
var section = sect.options[sect.selectedIndex].value;
//some code here
});
});
You can select all the rect in the SVG and filter them in the function, so the code would look like:
var sect = document.getElementById('inds');
var section = sect.options[sect.selectedIndex].value;
if(section !== '') {
d3.selectAll("rect")
.attr('opacity', function(d) {
if(d.name !== section) {
return 0.2;
} else {
return 1;
}
})
} else {
d3.selectAll('rect')
.attr('opacity', 1)
}
In the example above, I changed the opacity attribute, but you can change fill with the same approach.
I'm relatively new to D3 and trying to add labels to a grouped bar chart.. With below implementation, I'm only able to see them under one group instead of both.
Below is how the data looks in the db:
category,Exceed,Fully Meets,Partially Meets,Does not meet
business,10,20,30,30
leadership,15,5,30,50
Below is the code:
var chart1 = d3.select("#svgarea2"),
margin = { top: 70, right: 0, bottom: 30, left: 40 },
width = +chart1.attr("width") - margin.left - margin.right,
height = +chart1.attr("height") - margin.top - margin.bottom,
g = chart1.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//chart background color
var bg = d3.select("g").append("svg")
// .attr("width", width + margin.right + margin.left)
.attr("width", 510 + "px")
// .attr("height", height + margin.top + margin.bottom);
.attr("height", 310 + "px");
bg.append("rect")
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "#f8f8ff");
bg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//scale chart
var x0 = d3.scaleBand()
.rangeRound([0, width])
.paddingInner(0.4);
var x1 = d3.scaleBand()
.padding(0.05);
var y = d3.scaleLinear()
.rangeRound([height, 0]);
var z = d3.scaleOrdinal() //d3.schemeCategory20
// .range(["#0000ff", "#dcdcdc", "#696969", "#00008b"]);
.range(["#00008b", "#696969", "#dcdcdc", "#0000ff"]);
var columns = ['category', 'Does Not Meet', 'Partially Meets', 'Fully Meets', 'Exceed'];
var keys = columns.slice(1);
var color = d3.scaleOrdinal()
.range(["#00008b", "#696969", "#dcdcdc", "#0000ff"]);
x0.domain(data.map(function (d) { return d.category; }));
x1.domain(keys).rangeRound([0, x0.bandwidth()]);
y.domain([0, 100]).nice();
g.append("g")
.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function (d) { return "translate(" + x0(d.category) + ",0)"; })
.selectAll("rect")
.data(function (d) { return keys.map(function (key) { return { key: key, value: d[key] }; }); })
.enter().append("rect")
.attr("x", function (d) { return x1(d.key); })
.attr("y", function (d) {
return y(d.value);
})
.attr("width", x1.bandwidth() - 7)
.attr("height", function (d) { return height - y(d.value); })
.attr("fill", function (d) { return z(d.key); })
.on("mousemove", function(d){
tooltip
.style("left", d3.event.pageX - 50 + "px")
.style("top", d3.event.pageY - 70 + "px")
.style("display", "inline-block")
.html((d.key) + "<br>" + (d.value) + "%");
});
g.append("g")
.selectAll("g")
.data(data).enter()
.append("g")
.attr("transform", function (d) { return keys })
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.attr("x", function (d) { return x0(d.category); })
.call(d3.axisBottom(x1))
.selectAll("text")
.attr("y", 15)
.attr("x", 0)
.attr("dy", ".35em")
.attr("transform", "rotate(50)")
.style("text-anchor", "start");;
g.append("g")
.attr("class", "axis")
.call(d3.axisLeft(y).ticks(null, "s"))
.append("text")
.attr("x", 2)
.attr("y", y(y.ticks().pop()) - 5)
.attr("dy", "0.32em")
.attr("fill", "#000")
.attr("font-weight", "bold")
.attr("text-anchor", "start")
.text("Employees (%)");
//chart title
g.append("text")
.attr("x", (width / 2) + 30)
.attr("y", 1 - (margin.top / 2) + 20)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("font-weight", "bold")
.style("text-decoration", "underline")
.attr("font-family", "sans-serif")
.text("Performance Distribution");
};
Any help is appreciated!
It will work if you create a g element for each barchart, and then add you axes, bars etc to each. See here for example:
http://blockbuilder.org/tomshanley/aa5471a3ecaf9e41283d68188aecf042
Relevant code:
var chart = g.append("g")
.selectAll("g")
.data(data)
.enter().append("g");
chart.attr("transform", function (d) { return "translate(" + x0(d.category) + ",0)"; })
.selectAll("rect")
.data(function (d) { return keys.map(function (key) { return { key: key, value: d[key] }; }); })
.enter().append("rect")
.attr("x", function (d) { return x1(d.key); })
.attr("y", function (d) {
return y(d.value);
})
.attr("width", x1.bandwidth() - 7)
.attr("height", function (d) { return height - y(d.value); })
.attr("fill", function (d) { return z(d.key); })
//APPEND AN AXIS TO THE CHART G'S
chart.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.attr("x", function (d) { return x0(d.category); })
.call(d3.axisBottom(x1))
.selectAll("text")
.attr("y", 15)
.attr("x", 0)
.attr("dy", ".35em")
.attr("transform", "rotate(50)")
.style("text-anchor", "start");
I'm trying to add labels to my bar chart, and I can't make it work. I read a lot about it and tried many things already, but no success.
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var parseDate = d3.timeParse("%Y-%m");
var x = d3.scaleBand().rangeRound([0, width]).paddingInner(0.05);
var y = d3.scaleLinear().range([height, 0]);
var xAxis = d3.axisBottom(x)
.tickFormat(d3.timeFormat("%Y-%m"));
var yAxis = d3.axisLeft(y)
.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("bar-data.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.value = +d.value;
});
x.domain(data.map(function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.value; })]);
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)" );
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", "steelblue")
.attr("x", function(d) { return x(d.date); })
.attr("width", x.bandwidth())
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
svg.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function(d) {
return d.value;
})
.attr("text-anchor", "middle")
.attr("fill", "white")
.attr("x", function(d, i) {
return i * (width / data.length);
})
.attr("y", function(d) {
return height - (d * 4);
});
});
Here is my Plunker.
Any help is appreciated. Thank you in advance.
You can add labels to the bars using the snippet below -
svg.selectAll(".text")
.data(data)
.enter()
.append("text")
.attr("class","label")
.attr("x", (function(d) { return x(d.date); } ))
.attr("y", function(d) { return y(d.value) - 20; })
.attr("dy", ".75em")
.text(function(d) { return d.value; });
Your problem was here. The correct approach to get x-y positions for the labels would be the same approach you used for the bars using the x and y variables.
.attr("x", function(d, i) {
return i * (width / data.length);
})
.attr("y", function(d) {
return height - (d * 4);
});
Updated Plunkr - https://plnkr.co/edit/e6HPuph3OSbpxeEVQXfF?p=preview
I want to display negative and positive values with d3js... with dis code, it made only the positive values.
i've worked with this : http://jsfiddle.net/chrisJamesC/tNdJj/4/
can anyone help me?
her it is the code:
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 1200 - margin.left - margin.right,
height = 390 - margin.top - margin.bottom;
var y0 = Math.max(Math.abs(d3.min(d3.csv)), Math.abs(d3.max(d3.csv)));
var y = d3.scale.linear()
.domain([-y0, y0])
.range([height,0])
.nice();
var x = d3.scale.ordinal()
.domain(d3.range(d3.csv.length))
.rangeRoundBands([0, width], .1);
var color = d3.scale.ordinal()
.range(["#FFFFFF", "#FF0000", "#FE642E", "#00FF00", "#04B404", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
var chart2 = d3.select("#graph2")
.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 div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
d3.csv("dataanzeigeauto3.asp", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "State"; }));
data.forEach(function(d) {
var y0 = 0
d.ages = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
d.total = d.ages[d.ages.length - 1].y1;
});
x.domain(data.map(function(d) { return d.State; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]);
chart2.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
chart2.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("dy", ".71em")
.attr("y", 6)
.style("text-anchor", "end")
.text("Anzahl");
var state2 = chart2.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x(d.State) + ",0)"; });
state2.selectAll("rect")
.data(function(d) { return d.ages; }) .enter().append("rect")
.attr("class", function(d) { return d < 0 ? "bar negative" : "bar positive"; })
.attr("y", function(d) { return y(Math.max(0, (d.y1))); })
.attr("height", function(d) { return Math.abs(y(d.y0) - y(d.y1)); })
.attr("width", x.rangeBand())
.style("fill", function(d) { return color(d.name); })
.call(d3.helper.tooltip()
.attr({class: 'tooltip2'})
.text(function(d, i){ return d.name + ': '+ (-((d.y0) - (d.y1))) ; })
);
var legend2 = chart2.selectAll(".legend")
.data(color.domain().slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 100 + ")"; });
legend2.append("rect")
.attr("x", width - 30)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend2.append("text")
.attr("x", width - 35)
.attr("y", 14)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
I have a working d3.js line chart that renders linear numbers: http://jsfiddle.net/2g9VQ/
var probArray = ["1.0", "0.999999931839", "0.999816434171", "0.994147880224", "0.961785353466", "0.882923015661", "0.763731336472", "0.627901360001", "0.497594590727", "0.385100568858", "0.256161790111", "0.168894610653", "0.111773057", "0.0747467808441", "0.051065424573", "0.0355360834346", "0.0251527408762", "0.018097770"];
var imlArray = ["2.0", "4.0", "6.0", "8.0", "10.0", "12.0", "14.0", "16.0", "18.0", "20.0", "23.0", "26.0", "29.0", "32.0", "35.0", "38.0", "41.0", "44.0", "47.0", "50.0", "55.0", "60.0", "65.0", "70.0", "75.0", "80.0", "85.0", "90.0", "95.0", "100.0", "110.0", "120.0", "130.0", "140.0", "150.0", "160.0", "170.0", "180.0", "190.0", "200.0", "220.0", "240.0", "260.0", "280.0", "300.0"];
function log(n) {
return Math.log(n) / Math.LN10;
}
var data = [];
for(i=0; i<probArray.length; i++) {
// without log values...
data.push([parseFloat(imlArray[i]), parseFloat(probArray[i])]);
// with log valuse...
//data.push([log(parseFloat(imlArray[i])), log(parseFloat(probArray[i]))]);
}
console.log(data);
var margin = {top: 20, right: 20, bottom: 50, left: 50},
width = 400 - margin.left - margin.right,
height = 320 - margin.top - margin.bottom;
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");
var yAxis = d3.svg.axis().scale(y).orient("left");
var line = d3.svg.line()
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
var svg = d3.select("#dialog").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 dataCallback = function(d) {
d.x = +d[0];
d.y = +d[1];
};
data.forEach(dataCallback);
x.domain(d3.extent(data, function(d) { return d.x; }));
y.domain([0, d3.max(data, function(d) { return d.y; })]);
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", line);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", 160)
.attr("y", 30)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Intensity measure type");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -50)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Probabability of exceedance in "+invest_time+" years");
var legend = d3.select("#dialog").append("svg");
legend.append("text")
.attr("x", 20)
.attr("y", 7)
.attr("dy", ".35em")
.text("Location (Lon/Lat): "+lng+", "+lat);
d3.select('#chart').on("click", function() {
data.splice(0,1);
data.push([5,5]);
dataCallback(data[data.length - 1]);
x.domain(d3.extent(data, function(d) { return d.x; }));
y.domain([0, d3.max(data, function(d) { return d.y; })]);
svg.selectAll("path").data([data])
.attr("d", line);
});
But the chart fails to render when I change the points to a logarithmic scale: http://jsfiddle.net/Z3Yms/
var probArray = ["1.0", "0.999999931839", "0.999816434171", "0.994147880224", "0.961785353466", "0.882923015661", "0.763731336472", "0.627901360001", "0.497594590727", "0.385100568858", "0.256161790111", "0.168894610653", "0.111773057", "0.0747467808441", "0.051065424573", "0.0355360834346", "0.0251527408762", "0.018097770"];
var imlArray = ["2.0", "4.0", "6.0", "8.0", "10.0", "12.0", "14.0", "16.0", "18.0", "20.0", "23.0", "26.0", "29.0", "32.0", "35.0", "38.0", "41.0", "44.0", "47.0", "50.0", "55.0", "60.0", "65.0", "70.0", "75.0", "80.0", "85.0", "90.0", "95.0", "100.0", "110.0", "120.0", "130.0", "140.0", "150.0", "160.0", "170.0", "180.0", "190.0", "200.0", "220.0", "240.0", "260.0", "280.0", "300.0"];
function log(n) {
return Math.log(n) / Math.LN10;
}
var data = [];
for(i=0; i<probArray.length; i++) {
// without log values...
//data.push([parseFloat(imlArray[i]), parseFloat(probArray[i])]);
// with log valuse...
data.push([log(parseFloat(imlArray[i])), log(parseFloat(probArray[i]))]);
}
console.log(data);
var margin = {top: 20, right: 20, bottom: 50, left: 50},
width = 400 - margin.left - margin.right,
height = 320 - margin.top - margin.bottom;
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");
var yAxis = d3.svg.axis().scale(y).orient("left");
var line = d3.svg.line()
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
var svg = d3.select("#dialog").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 dataCallback = function(d) {
d.x = +d[0];
d.y = +d[1];
};
data.forEach(dataCallback);
x.domain(d3.extent(data, function(d) { return d.x; }));
y.domain([0, d3.max(data, function(d) { return d.y; })]);
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", line);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", 160)
.attr("y", 30)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Intensity measure type");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -50)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Probabability of exceedance in "+invest_time+" years");
var legend = d3.select("#dialog").append("svg");
legend.append("text")
.attr("x", 20)
.attr("y", 7)
.attr("dy", ".35em")
.text("Location (Lon/Lat): "+lng+", "+lat);
d3.select('#chart').on("click", function() {
data.splice(0,1);
data.push([5,5]);
dataCallback(data[data.length - 1]);
x.domain(d3.extent(data, function(d) { return d.x; }));
y.domain([0, d3.max(data, function(d) { return d.y; })]);
svg.selectAll("path").data([data])
.attr("d", line);
});
I believe this is due to the numbers becoming negative along the y axis.
You were setting the domain of the y axis as
y.domain([0, d3.max(data, function(d) { return d.y; })]);
which with the log values won't work because all values are less than 0. To fix, simply use
y.domain(d3.extent(data, function(d) { return d.y; }));
instead. You also might want to use a linear scale instead of a time scale for the x axis. Complete jsfiddle here.