I'm following the D3 tutorial but adding the axis makes half of my data disappear and I don't understand why. I thought that maybe the axis is taking up the space that's meant for the data so I added an extra 10px to the transform property, but it doesn't make any difference.
var GIST = "https://gist.githubusercontent.com/charisseysabel/f8f48fbf11b8a1b0d62cbe2d6bdc2aa6/raw/2ead1537adb822fbd59a666afd5334d525480a13/nano-2017.tsv"
var width = 1000,
height = 550,
margin = {top: 20, right: 30, bottom: 30, left: 4};
var y = d3.scaleLinear()
.range([height, 0]);
var yScale = d3.scaleLinear()
.range([height, 0]);
var xScale = d3.scaleLinear()
.range([0, width]);
var xAxis = d3.axisLeft(yScale);
var yAxis = d3.axisBottom(xScale);
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", height);
chart.append("g")
.attr("transform", "translate(10, 0)")
.call(xAxis);
chart.append("g")
.attr("transform", "translate(0, 540)")
.call(yAxis);
d3.tsv(GIST, type, function(error, data) {
y.domain([0, d3.max(data, function(d) { return d.value; })]);
var barWidth = width / data.length;
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) {
return "translate(" + ((i * barWidth) + 10) + ",0)"; }
);
bar.append("rect")
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.attr("width", barWidth - 1);
bar.append("text")
.attr("x", (barWidth / 2) - 2)
.attr("y", function(d) { return y(d.value) + 3; })
.attr("dy", ".75em")
.text(function(d) { return d.value; });
});
function type(d) {
d.value = +d.value;
return d;
}
When you do this...
var bar = chart.selectAll("g").etc...
... you're selecting group elements that already exist in the SVG, which are the axes, and binding your data to them.
There are two easy solutions:
Move your code that creates the axes to the bottom of the d3.tsv, that is, after you have appended the bars.
Select something that doesn't exist, like
var bar = chart.selectAll(null).etc. To read more about the logic behind selectAll(null), have a look at my answer here.
I am trying to create a multi-line graph and updating the data on button click. On each line, I want to highlight the intersection point with a cirlce. Now on button click, I was able to update the line path, but the old highlighted intersection points are not removed from the svgContainer(for eaxmple clicking update2 then update1 do not removes the last set of circles which are not connected to any line).
<input type="button" onclick="update1()" value="Update" />
<input type="button" onclick="update2()" value="UpdateDimension_T" />
<div id="outputViz">
</div>
<script type="text/javascript">
var data = [
[{'index':1,'score':0},{'index':2,'score':5},{'index':3,'score':10},{'index':4,'score':0},{'index':5,'score':6}],
[{'index':1,'score':1},{'index':2,'score':6},{'index':3,'score':11},{'index':4,'score':1},{'index':5,'score':7}],
[{'index':1,'score':2},{'index':2,'score':7},{'index':3,'score':12},{'index':4,'score':2},{'index':5,'score':8}],
[{'index':1,'score':3},{'index':2,'score':8},{'index':3,'score':13},{'index':4,'score':3},{'index':5,'score':9}],
[{'index':1,'score':4},{'index':2,'score':9},{'index':3,'score':14},{'index':4,'score':4},{'index':5,'score':10}]
];
var data_O = [
[{'index':1,'score':1},{'index':2,'score':6},{'index':3,'score':11},{'index':4,'score':1},{'index':5,'score':7},{'index':6,'score':12}],
[{'index':1,'score':2},{'index':2,'score':7},{'index':3,'score':12},{'index':4,'score':2},{'index':5,'score':8},{'index':6,'score':13}],
[{'index':1,'score':3},{'index':2,'score':8},{'index':3,'score':13},{'index':4,'score':3},{'index':5,'score':9},{'index':6,'score':14}],
[{'index':1,'score':4},{'index':2,'score':9},{'index':3,'score':14},{'index':4,'score':4},{'index':5,'score':10},{'index':6,'score':15}],
[{'index':1,'score':5},{'index':2,'score':10},{'index':3,'score':15},{'index':4,'score':5},{'index':5,'score':11},{'index':6,'score':16}]
];
var data_T = [
[{'index':1,'score':5},{'index':2,'score':10},{'index':3,'score':15},{'index':4,'score':5},{'index':5,'score':12},{'index':6,'score':20},{'index':7,'score':15}],
[{'index':1,'score':6},{'index':2,'score':11},{'index':3,'score':16},{'index':4,'score':6},{'index':5,'score':13},{'index':6,'score':21},{'index':7,'score':16}],
[{'index':1,'score':7},{'index':2,'score':12},{'index':3,'score':17},{'index':4,'score':7},{'index':5,'score':14},{'index':6,'score':22},{'index':7,'score':17}],
[{'index':1,'score':8},{'index':2,'score':13},{'index':3,'score':18},{'index':4,'score':8},{'index':5,'score':15},{'index':6,'score':23},{'index':7,'score':18}],
[{'index':1,'score':9},{'index':2,'score':14},{'index':3,'score':19},{'index':4,'score':9},{'index':5,'score':16},{'index':6,'score':24},{'index':7,'score':19}]
];
var colors = [
'steelblue',
'green',
'red',
'purple',
'black'
];
var dataset = ["","Or","Se","Tr","De","Cc"];
var dataset_O = ["","O_1","O_2","O_3","O_4","O_5","O_6"];
var dataset_T = ["","T_1","T_2","T_3","T_4","T_5","T_6","T_7"];
var margin = {top: 20, right: 30, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
padding = 30;
var x = d3.scale.linear()
.domain([0, dataset.length])
.range([0, width]);
var y = d3.scale.linear()
.domain([-1, 16])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickFormat(function(d) { return dataset[d]; })
.tickSize(-height)
.tickPadding(10)
.tickSubdivide(false)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.tickPadding(10)
.tickSize(-width)
.tickSubdivide(false)
.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 + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "y axis")
.append("text")
.attr("class", "axis-label")
.attr("transform", "rotate(-90)")
.attr("y", (-margin.left) + 10)
.attr("x", -height/2)
.text('Axis Label');
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return x(d.index); })
.y(function(d) { return y(d.score); });
svg.selectAll('.line')
.data(data)
.enter()
.append("path")
.attr("class", "line")
.attr('stroke', function(d,i){
return colors[i%colors.length];
})
.attr("d", line);
var points = svg.selectAll('.dots')
.data(data)
.enter()
.append("g")
.attr("class", "dots")
points.selectAll('.dot')
.data(function(d, index){
var a = [];
d.forEach(function(point,i){
a.push({'index': index, 'point': point});
});
return a;
})
.enter()
.append('circle')
.attr('class','dot')
.attr("r", 2.5)
.attr('fill', function(d,i){
return colors[d.index%colors.length];
})
.attr("transform", function(d) {
return "translate(" + x(d.point.index) + "," + y(d.point.score) + ")"; }
);
function update1(){
var x = d3.scale.linear()
.domain([0, dataset_O.length])
.range([0, width]);
var y = d3.scale.linear()
.domain([-1, 16])
.range([height, 0]).nice();
xAxis = d3.svg.axis()
.scale(x)
.tickFormat(function(d) { return dataset_O[d]; })
.tickSize(-height)
.tickPadding(10)
.tickSubdivide(false)
.orient("bottom");
yAxis = d3.svg.axis()
.scale(y)
.tickPadding(10)
.tickSize(-width)
.tickSubdivide(false)
.orient("left");
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return x(d.index); })
.y(function(d) { return y(d.score); });
svg.selectAll('.line')
.data(data_O)
.transition(750)
.attr("d", line)
.attr("class", "line");
// change the x axis
svg.select(".x.axis").call(xAxis);
// change the y axis
svg.select(".y.axis").call(yAxis);
var points = svg.selectAll('.dots').data(data_O);
//UPDATE - HANDLE the current count
points.selectAll('.dot')
.data(function(d, index){
var a = [];
d.forEach(function(point,i){
a.push({'index': index, 'point': point});
});
return a;
})
.attr("transform", function(d) {
return "translate(" + x(d.point.index) + "," + y(d.point.score) + ")";
});
//ENTER - add the newly added count
points.selectAll('.dot')
.data(function(d, index){
var a = [];
d.forEach(function(point,i){
a.push({'index': index, 'point': point});
});
return a;
})
.enter()
.append('circle')
.attr('class','dot')
.attr("r", 2.5)
.attr('fill', function(d,i){
return colors[d.index%colors.length];
})
.attr("transform", function(d) {
return "translate(" + x(d.point.index) + "," + y(d.point.score) + ")";
});
d3.selectAll('g.dots').data(data_O).exit().remove();
}
function update2(){
var x = d3.scale.linear()
.domain([0, dataset_T.length])
.range([0, width]);
//var yExtents = d3.extent(d3.merge(data_T), function (d) { return d.score; });
var y = d3.scale.linear()
.domain([-1, 29])
.range([height, 0]).nice();
xAxis = d3.svg.axis()
.scale(x)
.tickFormat(function(d) { return dataset_T[d]; });
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return x(d.index); })
.y(function(d) { return y(d.score); });
svg.selectAll('.line')
.data(data_T)
.transition(750)
.attr("d", line)
.attr("class", "line");
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
var points = svg.selectAll('.dots').data(data_T);
//ENTER - add the newly added count
points.selectAll('.dot')
.data(function(d, index){
var a = [];
d.forEach(function(point,i){
a.push({'index': index, 'point': point});
});
return a;
})
.enter()
.append('circle')
.attr('class','dot')
.attr("r", 2.5)
.attr('fill', function(d,i){
return colors[d.index%colors.length];
})
.attr("transform", function(d) {
return "translate(" + x(d.point.index) + "," + y(d.point.score) + ")";
});
//UPDATE - HANDLE the current count
points.selectAll('.dot')
.data(function(d, index){
var a = [];
d.forEach(function(point,i){
a.push({'index': index, 'point': point});
});
return a;
})
.attr("transform", function(d) {
return "translate(" + x(d.point.index) + "," + y(d.point.score) + ")";
});
}
</script>
Here is the link to fiddle:
https://jsfiddle.net/aakashjain/1dc57aL7/1/
You'll need an "exit" selection:
points.selectAll('.dot')
.data(function(d, index){
var a = [];
d.forEach(function(point,i){
a.push({'index': index, 'point': point});
});
return a;
})
.exit()
.remove();
Here is the update fiddle:. https://jsfiddle.net/1dc57aL7/2/
(Just a tip: you have a lot of duplicated code here. Your "update1" and "update2" functions could be way smaller)
I have a bar chart.
function svg_render(data, svg) {
var node = d3.select(svg).append("svg")
.attr("class", "chart")
.attr("width", width)
.attr("height", height);
var y = d3.scale.linear().range([height, -height]);
var max_val = d3.max(data, function(d) {
return d;
});
y.domain([-max_val, max_val]);
var x = d3.scale.linear().domain([0, data.length]);
var bar_width = width / data.length;
var chart = node.attr("width", width).attr("height", height);
var bar = chart.selectAll("g")
.data(data)
.enter().append("g") // svg "group"
.attr("transform", function(d, i) {
return "translate(" + i * bar_width + ",0)";
});
bar.append("rect")
.attr("y", function(d) {
var yv = height - Math.abs(y(d) / 2) - height / 2 + 2;
return yv;
})
.attr("height", function(d) {
return Math.abs(y(d));
})
.attr("width", bar_width);
var axis = d3.svg.axis()
.scale(y)
.ticks(12)
.orient("left");
d3.select(".svg").append("svg")
.attr("class", "axis")
.attr("width", 60)
.attr("height", height)
.append("g")
.attr("transform", "translate(40," + (height / 2) + ")")
.call(axis);
}
would be great to be able to have a gradient towards the chart. An horizontal one.
Something like
Each bar can have a specific rgb code, but would be better if it was all calculated with a single gradient.
Also, bonus question, why i have that white lines as a border of my bars if i actually didn't specify any border at all (feels like aliasing svg issue)
So, i managed to achieve that by doing
var color = d3.scale.linear()
.domain([0, width])
.range(["hsl(62,100%,90%)", "hsl(222,30%,20%)"]);
And later on, for each bar element append
.style("fill", function(d, i) {
return color(i);
});
wonder if it's the fast way to do this
I'm new to D3JS, trying to use the nested json array to show the bar chart.Below is my json.
[
{
"image":"suresh.jpg",
"name":"Suresh",
"email":"abc#gmail.com",
"barValues":[
{
"letter":"A",
"frequency":".04253"
},
{
"letter":"B",
"frequency":".12702"
},
{
"letter":"C",
"frequency":".02288"
}
]
}
]
Below is my D3 code.
$scope.showDetails = function(relatedData) {
$http.get("searchInfo.json").success(function(response) {
var x = response;
$scope.data = [];
var searchT = relatedData;
var margin ={top:20, right:30, bottom:30, left:20},
width=360-margin.left- margin.right,
height=200-margin.top-margin.bottom;
var x = d3.scale.ordinal().rangeRoundBands([0, width], .1);
var y = d3.scale.linear().range([height, 0]);
var chart = d3.select("#chart")
.append("svg")
.attr("width", 600)
.attr("height", height+margin.top+margin.bottom);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
d3.json(searchT+'Details.json', function(error, data){
x.domain(data.map(function(d){ return d.letter}));
y.domain([0, d3.max(data, function(d){return d.frequency})]);
var bar = chart.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d, i){
return "translate("+x(d.letter)+", 0)";
});
bar.append("rect")
.attr("y", function(d) {
return margin.top+margin.right;
})
.attr("x", function(d,i){
return x.rangeBand()+(margin.left/4);
})
.attr("height", function(d) {
return height - y(d.frequency);
})
.attr("width", 29);
bar.append("text")
.attr("x", x.rangeBand()+margin.left )
.attr("y", function(d) { return y(d.frequency) -10; })
.attr("dy", ".75em")
.text(function(d) { return d.frequency; });
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate("+margin.left+","+ height+")")
.call(xAxis);
chart.append("g")
.attr("class", "y axis")
.attr("transform", "translate("+margin.left+",0)")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Frequency");
});
});
};
}
I'm not able to get the X-axis and Y-axis values. I've tried in different ways but was not working.Could any one help me on this,Thanks.