How to limit number of ticks to display in D3.js? - javascript

I found an example. http://jsfiddle.net/aWJtJ/8/, for limiting number of ticks but it uses D3.js version 3. I converted the code to version 5 but I am not getting the same result. It shows only two bars. Complete Fiddle: http://jsfiddle.net/pmLf095y/
// Margins, width and height.
var margin = {top: 20, right: 20, bottom: 30, left: 10},
body_width = 500,
width = body_width - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
// Scales.
var x = d3.scaleTime().range([width/data.length/2, width-width/data.length/2]);
var y = d3.scaleLinear().range([height, 0]);
// Construct our SVG object.
var svg = d3.select(".system-efficiency").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 + ")");
// X-axis.
var xAxis = d3.axisBottom(x)
.ticks(d3.timeMonth.every(1))
.tickFormat(d3.timeFormat('%b %Y'));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Set scale domains.
x.domain(data.map(d => new Date(d.datestr)));
y.domain([0, d3.max(data, function(d) { return d.air_used; })]);
// Call x-axis.
d3.select(".x.axis")
.transition().duration(1000)
.call(xAxis);
// Draw bars.
var bars = svg.selectAll(".air_used")
.data(data, function(d) { return d.datestr; });
bars.exit().remove();
bars.transition().duration(1000)
.attr("x", function(d) { return x(d.date) - width/data.length/2; })
.attr("width", width / data.length)
.attr("y", function(d) { return y(d.air_used); })
.attr("height", function(d) { return height - y(d.air_used);});
bars.enter().append("rect")
.attr("class", "air_used")
.attr("width", width / data.length)
.attr("x", function(d) { return x(new Date(d.datestr)) - (width/data.length)/2; })
.attr("y", height)
.attr("height", 0)
.transition().duration(1000)
.attr("y", function(d) { return y(d.air_used); })
.attr("height", function(d) { return height - y(d.air_used);});

To set the x domain, you don't need to map the dates but to find the extent of the dates.
x.domain(d3.extent(data, (d => new Date(d.datestr))));
Changed code:
var data = [
{
"air_produced": 0.660985,
"air_used": 0.342706,
"datestr": "2012-12-01 00:00:00",
"energy_used": 0.106402
},
{
"air_produced": 0.824746,
"air_used": 0.400776,
"datestr": "2013-01-01 00:00:00",
"energy_used": 0.250462
},
{
"air_produced": 0.181898,
"air_used": 0.003541,
"datestr": "2013-02-01 00:00:00",
"energy_used": 0.000582
},
{
"air_produced": 1.096685,
"air_used": 0.97719,
"datestr": "2013-03-01 00:00:00",
"energy_used": 0.923212
},
{
"air_produced": 0.283379,
"air_used": 0.241088,
"datestr": "2013-04-01 00:00:00",
"energy_used": 0.23381
}
];
// Margins, width and height.
var margin = {top: 20, right: 20, bottom: 30, left: 10},
body_width = 500,
width = body_width - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
// Scales.
var x = d3.scaleTime().range([width/data.length/2, width-width/data.length/2]);
var y = d3.scaleLinear().range([height, 0]);
// Construct our SVG object.
var svg = d3.select(".system-efficiency").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 + ")");
// X-axis.
var xAxis = d3.axisBottom(x)
.ticks(d3.timeMonth.every(1))
.tickFormat(d3.timeFormat('%b %Y'));
// Set scale domains.
x.domain(d3.extent(data, (d => new Date(d.datestr))));
y.domain([0, d3.max(data, function(d) { return d.air_used; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")");
// Call x-axis.
d3.select(".x.axis")
.transition().duration(1000)
.call(xAxis);
// Draw bars.
var bars = svg.selectAll(".air_used")
.data(data, function(d) { return d.datestr; });
bars.exit().remove();
bars.transition().duration(1000)
.attr("x", function(d) { return x(d.date) - width/data.length/2; })
.attr("width", width / data.length)
.attr("y", function(d) { return y(d.air_used); })
.attr("height", function(d) { return height - y(d.air_used);});
bars.enter().append("rect")
.attr("class", "air_used")
.attr("width", width / data.length)
.attr("x", function(d) { return x(new Date(d.datestr)) - (width/data.length)/2; })
.attr("y", height)
.attr("height", 0)
.transition().duration(1000)
.attr("y", function(d) { return y(d.air_used); })
.attr("height", function(d) { return height - y(d.air_used);});
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.air_used {
fill: steelblue;
}
.x.axis path {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<div class="section system-efficiency">
<h4>SYSTEM EFFICIENCY</h4>
</div>
Hope this clears up.

The following line returns only one value [0] but I need to define range [0, ?]:
x.domain(data.map(d => new Date(d.datestr)));
I changed back to original line:
x.domain(d3.extent(data, function(d) { return d.date; }));
Complete code:
// Margins, width and height.
var margin = {top: 20, right: 20, bottom: 30, left: 10},
body_width = 600,
width = body_width - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
// Scales.
var x = d3.scaleTime().range([width / data.length / 2, width - width / data.length / 2]);
var y = d3.scaleLinear().range([height, 0]);
// Construct our SVG object.
var svg = d3.select(".system-efficiency").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 + ")");
// X-axis.
var xAxis = d3.axisBottom(x)
.ticks(d3.timeMonth.every(1))
.tickFormat(d3.timeFormat('%b %Y'));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Date parsing.
const parseDate = d3.timeParse("%Y-%m-%d %H:%M:%S");
data.forEach(function(d) {
d.date = parseDate(d.datestr);
});
console.log(data);
// Set scale domains.
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function (d) {
return d.air_used;
})]);
// Call x-axis.
d3.select(".x.axis")
.transition().duration(1000)
.call(xAxis);
// Draw bars.
var bars = svg.selectAll(".air_used")
.data(data, function (d) {
return d.datestr;
});
bars.exit().remove();
bars.transition().duration(1000)
.attr("x", function (d) {
return x(d.date) - width / data.length / 2;
})
.attr("width", width / data.length)
.attr("y", function (d) {
return y(d.air_used);
})
.attr("height", function (d) {
return height - y(d.air_used);
});
bars.enter().append("rect")
.attr("class", "air_used")
.attr("width", width / data.length)
.attr("x", function (d) {
return x(d.date) - (width / data.length) / 2;
})
.attr("y", height)
.attr("height", 0)
.transition().duration(1000)
.attr("y", function (d) {
return y(d.air_used);
})
.attr("height", function (d) {
return height - y(d.air_used);
});
Note: I took the v3 example from one of stackoverflow questions, but now I could not find it to reference.

Related

How to have make this visualization in d3.js using values from a column matching a specific string

I am trying to implement the following problem while learning d3.js for visualization.
Using the following titanic dataset:
Plot in scatterplot :
a)the male passengers using an SVG square (width 5, x and y - 2.5 )
b)the female passengers using a circle of radius 2.8
c) Have the survived column used as opacity such that the dead have opacity 0.25 and alive have opacity: 1;
fill-opacity:.1;
stroke: black;
Make the scatterplot axes, make the y axis to log scale, and add the passengers name on their mark (using the SVG title element).
I am implementing the following code to achieve my goals but, I have am not successful in displaying my graph.
Can anyone please help me.
The titanic dataset - here
And my code here:
// set the dimensions and margins of the graph
var margin = {
top: 20,
right: 30,
bottom: 30,
left: 40
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.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 + ")");
//Read the data
d3.csv("https://gist.githubusercontent.com/michhar/2dfd2de0d4f8727f873422c5d959fff5/raw/fa71405126017e6a37bea592440b4bee94bf7b9e/titanic.csv", function(rawData) {
const data = rawData.map(function(d) {
return {
age: Number(d.age),
fare: Number(d.fare),
sex: d.sex,
survived: d.survived === "1",
name: d.name
};
});
// Add X axis
var x = d3.scaleLinear()
.domain([0, 80])
.range([0, width]);
svg.append("g")
.attr("transform", "translate(0," + height + ")");
// Add Y axis
var y = d3.scaleLog()
.domain([1e+0, 1e+3])
.range([height, 0]);
svg.append("g");
// Add dots
svg.append('g')
.selectAll("dot").select("female")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return x(d.age);
})
.attr("cy", function(d) {
return y(d.fare);
})
//.attr("r", 2.8)
.style("opacity", function(d) {
return d.survived ? "1" : "0.25";
})
.style("stroke", "black")
.style("fill-opacity", 0.1)
svg.append('g')
.selectAll("dot").select("male")
.data(data)
.enter()
.append("rect")
.attr("cx", function(d) {
return x(d.age);
})
.attr("cy", function(d) {
return y(d.fare);
})
//.attr("width", 5)
.style("opacity", function(d) {
return d.survived ? "1" : "0.25";
})
.style("stroke", "black")
.style("fill-opacity", 0.1)
.append("svg:title")
.text(function(d) {
return d.name
});
})
<script src="https://d3js.org/d3.v4.js"></script>
<div id="my_dataviz"></div>
can anyone please highlight where i am making mistake and help me please
You really, really need to read the manual, especially the SVG one. rect nodes don't have cx and cy, they have x and y, width, and height. And circle needs a radius r in order to be visible.
And you gave all the properties you read a lowercase starting letter. They need capitals. Look up a manual on debugging.
// set the dimensions and margins of the graph
var margin = {
top: 20,
right: 30,
bottom: 30,
left: 40
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.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 + ")");
//Read the data
d3.csv("https://gist.githubusercontent.com/michhar/2dfd2de0d4f8727f873422c5d959fff5/raw/fa71405126017e6a37bea592440b4bee94bf7b9e/titanic.csv", function(rawData) {
const data = rawData.map(function(d) {
return {
age: Number(d.Age),
fare: Number(d.Fare),
sex: d.Sex,
survived: d.Survived === "1",
name: d.Name
};
});
// Add X axis
var x = d3.scaleLinear()
.domain([0, 80])
.range([0, width]);
svg.append("g")
.attr("transform", "translate(0," + height + ")");
// Add Y axis
var y = d3.scaleLog()
.domain([1e+0, 1e+3])
.range([height, 0]);
svg.append("g");
// Add dots
svg.append('g')
.selectAll("dot").select("female")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return x(d.age);
})
.attr("cy", function(d) {
return y(d.fare);
})
.attr("r", 2.8)
.style("opacity", function(d) {
return d.survived ? "1" : "0.25";
})
.style("stroke", "black")
.style("fill-opacity", 0.1)
svg.append('g')
.selectAll("dot").select("male")
.data(data)
.enter()
.append("rect")
.attr("x", function(d) {
return x(d.age);
})
.attr("y", function(d) {
return y(d.fare);
})
.attr("width", 5)
.attr("height", 5)
.style("opacity", function(d) {
return d.survived ? "1" : "0.25";
})
.style("stroke", "black")
.style("fill-opacity", 0.1)
.append("svg:title")
.text(function(d) {
return d.name
});
})
<script src="https://d3js.org/d3.v4.js"></script>
<div id="my_dataviz"></div>

D3 Scatterplot v6 unable to plot correctly

I have an issue with D3 scatterplot where the data are not correctly plot
(plotted to 1 horizontal line rather than a scattered plot, the actual data is also scattered)
and the x-axis not able to show up.
// set the dimensions and margins of the graph
var margin = {
top: 20,
right: 20,
bottom: 30,
left: 50
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// parse the date / time
var parseTime = d3.timeParse("%Y-%m-%dT%H:%M:%S.%L%Z");
// set the ranges
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
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 + ")");
// Get the data
data = data.rows;
// format the data
data.forEach(function(d) {
var momentTemp = moment(d[0]).format("YYYY-MM-DDTHH:mm:ss.SSSZ");
var parseTemp = parseTime(momentTemp);
d.date = parseTemp;
d.close += d[1];
});
// 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 d.close;
})]);
var xValue = function(d) {
return d.date;
}
var yValue = function(d) {
return d.close;
}
// Add the scatterplot
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 1.5)
.attr("cx", function(d) {
return x(d.date);
})
.attr("cy", function(d) {
return y(d.close);
});
// Add the X Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add the Y Axis
svg.append("g")
.attr("transform", "translate(" + margin.left + " ,0)")
.call(d3.axisLeft(y));
That happens when your data is invalid. Are you sure the field close is correct? Your data calls the column ratio. I made some sample data and everything works:
// set the dimensions and margins of the graph
var margin = {
top: 20,
right: 20,
bottom: 30,
left: 50
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// parse the date / time
var parseTime = d3.timeParse("%Y-%m-%dT%H:%M:%S.%L%Z");
// set the ranges
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
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 + ")");
var data = new Array(100)
.fill(undefined)
.map(function(d, i) {
return {
date: new Date(Number(new Date("01/01/2000")) + i * 24 * 60 * 60 * 1000),
close: Math.random(),
};
});
// 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 d.close;
})]);
var xValue = function(d) {
return d.date;
}
var yValue = function(d) {
return d.close;
}
// Add the scatterplot
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 1.5)
.attr("cx", function(d) {
return x(d.date);
})
.attr("cy", function(d) {
return y(d.close);
});
// Add the X Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add the Y Axis
svg.append("g")
.attr("transform", "translate(" + margin.left + " ,0)")
.call(d3.axisLeft(y));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>

Prevent D3 graph from scaling

I am using this as my base project which is scrollable and scalable in both x and y axis. I have modified it to only be scrollable and scalable in x axis. Now, I want to prevent it from being scalable (i.e the x-scale should not change) while keeping it scrollable (i.e click the graph and dragging it slides it to the left or right)
I have tried doing scale(1) where there's transformation to keep the scale from not changing but that doesn't help. Here's the snippet for that:
g.append("svg:rect")
.attr("class", "zoom x box")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom)
.attr("transform", "translate(" + 0 + "," + 0 + ")")
.style("visibility", "hidden")
.attr("pointer-events", "all")
.call( d3.behavior.zoom().on("zoom", function(){
g.attr("transform", "translate(" + d3.event.translate + ") scale(1)")
}) ).append("g");
And here's the full code:
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Simpe Single Axis Zoom</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style>
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<div id="chart"></div>
<script>
var ex_chart = example().zoom(true);
var data = [];
for (var i = 0; i < 100; i++) {
data.push([Math.random(), Math.random()]);
}
d3.select('#chart')
.append("svg").attr("width", window.innerWidth).attr("height",window.innerHeight)
.datum(data).call(ex_chart);
function example() {
var svg;
var margin = {
top: 60,
bottom: 80,
left: 60,
right: 0
};
var width = 500;
var height = 400;
var xaxis = d3.svg.axis();
var yaxis = d3.svg.axis();
var xscale = d3.scale.linear();
var yscale = d3.scale.linear();
var zoomable = true;
var xzoom = d3.behavior.zoom()
.x(xscale)
.on("zoom", zoomable ? draw : null);
function chart(selection) {
selection.each(function(data) {
svg = d3.select(this).selectAll('svg').data([data]);
svg.enter().append('svg');
var g = svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom);
g.append("svg:rect")
.attr("class", "border")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom)
.style("stroke", "black")
.style("fill", "none");
g.append("g").attr("class", "x axis")
.attr("transform", "translate(" + 0 + "," + (height - margin.top - margin.bottom) + ")");
g.append("g").attr("class", "y axis");
g.append("g")
.attr("class", "scatter")
.attr("clip-path", "url(#clip)");
g
.append("svg:rect")
.attr("class", "zoom x box")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom)
.attr("transform", "translate(" + 0 + "," + 0 + ")")
.style("visibility", "hidden")
.attr("pointer-events", "all")
.call( d3.behavior.zoom().on("zoom", function(){
g.attr("transform", "translate(" + d3.event.translate + ") scale(1)")
}) ).append("g");
// Update the x-axis
xscale.domain(d3.extent(data, function(d) {
return d[0];
}))
.range([0, width - margin.left - margin.right]);
xaxis.scale(xscale)
.orient('bottom')
.tickPadding(10);
svg.select('g.x.axis').call(xaxis);
// Update the y-scale.
yscale.domain(d3.extent(data, function(d) {
return d[1];
}))
.range([height - margin.top - margin.bottom, 0]);
yaxis.scale(yscale)
.orient('left')
.tickPadding(10);
svg.select('g.y.axis').call(yaxis);
draw();
});
return chart;
}
function update() {
var gs = svg.select("g.scatter");
var circle = gs.selectAll("circle")
.data(function(d) {
return d;
});
circle.enter().append("svg:circle")
.attr("class", "points")
.style("fill", "steelblue")
.attr("cx", function(d) {
return X(d);
})
.attr("cy", function(d) {
return Y(d);
})
.attr("r", 4);
circle.attr("cx", function(d) {
return X(d);
})
.attr("cy", function(d) {
return Y(d);
});
circle.exit().remove();
}
function zoom_update() {
xzoom = d3.behavior.zoom()
.x(xscale)
.on("zoom", zoomable ? draw : null);
svg.select('rect.zoom.x.box').call(xzoom);
}
function draw() {
svg.select('g.x.axis').call(xaxis);
//svg.select('g.y.axis').call(yaxis);
update();
zoom_update();
};
// X value to scale
function X(d) {
return xscale(d[0]);
}
// Y value to scale
function Y(d) {
return yscale(d[1]);
}
chart.zoom = function (_){
if (!arguments.length) return zoomable;
zoomable = _;
return chart;
}
return chart;
}
</script>
</body>
</html>
Any sort of help is greatly appreciated. Thanks.
I found out that there was an easy fix for this. In the d3.behaviour.zoom() function, all I needed to add was .scaleExtent([1,1]), which doesn't scale anything more than 1 and hence preventing the zoom.
An example: https://jsfiddle.net/x97k4snj/1/
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Simpe Single Axis Zoom</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style>
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<div id="chart"></div>
<script>
var ex_chart = example().zoom(true);
var data = [];
for (var i = 0; i < 100; i++) {
data.push([Math.random(), Math.random()]);
}
d3.select('#chart')
.append("svg").attr("width", window.innerWidth).attr("height",window.innerHeight)
.datum(data).call(ex_chart);
function example() {
var svg;
var margin = {
top: 60,
bottom: 80,
left: 60,
right: 0
};
var width = 500;
var height = 400;
var xaxis = d3.svg.axis();
var yaxis = d3.svg.axis();
var xscale = d3.scale.linear();
var yscale = d3.scale.linear();
var zoomable = true;
var xzoom = d3.behavior.zoom()
.scaleExtent([1,1])
.x(xscale)
.on("zoom", zoomable ? draw : null);
function chart(selection) {
selection.each(function(data) {
svg = d3.select(this).selectAll('svg').data([data]);
svg.enter().append('svg');
var g = svg.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom);
g.append("svg:rect")
.attr("class", "border")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom)
.style("stroke", "black")
.style("fill", "none");
g.append("g").attr("class", "x axis")
.attr("transform", "translate(" + 0 + "," + (height - margin.top - margin.bottom) + ")");
g.append("g").attr("class", "y axis");
g.append("g")
.attr("class", "scatter")
.attr("clip-path", "url(#clip)");
g
.append("svg:rect")
.attr("class", "zoom x box")
.attr("width", width - margin.left - margin.right)
.attr("height", height - margin.top - margin.bottom)
.attr("transform", "translate(" + 0 + "," + 0 + ")")
.style("visibility", "hidden")
.attr("pointer-events", "all")
.call( d3.behavior.zoom().on("zoom", function(){
g.attr("transform", "translate(" + d3.event.translate + ") scale(1)")
}) ).append("g");
// Update the x-axis
xscale.domain(d3.extent(data, function(d) {
return d[0];
}))
.range([0, width - margin.left - margin.right]);
xaxis.scale(xscale)
.orient('bottom')
.tickPadding(10);
svg.select('g.x.axis').call(xaxis);
// Update the y-scale.
yscale.domain(d3.extent(data, function(d) {
return d[1];
}))
.range([height - margin.top - margin.bottom, 0]);
yaxis.scale(yscale)
.orient('left')
.tickPadding(10);
svg.select('g.y.axis').call(yaxis);
draw();
});
return chart;
}
function update() {
var gs = svg.select("g.scatter");
var circle = gs.selectAll("circle")
.data(function(d) {
return d;
});
circle.enter().append("svg:circle")
.attr("class", "points")
.style("fill", "steelblue")
.attr("cx", function(d) {
return X(d);
})
.attr("cy", function(d) {
return Y(d);
})
.attr("r", 4);
circle.attr("cx", function(d) {
return X(d);
})
.attr("cy", function(d) {
return Y(d);
});
circle.exit().remove();
}
function zoom_update() {
xzoom = d3.behavior.zoom()
.scaleExtent([1,1])
.x(xscale)
.on("zoom", zoomable ? draw : null);
svg.select('rect.zoom.x.box').call(xzoom);
}
function draw() {
svg.select('g.x.axis').call(xaxis);
//svg.select('g.y.axis').call(yaxis);
update();
zoom_update();
};
// X value to scale
function X(d) {
return xscale(d[0]);
}
// Y value to scale
function Y(d) {
return yscale(d[1]);
}
chart.zoom = function (_){
if (!arguments.length) return zoomable;
zoomable = _;
return chart;
}
return chart;
}
</script>
</body>
</html>

Label is not coming in proper position in D3 Bar graphs

I have the following problems with my bar chart.How to set decimal label value in proper position in Bar graph.label should not be overlap in nearest bar.but in my case it's overlapping.please suggest how to correct it
below is my code
var data = [
{ Request: 1, AvgRequest: 4123.18 },
{ Request: 2, AvgRequest: 5221.16 },
{ Request: 3, AvgRequest: 32.42 },
{ Request: 4, AvgRequest: 22.13 },
{ Request: 5, AvgRequest: 413.21 },
{ Request: 6, AvgRequest: 112.19 }
];
var margin = { top: 40, right: 40, bottom: 35, left: 85 },
width = 450 - margin.left - margin.right,
height = 250 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
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 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 + ")");
data.forEach(function (d) {
d.Request = d.Request;
d.AvgRequest = +d.AvgRequest;
});
x.domain(data.map(function (d) { return d.Request; }));
y.domain([0, d3.max(data, function (d) { return d.AvgRequest; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// xAxis label
svg.append("text")
.attr("transform", "translate(" + (width / 2) + " ," + (height + margin.bottom + 5) + ")")
.style("text-anchor", "middle")
.text("Numbers of request");
//yAxis label
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x", 0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("avg request);
// Title
svg.append("text")
.attr("x", (width / 2))
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("text-decoration", "underline")
.text("Avg");
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function (d) { return x(d.Request); })
.attr("width", x.rangeBand())
.attr("y", function (d) { return y(d.AvgRequest); })
.attr("height", function (d) { return height - y(d.AvgRequest); });
var text = svg.selectAll("text1")
.data(data)
.enter()
.append("text")
.attr("class", function (d) { return "label " + d.Request; })
.attr("x", function (d, i) {
return x(i) + x.rangeBand() / 5;
})
.attr("y", function (d, i) {
return y(d.AvgRequest) + 25;
})
.text(function (d) { return d.AvgRequest; })
.attr("font-size", "15px")
.style("stroke", "black");
I added two new variables to separate dimensions of complete chart and plot area:
var margin = { top: 40, right: 40, bottom: 35, left: 85 },
width = 450,
height = 250;
plotAreaWidth = width - margin.left - margin.right,
plotAreaHeight = height - margin.top - margin.bottom;
and changed other code accordingly.
And changes for text labels:
var text = svg.selectAll("text1")
.data(data)
.enter()
.append("text")
.attr("class", function (d) { return "label " + d.Request; })
.attr("x", function (d, i) {
//return x(i) + x.rangeBand() / 2;
return x(d.Request);
})
.attr("y", function (d, i) {
//return y(d.AvgRequest) + 25;
return y(d.AvgRequest) - 5;
})
.text(function (d) { return d.AvgRequest; })
.attr("font-size", "15px")
.style("stroke", "black");
Changed example at jsbin.

Determining bar width, with a 3d matrix

I have my data as follows:
var data = [[-5,7,10],[10,15,25],[-18,-14,-6]];
var margin = {top: 0, right: 30, bottom: 80, left: 30},
width = 180 - margin.left - margin.right,
height = 295 - margin.top - margin.bottom;
var x0 = Math.max(-d3.min(data[0]), d3.max(data[2]));
var x = d3.scale.linear()
.domain([-x0, x0])
.range([0, width]);
var y = d3.scale.ordinal()
.domain(d3.range(data.length))
.rangeRoundBands([0, height], .2);
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.selectAll(".bar")
.data(data)
.enter().append("rect")
.style("fill", "steelblue")
.attr("x", function(d, i) { return x(Math.min(0, d[0])); })
.attr("y", function(d, i) { return y(i); })
.attr("width", function(d, i) { return Math.abs(x(d[2]) - x(d[0])); })
.attr("height", y.rangeBand())
.append("rect");
//y axis
svg.append("g")
.attr("class", "y axis")
.append("line")
.attr("x1", x(0))
.attr("x2", x(0))
.attr("y1", 0)
.attr("y2", height+10);
What I want to do is create a bar chart where data[0] is the starting point, data[1] has a vertical line bisecting the bar and data[2] is the max value of the bar. So far, I think I'm covering the first two use cases correctly, but the third one fails. Any ideas?
http://jsfiddle.net/NPqEm/

Categories

Resources