I am not sure if I am messing it up, kinda new to javascript, what I am trying to do is showing some text when mouse enters a specific region and hide it when it leaves. You can find a fully working example of what I am trying to do at this link.
Somehow I needed to encapsulate this code and what I did was something like below (anyways, just so you don't lose time, this code is almost a copy and paste from the link above, I just encapsulated it into a function and changed the way it consumed data):
function candlestickChart(targetContainer, data) {
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("%d-%b-%y").parse,
timeFormat = d3.time.format('%Y-%m-%d'),
valueFormat = d3.format(',.2fs');
var x = techan.scale.financetime()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var candlestick = techan.plot.candlestick()
.xScale(x)
.yScale(y);
var trendline = techan.plot.trendline()
.xScale(x)
.yScale(y)
.on("mouseenter", enter)
.on("mouseout", out)
.on("drag", drag);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select(targetContainer).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 valueText = svg.append('text')
.style("text-anchor", "end")
.attr("class", "coords")
.attr("x", width - 5)
.attr("y", 15);
accessor = candlestick.accessor();
data = data.slice(0, 3500).map(function (data) {
return {
date: new Date(data.date),
open: +data.open,
high: +data.high,
low: +data.low,
close: +data.close,
volume: +data.volume
}
}).sort(function (a, b) { return d3.ascending(accessor.d(a), accessor.d(b)); });
var trendlineData = [
{ start: { date: new Date(2014, 2, 11), value: 72.50 }, end: { date: new Date(2014, 5, 9), value: 63.34 } },
{ start: { date: new Date(2013, 10, 21), value: 43 }, end: { date: new Date(2014, 2, 17), value: 70.50 } }
];
x.domain(data.map(accessor.d));
y.domain(techan.scale.plot.ohlc(data, accessor).domain());
svg.append("g")
.datum(data)
.attr("class", "candlestick")
.call(candlestick);
svg.append("g")
.datum(trendlineData)
.attr("class", "trendlines")
.call(trendline)
.call(trendline.drag);
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("Price ($)");
function enter(d) {
valueText.style("display", "inline");
refreshText(d);
}
function out(d) {
valueText.style("display", "none");
}
function drag(d) {
refreshText(d);
}
function refreshText(d) {
valueText.text(
"Start: [" + timeFormat(d.start.date) + ", " + valueFormat(d.start.value) +
"] End: [" + timeFormat(d.end.date) + ", " + valueFormat(d.end.value) + "]"
);
}
}
After doing that, mouseenter and mouseout events stopped fireing, am I getting it wrong?
Related
In a web application I was supposed to create a vertically grouped bar chart using d3.js using json data. Previously I create a horizontal grouped bar using the following code. Can anyone help me out? Thanks in advance.
var data = {
labels: [
'resilience', 'maintainability', 'accessibility',
'uptime', 'functionality', 'impact'
],
series: [
{
label: '2012',
values: [4, 8, 15, 16, 23, 42]
},
{
label: '2013',
values: [12, 43, 22, 11, 73, 25]
},
{
label: '2014',
values: [31, 28, 14, 8, 15, 21]
},]
};
var chartWidth = 300,
barHeight = 20,
groupHeight = barHeight * data.series.length,
gapBetweenGroups = 10,
spaceForLabels = 150,
spaceForLegend = 150;
// Zip the series data together (first values, second values, etc.)
var zippedData = [];
for (var i=0; i<data.labels.length; i++) {
for (var j=0; j<data.series.length; j++) {
zippedData.push(data.series[j].values[i]);
}
}
// Color scale
var color = d3.scale.category20();
var chartHeight = barHeight * zippedData.length + gapBetweenGroups * data.labels.length;
var x = d3.scale.linear()
.domain([0, d3.max(zippedData)])
.range([0, chartWidth]);
var y = d3.scale.linear()
.range([chartHeight + gapBetweenGroups, 0]);
var yAxis = d3.svg.axis()
.scale(y)
.tickFormat('')
.tickSize(0)
.orient("left");
// Specify the chart area and dimensions
var chart = d3.select(".chart")
.attr("width", spaceForLabels + chartWidth + spaceForLegend)
.attr("height", chartHeight);
// Create bars
var bar = chart.selectAll("g")
.data(zippedData)
.enter().append("g")
.attr("transform", function(d, i) {
return "translate(" + spaceForLabels + "," + (i * barHeight + gapBetweenGroups * (0.5 + Math.floor(i/data.series.length))) + ")";
});
// Create rectangles of the correct width
bar.append("rect")
.attr("fill", function(d,i) { return color(i % data.series.length); })
.attr("class", "bar")
.attr("width", x)
.attr("height", barHeight - 1);
// Add text label in bar
bar.append("text")
.attr("x", function(d) { return x(d) - 3; })
.attr("y", barHeight / 2)
.attr("fill", "red")
.attr("dy", ".35em")
.text(function(d) { return d; });
// Draw labels
bar.append("text")
.attr("class", "label")
.attr("x", function(d) { return - 10; })
.attr("y", groupHeight / 2)
.attr("dy", ".35em")
.text(function(d,i) {
if (i % data.series.length === 0)
return data.labels[Math.floor(i/data.series.length)];
else
return ""});
chart.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + spaceForLabels + ", " + -gapBetweenGroups/2 + ")")
.call(yAxis);
// Draw legend
var legendRectSize = 18,
legendSpacing = 4;
var legend = chart.selectAll('.legend')
.data(data.series)
.enter()
.append('g')
.attr('transform', function (d, i) {
var height = legendRectSize + legendSpacing;
var offset = -gapBetweenGroups/2;
var horz = spaceForLabels + chartWidth + 40 - legendRectSize;
var vert = i * height - offset;
return 'translate(' + horz + ',' + vert + ')';
});
legend.append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.style('fill', function (d, i) { return color(i); })
.style('stroke', function (d, i) { return color(i); });
legend.append('text')
.attr('class', 'legend')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.text(function (d) { return d.label; });
After continuous digging I found the correct way of doing this. Thanks to Mike Bostock for the example he provided in here. In here you can also find out the elaborate discussion of that example. Thanks for your support :)
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
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(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
//console.log(margin.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 + ")");
/*Our json object is [{letter: "A", frequency: .08167,depth:.32},{letter: "B", frequency: .01492,depth:.69}]
To use csv file you just need to follow the link I provided
*/
var data = [
{letter: "A", frequency: .08167,depth:.32},
{letter: "B", frequency: .01492,depth:.69}
];
var groupNames=d3.keys(data[0]).filter(function(key){return key!="letter";})
data.forEach(function(d){
d.groups=groupNames.map(function(name){return {name:name,value:+d[name]};})
});
x0.domain(data.map(function(d){return d.letter;}));
x1.domain(groupNames).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0,d3.max(data,function(d){
return d3.max(d.groups,function(d){
return d.value;
});
})]);
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("Letter Fun");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x0(d.letter) + ",0)"; });
state.selectAll("rect")
.data(function(d) { return d.groups; })
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) { return x1(d.name); })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); })
.style("fill", function(d) { return color(d.name); });
Please let me know if you have anything to know about the code.
This is my very first to d3js.I have use this d3js Line Chart Sample.But after feeding the data it doesn't draw the chart but i can see the data has been loaded by using the firebug.But the data doesn't print in the graph at all. Could n't figure out the problem.Any help will be really appreciated.
This 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("%d-%b").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.timeStamp);
})
.y(function(d) {return y(d.memberAverageLoadAverage); });
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 json1=[
{
"clusterId": "",
"timeStamp": 1437063744524,
"memberAverageLoadAverage": 20,
"memberId": ""
},
{
"clusterId": "",
"timeStamp": 1437069850060,
"memberAverageLoadAverage": 20,
"memberId": ""
},
{
"clusterId": "",
"timeStamp": 1437069910059,
"memberAverageLoadAverage": 20,
"memberId": ""
},
{
"clusterId": "",
"timeStamp": 1437069970060,
"memberAverageLoadAverage": 20,
"memberId": ""
},
{
"clusterId": "",
"timeStamp": 1437070030056,
"memberAverageLoadAverage": 20,
"memberId": ""
}
];
root = json1;
x.domain(d3.extent(root, function(d) { return d.timeStamp; }));
y.domain(d3.extent(root, function(d) { return d.memberAverageLoadAverage; }));
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("memberAverageLoadAverage");
svg.append("path")
.datum(root)
.attr("class", "line")
.attr("d", line);
After removing the JSON.parse for the JS object and changing the memberAverageLoadAverage to not all be the same value, I was able to display a graph. The reason I needed to change the memberAverageLoadAverage values is that the extent call was making the y axis go from 20 to 20 so the line was at the bottom of the screen and collided with the x axis line. I would suggest setting the y.domain to [0, d3.max(...)] instead of using d3.extent.
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("%d-%b").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.timeStamp);
})
.y(function(d) {return y(d.memberAverageLoadAverage); });
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 json1=[{"clusterId":"","timeStamp":1437063744524,"memberAverageLoadAverage":11,"memberId":""},{"clusterId":"","timeStamp":1437069850060,"memberAverageLoadAverage":5,"memberId":""},{"clusterId":"","timeStamp":1437069910059,"memberAverageLoadAverage":6,"memberId":""},{"clusterId":"","timeStamp":1437069970060,"memberAverageLoadAverage":15,"memberId":""},{"clusterId":"","timeStamp":1437070030056,"memberAverageLoadAverage":20,"memberId":""}];
var data = json1;
x.domain(d3.extent(data, function(d) { return d.timeStamp; }));
y.domain([0, d3.max(data, function(d) { return d.memberAverageLoadAverage; })]);
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("Price ($)");
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Should be a comment, but I suggest a couple of things. 1. I suggest using externally loaded JSON data if you have a server you can use to get the http request. If not, then you can use local data, but either way you have to have a data.foreach function in which you create all of your values, similar to the oneseen below.
data.foreach(function(d) {
d.timeStamp = d.timeStamp;
d.memberAverageLoadAverage = +d.memberAverageLoadAverage;
});
I also strongly suggest you reformat your JSON because your keys are not done phenomenally well, so I suggest you take a look here and reformat the data. Let me know how you do and what else I can help you with.
I am not sure if you can parse this. It is an array. Anyways, even if you can, I don't think there is a need to parse it.
`var json1=`[{"clusterId":"","timeStamp":1437063744524,"memberAverageLoadAverage":20,"memberId":""},
I am working with Techan JS, with d3 tip plugin.
Callback function of D3-Tip is passed the whole data array instead of object in context. I am probably hooking it on the wrong place.
/* Initialize tooltip */
var tip = d3.tip().attr('class', 'd3-tip').html(function(d) {
console.log(d);
return d;
});
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var parseDate = d3.time.format("%d-%b-%y").parse,
timeFormat = d3.time.format('%Y-%m-%d'),
valueFormat = d3.format(',.2fs');
var x = techan.scale.financetime()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var candlestick = techan.plot.candlestick()
.xScale(x)
.yScale(y);
var trendline = techan.plot.trendline()
.xScale(x)
.yScale(y)
.on("mouseenter", enter)
.on("mouseout", out)
.on("drag", drag);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("#candle-stick").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 valueText = svg.append('text')
.style("text-anchor", "end")
.attr("class", "coords")
.attr("x", width - 5)
.attr("y", 15);
var data = [
{ date: "9-Jun-14", open: 62.40, high: 63.34, low: 61.79, close: 62.88, volume: 37617413 },
{ date: "6-Jun-14",open: 63.37, high: 63.48, low: 62.15, close: 62.50,volume: 42442096 },
{ date: "5-Jun-14",open: 63.66, high: 64.36, low: 62.82, close: 63.19,volume: 47352368 },
{ date: "4-Jun-14",open: 62.45, high: 63.59, low: 62.07, close: 63.34,volume: 36513991 },
{ date: "3-Jun-14",open: 62.62, high: 63.42, low: 62.32, close: 62.87,volume: 32216707 },
{ date: "2-Jun-14",open: 63.23, high: 63.59, low: 62.05, close: 63.08,volume: 35995537 },
{ date: "30-May-14",open: 63.95, high: 64.17, low: 62.56, close: 63.30,volume: 45283577 }
];
var accessor = candlestick.accessor();
data = data.slice(0,200).map(function(d) {
return {
date: parseDate(d.date),
open: +d.open,
high: +d.high,
low: +d.low,
close: +d.close,
volume: +d.volume
};
}).sort(function(a, b) { return d3.ascending(accessor.d(a), accessor.d(b)); });
x.domain(data.map(accessor.d));
y.domain(techan.scale.plot.ohlc(data, accessor).domain());
svg.append("g")
.datum(data)
.attr("class", "candlestick")
.call(candlestick)
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
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("Price ($)");
/* Invoke the tip in the context of your visualization */
svg.call(tip)
// functions
function enter(d) {
valueText.style("display", "inline");
refreshText(d);
}
function out(d) {
valueText.style("display", "none");
}
You can see the code live at http://jsfiddle.net/sisir/ghox8ewa/1/
(look at the console when hovering on a candlestick)
/* Initialize tooltip */
var tip = d3.tip().attr('class', 'd3-tip').html(function(d) {
console.log(d);
return d;
});
In the above tooltip you are returning d for html, change it to
/* Initialize tooltip */
var tip = d3.tip().attr('class', 'd3-tip').html(function(d, i) {
return d[i].open;//your required text here
});
Hope this is what you are looking for....
If not ask for more.
The problem in the above chart is the approach we are following,
we are drawing candlestick and binding tooltip to this candlestick by writing below code
svg.append("g")
.datum(data)
.attr("class", "candlestick")
.call(candlestick)
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
from the above code that will return a 'g' of class 'candlestick'
(to view that write this code
var candle= svg.append("g")
.datum(data)
.attr("class", "candlestick")
.call(candlestick)
console.log(candle);
) and we are binding tooltip to that so it is returning data(whole data object) as argument to our tooltip,
To fulfill our requirement,
I've implemented and developed required code in the below fiddle
http://jsfiddle.net/ghox8ewa/5/
Kindly follow the link and try to analyze....
If you still have doubts ask me for more.
I'm having a bizarre d3 issue wherein my y-axis transition results in the axis switching sides. Besides that, I am happy with how the transition looks. A gif that demonstrates the issue is available at https://i.imgflip.com/g4kdc.gif. I have followed a few examples including http://bl.ocks.org/mbostock/4323929, but can't seem to figure out the issue.
var dataset = [{
"year_decided": 1982,
"Total": 0
}, //some more data
{
"year_decided": "2000",
"Total": "310"
}]; // default dataset that we can access and override
var margin = {
top: 30,
right: 20,
bottom: 20,
left: 35
};
var w = $("#section").width() - margin.left - margin.right;
var h = $("#section").height() - margin.top - margin.bottom;
///create the default scales
var xScale = d3.scale.linear()
.domain([0,dataset.length])
.range([0,w]);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset,function(d){ return +d.Total }) ])
.range([h,0]);
// create the axes
var xAxis = d3.svg.axis()
.scale(xScale)
.tickSize(6, 0)
.orient("bottom")
.tickFormat(function(d,i){
return d + 1982;
});
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("right")
.tickSize(w);
//define the svg and add it to the document
var svg = d3.select("#section").append("svg")
.attr("width",w + margin.left + margin.right)
.attr("height",h + margin.top + margin.bottom)
.attr("id", "main-chart");
svg.append("g")
.attr("transform","translate(" + margin.left + "," + margin.top + ")");
//add an axis group and add the y axis
var gy = svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.call(customAxis)
var gx = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + margin.left + "," + h + ")")
.call(xAxis);
//create the line
var line = d3.svg.line()
.x(function(d, i){ return xScale(i) })
.y(function(d){ return yScale(+d.Total) })
.interpolate("linear");
svg.append('path')
.classed('data-line', true)
.attr('d', line(dataset))
.attr("transform", "translate(" + margin.left + ",0)");
//create the tooltip
var focus = svg.append("g")
.attr("class", "focus")
.style("display", "none");
focus.append("circle")
.attr("r", 4.5)
.attr("transform", "translate(" + margin.left + ",0)")
;
var tool_tip_year = focus.append("text")
.attr("x", 9)
.attr("dy", ".35em")
.attr("transform", "translate(" + margin.left + ",0)")
;
var tool_tip_total = focus.append("text")
.attr("x", 9)
.attr("dy", "1.8em")
.attr("transform", "translate(" + margin.left + ",0)")
;
svg.append("rect")
.attr("class", "overlay")
.attr("width", w)
.attr("height", h)
.attr("transform", "translate(" + margin.left + ",0)")
.on("mouseover", function() { focus.style("display", null); })
.on("mouseout", function() { focus.style("display", "none"); })
.on("mousemove", mousemove);
var bisectIndex = d3.bisector(function(d, i) { return i; }).left;
function mousemove() {
var x0 = xScale.invert(d3.mouse(this)[0]),
i = Math.round(x0),
d = dataset[i];
focus.attr("transform", "translate(" + xScale(i) + "," + yScale(+d.Total) + ")");
tool_tip_year.text(1982 + i);
tool_tip_total.text(d3.format(",")(+d.Total));
}
function customAxis(g){
g.selectAll("text")
.attr("x",4)
.attr("dy",-4);
}
//update the graph following http://bl.ocks.org/d3noob/7030f35b72de721622b8
$("#submission").submit(function(){
//define url to request
var submission = "php/data.php?word=" + $("#submission-text").val();
//request json and save as dataset
d3.json(submission, function(error, json) {
if (error) return console.warn(error);
dataset = json;
//rescale the graphs
xScale = d3.scale.linear()
.domain([0,dataset.length])
.range([0,w]);
yScale = d3.scale.linear()
.domain([0, d3.max(dataset,function(d){ return +d.Total }) ])
.range([h,0]);
gy.transition()
.duration(2500)
.call(yAxis);
gy.call(customAxis);
svg.select(".data-line")
.transition()
.duration(2000)
.attr("d",line(dataset));
})
});
I tried now couple of things but I can not figure out why my ticks are wrong positioned. I used different sources to make this stacked barchart.
Here is the fiddle of my code: http://jsfiddle.net/azj7guec/
And here is the code itself:
var margin = {top: 20, right: 20, bottom: 70, left: 40},
width = 1000 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
x = d3.scale.ordinal().rangeRoundBands([0, width], .50);
y = d3.scale.linear().range([height, 0]);
z = d3.scale.ordinal().range(["darkblue", "blue", "lightblue"])
console.log("RAW MATRIX---------------------------");
// 4 columns: ID,c1,c2,c3
var matrix = [
[22,45,34,65],
[23,66,12,22],
[24,32,44,76],
[25,12,76,32],
[26, 67, 34, 56]
];
console.log(matrix)
var keys = matrix.map(function(item){return item[0]});
console.log("REMAP---------------------------");
var remapped =["c1","c2","c3"].map(function(dat,i){
return matrix.map(function(d,ii){
return {x: d[0], y: d[i+1] };
})
});
console.log(remapped)
console.log("LAYOUT---------------------------");
var stacked = d3.layout.stack()(remapped)
console.log(stacked)
//var yMax= d3.max(stacked)
x.domain(keys);
y.domain([0, d3.max(stacked[stacked.length - 1], function(d) { return d.y0 + d.y; })]);
// show the domains of the scales
console.log("x.domain(): " + x.domain())
console.log("y.domain(): " + y.domain())
console.log("------------------------------------------------------------------");
var yAxis = d3.svg.axis()
.scale(y)
.ticks(10)
.orient("left");
var xAxis = d3.svg.axis()
.scale(x)
.tickValues(keys)
.orient("bottom");
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)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function(d) {
return "rotate(-65)"
});
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("Open Issues");
// Add a group for each column.
var valgroup = svg.selectAll("g.valgroup")
.data(stacked)
.enter().append("g")
.attr("class", "valgroup")
.style("fill", function(d, i) { return z(i); })
.style("stroke", function(d, i) { return d3.rgb(z(i)).darker(); });
// Add a rect for each date.
var rect = valgroup.selectAll("rect")
.data(function(d){return d;})
.enter().append("rect")
.attr("width", 20)
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return y(d.y0 + d.y); })
.attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); });
//.attr("width", x.rangeBand());
Hope someone can help me.
The ordinal scale divides its output range into intervals based on the input domain. Your current positioning puts the bars at the beginning of those intervals, whereas the ticks are in the center. To match up the positions, add half the interval minus half the bar width to the beginning of the interval:
.attr("x", function(d) { return x(d.x) + (x.rangeBand() - 20) / 2; })
Complete demo here.