D3 chart Should not show negative when zoom in and zoom out - d3.js

I am using d3 chart with zoom
i don't want negative values in y axis when zoom out. how can i avoid it.
Even i should avoid y axis values don't exceed to the actual value in zooming
For example:
My best y axis value is 5000
When i zoom out i don't want to see 5100, 5500 and 6000 like this
How can i avoid this.
thanks
Subash
Here is my code
var margin = { top: 0, right: 45, bottom: 20, left: 0 },
width = $('#realtimechart').width() - 40,
height = 300;
var x = d3.time.scale.utc()
.domain(d3.extent(data, function (d) {
return d.date;
}))
.range([0, width]);
var y = d3.scale.linear()
.domain([0, d3.max(data, function (d) {
return d.close;
})])
.range([height, 0]);
var line = d3.svg.line()
.x(function (d) {
return x(d.date);
})
.y(function (d) {
return y(d.close);
});
var xAxis = d3.svg.axis().scale(x).ticks(10).orient("bottom");
var yAxis = d3.svg.axis().scale(y).ticks(8).orient("right");
console.log(y)
var zoom = d3.behavior.zoom().x(x).y(y).translate([0,0]).scale(1).scaleExtent([0, 1000]).on("zoom", refresh);
var svg = d3.select("#realtimechart").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 + ")")
.call(zoom)
.append("g");
var make_x_axis = function () {
return d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5);
};
var make_y_axis = function () {
return d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5);
};
svg.append("rect")
.attr("width", width)
.attr("height", height);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + ", 0)")
.call(yAxis);
svg.append("g")
.attr("class", "x grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat(""));
svg.append("g")
.attr("class", "y grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat(0));
var clip = svg.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var chartBody = svg.append("g")
.attr("clip-path", "url(#clip)");
chartBody.append("svg:path")
.datum(data)
.attr("class", "line")
.attr("d", line);
function refresh() {
//$('#realtimechart').yAxis.scale().domain();
console.log(d3.svg.axis().scale().domain());
//console.log(i);
if(i < 1000) {
i++;
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.select(".x.grid")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat(""));
svg.select(".y.grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat(""));
svg.select(".line")
.attr("class", "line")
.attr("d", line);
}
}

Related

Change chart colors

I have a bar chart/histogram, all working fine.
I need to change the text and lines on the chart is on a black background.I
Also, the bar colors need to be orange.
I have had a look around the web, and seen some references to .attr("style":...); and have tried this without success.
Any pointers gratefully received.
<script>
// set the dimensions of the canvas
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 1890 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// set the ranges
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);
var y = d3.scale.linear().range([height, 0]);
// define the axis
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
// add the SVG element
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 + ")");
// load the data
d3.json("/assets/js/risk_hist_values.json", function(error, data) {
// the number of columns in this chart
var numCols = data.length;
data.forEach(function(d) {
d.Letter = d.bin_no;
d.Freq = +d.count;
});
// scale the range of the data
x.domain(data.map(function(d) { return d.Letter; }));
y.domain([0, d3.max(data, function(d) { return d.Freq; })]);
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong>Count:</strong> <span style='color:red'>" + d.count + "</span>";
})
// call the tips
svg.call(tip);
// add 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)" );
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 5)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Count");
// Add bar chart
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.Letter); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.Freq); })
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.on('click', drill)
.attr("id", function(d, i){ return 'b_'+i+''; })
.attr("height", function(d) { return height - y(d.Freq); });
});
function drill(){
alert( 'drilling' );
}
</script>

Timescale D3js from 23 to 11

I want to make my timescale from 23:00 to 7:00.
My data:
date close
23:03:34 2
23:06:34 3
23:15:34 9
23:57:34 42
00:08:12 8
01:08:12 60
02:08:12 60
03:08:12 60
04:08:12 60
04:08:12 0
05:08:12 60
05:13:24 5
06:28:24 9
Now it makes from 00-23!
Can anyone help me?
Here is my code:
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%H:%M:%S").parse;
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")
.tickFormat(d3.time.format("%H:%M"));
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
var svg = d3.select("#graph").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
function make_x_axis() {
return d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5)
}
function make_y_axis() {
return d3.svg.axis()
.scale(y)
.orient("left")
.ticks(20)
}
d3.tsv("datafordiagramm_masch2_fruh.asp", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain(d3.extent(data, function(d) { return d.close; }));
svg.append("g")
.attr("class", "grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat("")
.tickValues([5])
)
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat("")
)
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", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Zeit in Minuten");
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
});
now there are two lines, they start from coordinate 0/0. but i want one line from 23:00(pm) to 7:00 (am)

D3 chart. unneccessary yaxis range

i have used d3 chart. my data range is 600 to 1400.
when onLoad the charts shows the correct range.
the problem is when i scroll down its goes away like top 4000, bottom -2000.
how can i stop this.
the range show not be exceed.
regards,
Subash
this is my code
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
},
width = 1000,
height = 150;
d3.select("rect")
.filter(function(d) { return d.value === max; })
.classed("max", true);
var x = d3.time.scale()
.domain(d3.extent(data, function (d) {
return d.date;
}))
.range([0, width]);
//var y = (d3.scale.linear().domain(['100', '1000']))
var y = d3.scale.linear()
.domain(d3.extent(data, function (d) {
return d.value;
}))
.range([height, 0]);
var line = d3.svg.line()
.x(function (d) {
return x(d.date);
})
.y(function (d) {
return y(d.value);
});
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(d3.time.hour)
//var xAxis = d3.svg.axis()
// .scale(x)
// .tickValues([1, 2, 3, 5, 8, 13, 21]);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
var zoom = d3.behavior.zoom().x(x).y(y).on("zoom", refresh);
var zoomRect = false;
d3.select("#zoom-rect").on("change", function () {
zoomRect = this.checked;
});
var svg = d3.select("#realtimechart").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 + ")")
.call(zoom)
.append("g")
.on("mousedown", function () {
if (!zoomRect) return;
var e = this,
origin = d3.mouse(e),
rect = svg.append("rect").attr("class", "zoom");
d3.select("#realtimechart").classed("noselect", true);
origin[0] = Math.max(0, Math.min(width, origin[0]));
origin[1] = Math.max(0, Math.min(height, origin[1]));
d3.select(window)
.on("mousemove.zoomRect", function () {
var m = d3.mouse(e);
m[0] = Math.max(0, Math.min(width, m[0]));
m[1] = Math.max(0, Math.min(height, m[1]));
rect.attr("x", Math.min(origin[0], m[0]))
.attr("y", Math.min(origin[1], m[1]))
.attr("width", Math.abs(m[0] - origin[0]))
.attr("height", Math.abs(m[1] - origin[1]));
})
.on("mouseup.zoomRect", function () {
d3.select(window).on("mousemove.zoomRect", null).on("mouseup.zoomRect", null);
d3.select("#realtimechart").classed("noselect", false);
var m = d3.mouse(e);
m[0] = Math.max(0, Math.min(width, m[0]));
m[1] = Math.max(0, Math.min(height, m[1]));
if (m[0] !== origin[0] && m[1] !== origin[1]) {
zoom.x(x.domain([origin[0], m[0]].map(x.invert).sort()))
.y(y.domain([origin[1], m[1]].map(y.invert).sort()));
}
rect.remove();
refresh();
}, true);
d3.event.stopPropagation();
});
var make_x_axis = function () {
return d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5);
};
var make_y_axis = function () {
return d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5);
};
svg.append("rect")
.attr("width", width)
.attr("height", height);
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", "x grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat(""));
svg.append("g")
.attr("class", "y grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat(""));
var clip = svg.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var chartBody = svg.append("g")
.attr("clip-path", "url(#clip)");
chartBody.append("svg:path")
.datum(data)
.attr("class", "line")
.attr("d", line);
function refresh() {
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.select(".x.grid")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat(""));
svg.select(".y.grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat(""));
svg.select(".line")
.attr("class", "line")
.attr("d", line);
}

Chart zooming in D3

Here is my code for drawing line chart with zooming capabilities. However the problem is that when I zoom in the cursor doesn't stay on the same point. I would like to zoom in where mouse cursor is (I hope I'm clear enough).
Here's jsfiddle: http://jsfiddle.net/KSAbK/
width = 400 - margin.left - margin.right;
height = 200 - margin.top - margin.bottom;
var x = d3.time.scale()
.domain(d3.extent(data, function (d) {
return d.date;
}))
.range([0, width]);
var y = d3.scale.linear()
.domain(d3.extent(data, function (d) {
return d.value;
}))
.range([height, 0]);
var line = d3.svg.line()
.x(function (d) {
return x(d.date);
})
.y(function (d) {
return y(d.value);
});
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.on("zoom", zoomed);
svg = d3.select('#chart')
.append("svg:svg")
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.call(zoom)
.append("svg:g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var make_x_axis = function () {
return d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5);
};
var make_y_axis = function () {
return d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5);
};
var xAxis = make_x_axis();
svg.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + height + ")")
.call(xAxis);
var yAxis = make_y_axis();
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "x grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat(""));
svg.append("g")
.attr("class", "y grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat(""));
var clip = svg.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var chartBody = svg.append("g")
.attr("clip-path", "url(#clip)");
chartBody.append("svg:path")
.datum(data)
.attr("class", "line")
.attr("d", line);
function zoomed() {
console.log(d3.event.translate);
console.log(d3.event.scale);
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.select(".x.grid")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat(""));
svg.select(".y.grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat(""));
svg.select(".line")
.attr("class", "line")
.attr("d", line);
}
Figured it out. I had to use .call(zoom) on g element and I also added another rectangle so that zoom gets triggered when mouse cursor is anywhere on the charting area.
http://jsfiddle.net/KSAbK/1/
svg = d3.select('#chart')
.append("svg:svg")
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append("svg:g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
svg.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("class", "plot");

How to add space between axis and line in D3 line chart?

Given this simple chart I created:
var data = [["2013-01-24 06:38:02.235191", 52], ["2013-01-23 06:38:02.235310", 54], ["2013-01-22 06:38:02.235330", 45], ["2013-01-21 06:38:02.235346", 53]],
maxValue = d3.max(data, function (d) { return d[1]; }),
margin = {top: 20, right: 20, bottom: 50, left: 50},
width = 500 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom,
svg, x, y, xAxis, yAxis, line;
$.each(data, function(index, val) {
val[0] = new Date(val[0]);
});
x = d3.time.scale()
.range([0, width])
y = d3.scale.linear()
.domain([0, maxValue])
.range([height, 0]);
xAxis = d3.svg.axis()
.scale(x)
.tickSize(4, 2, 0)
.ticks(d3.time.days, 1)
.tickFormat(d3.time.format("%m/%d"))
.orient("bottom");
yAxis = d3.svg.axis()
.scale(y)
// .ticks(5)
// .tickValues([0, maxValue * 0.25, maxValue * 0.5, maxValue * 0.75, maxValue])
.tickSize(4, 2, 0)
.orient("left");
line = d3.svg.line()
.x(function(d) { return x(d[0]); })
.y(function(d) { return y(d[1]); });
svg = d3.select("#chart-holder").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.domain(d3.extent(data, function(d) { return d[0]; }));
y.domain(d3.extent(data, function(d) { return d[1]; }));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("transform", function(d) {
return "rotate(-60)translate(" + -this.getBBox().height * 1.7 + "," +
-this.getBBox().width/4 + ")";
});
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
svg
.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("fill", "#0b8da0")
.attr("r", 3.5)
.attr("cx", function(d) { return x(d[0]); })
.attr("cy", function(d) { return y(d[1]); });
How can I add a space between axis and line, so it won't touch the axis.
Also is there a way to force yAxis ticks to always start from 0, no matter what is the smallest value in the data set?
Working example can be found here: http://jsfiddle.net/n7Vmr/
You can just change the domain of the scale used to draw the y-axis, look for the line
y.domain(d3.extent(data, function(d) { return d[1]; }));
needs to be changed, if you want it one less than the smallest value in your dataset use
y.domain([d3.min(data, function (d) { return d[1]; })-1, maxValue]);
or if you want it to start from 0, regardless of the data
y.domain([0, maxValue]);

Resources