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");
Related
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>
I am trying to extend the x and y axis length and add the arrow at the end. Here is my code and plunker. I need x axis to extend beyond 4.6 and y-axis beyond "AS" and add an arrow at the end. Kindly help.
https://plnkr.co/edit/tA6oyKQCCmhNadbARR89?p=preview
var margin = {top: 20, right: 20, bottom: 20, left: 40},
width = 420 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.ordinal().rangePoints([height, 0])
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom").outerTickSize(0);
var yAxis = d3.svg.axis()
.scale(y).tickSize(-width).outerTickSize(0)
.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.tsv("data.tsv", function(error, data) {
if (error) throw error;
data.forEach(function(d) {
d.sepalWidth = +d.sepalWidth;
});
x.domain(d3.extent(data, function(d) { return d.sepalWidth; })).nice();
y.domain(data.map(function(d) { return d.sepalLength;}));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height) + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.sepalWidth); })
.attr("cy", function(d) { return y(d.sepalLength); })
.style("fill", function(d) { return color(d.species); });
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
Easiest way is to just tack on a custom path to the end of the axis:
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height) + ")")
.call(xAxis)
.append("path")
// add extension arrow
.attr("d", "M" + width + ",0L" + (width + 20) + ",0L" + (width + 20) + ",-5L" + (width + 30) + ",0L" + (width + 20) + ",5L" + (width + 20) + ",0L");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("path")
// add extension arrow
.attr("d", "M0,0L0,-20L-5,-20L0,-30L5,-20,L0,-20Z");
Updated plunker.
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);
}
}
I am new in D3 js and working on it.i wanted to implement bar graph through it in my MVC3 web application.Could you please let me know how can i create bar graph with dynamically.below is sample code but i am not able to find the dynamic creation bar graph
<script>
var margin = { top: 20, right: 20, bottom: 30, left: 50 },
width = 600 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y").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");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.x(function (d) { return x(d.year); })
.y(function (d) { return y(d.oil); });
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("YearlyOilProduction.csv", function (error, data)
{
data.forEach(function (d) {
d.year = parseDate(d.year);
d.oil = +d.oil;
});
x.domain(d3.extent(data, function (d) { return d.year; }));
y.domain(d3.extent(data, function (d) { return d.oil; }));
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("million Sm3");
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
});
</script>
I need some help with my following D3 line chart, where x is a time domain and y is linear scale value, currently in this fiddle, the transition of path occurs from right to left, but I want it to happen as left to right instead.
var data = [{"closedate":"2013-12-07T08:00:00.000Z","amount":60000}];
//Set Canvas Area properites
var margin = {top: 50, right: 50, bottom: 100, left: 100},
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
//X value transformation function - transforms close date into chart x position of canvas
var x = d3.time.scale()
.range([0, width])
.domain(d3.extent(data, function(d) { return new Date(d.closedate); }));
//Y Value transformation function - transforms amount into y position of canvas
var y = d3.scale.linear()
.range([height, 0])
.domain(d3.extent(data, function(d) { return d.amount; }));
//X Axis Function
var xAxis = d3.svg.axis()
.scale(x)
//.tickFormat(d3.time.format('%m/%y'))
.ticks(6)
.orient("bottom");
//Y Axis Function
var yAxis = d3.svg.axis().scale(y).ticks(6).orient("left");
//Line Function to draw SVG Line
var line = d3.svg.line()
.interpolate("cardinal")
.x(function(d) { return x(new Date(d.closedate)); })
.y(function(d) { return y(d.amount); });
//Create SVG canvas area with height and width properites
var svg = d3.select("#d3linechartid").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 + ")");
//console.log("data = "+JSON.stringify(data));
//Draw XAxis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", width )
.attr("y", "50")
.style("text-anchor", "middle")
.text("Close Date");
//Draw YAxis
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "middle")
.text("Sales Amount ($)");
//Draw SVG Path
var path = svg.append("path")
.datum(data)
.attr("d", line)
.style('fill', 'none')
.style('stroke', 'steelblue')
.attr("stroke-width", "2");
//Do Transistion of Path
var totalLength = path.node().getTotalLength();
path
.attr("stroke-dasharray", totalLength+","+totalLength)
.attr("stroke-dashoffset", totalLength)
.transition()
.duration(2000)
.ease("linear-in-out")
.attr("stroke-dashoffset", 0);
You can sort the input data in ascending order, like so:
data.sort(function(a, b){ return d3.ascending(a.closedate, b.closedate); });