d3.on("mouseover") occurring before mouseover - javascript

This is a d3 bar chart. line 162 ,
.on("mouseover", console.log("I am on it"))
should only happen when user is over a bar on the bar chart, but the log is output from the time the page loads.
The running code is here, https://shanegibney.github.io/d3Mouseover/
The full code is here, https://github.com/shanegibney/d3Mouseover
<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
body {
font-family: avenir next, sans-serif;
font-size: 12px;
}
.zoom {
cursor: move;
fill: none;
pointer-events: all;
}
.axis {
stroke-width: 0.5px;
stroke: #888;
font: 10px avenir next, sans-serif;
}
.axis>path {
stroke: #888;
}
</style>
<body>
<div id="totalDistance">
</div>
</body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
/* Adapted from: https://bl.ocks.org/mbostock/34f08d5e11952a80609169b7917d4172 */
var margin = {
top: 20,
right: 20,
bottom: 90,
left: 50
},
margin2 = {
top: 230,
right: 20,
bottom: 30,
left: 50
},
width = 960 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom,
height2 = 300 - margin2.top - margin2.bottom;
var parseTime = d3.timeParse("%Y-%m-%d %H:%M");
var x = d3.scaleTime().range([0, width]),
x2 = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
y2 = d3.scaleLinear().range([height2, 0]),
dur = d3.scaleLinear().range([0, 12]);
var xAxis = d3.axisBottom(x).tickSize(0),
xAxis2 = d3.axisBottom(x2).tickSize(0),
yAxis = d3.axisLeft(y).tickSize(0);
var brush = d3.brushX()
.extent([
[0, 0],
[width, height2]
])
.on("start brush end", brushed);
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([
[0, 0],
[width, height]
])
.extent([
[0, 0],
[width, height]
])
.on("zoom", zoomed);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
d3.json("dataDefault.json", function(error, data) {
if (error) throw error;
var parseTime = d3.timeParse("%Y-%m-%d %H:%M");
var mouseoverTime = d3.timeFormat("%a %e %b %Y %H:%M");
var minTime = d3.timeFormat("%b%e, %Y");
var parseDate = d3.timeParse("%b %Y");
data.forEach(function(d) {
d.mouseoverDisplay = parseTime(d.date);
d.date = parseTime(d.date);
d.end = parseTime(d.end);
d.duration = ((d.end - d.date) / (60 * 1000)); // session duration in minutes
d.distance = +d.distance;
d.intensityInverted = (1 / (d.distance / d.duration)); // inverse of intensity so that the light colour is for low intensity and dark colour is for high intensity
d.intensity = Math.round(d.distance / d.duration); // actually intensity, metres per minute.
d.course = d.course.toLowerCase();
return d;
},
function(error, data) {
if (error) throw error;
});
var total = 0;
data.forEach(function(d) {
total = d.distance + total;
});
var minDate = d3.min(data, function(d) {
return d.date;
});
total = String(total).replace(/(.)(?=(\d{3})+$)/g, '$1,') //place thousands comma in total distance string
var xMin = d3.min(data, function(d) {
return d.date;
});
var yMax = Math.max(20, d3.max(data, function(d) {
return d.distance;
}));
dur.domain([0, d3.max(data, function(d) {
return d.duration;
})]);
var colorScale = d3.scaleSequential(d3.interpolateInferno)
.domain([0, d3.max(data, function(d) {
return d.intensityInverted;
})]);
var totalDistance = d3.select("#totalDistance").append("p").text("Total distance: " + total + "m");
x.domain([xMin, new Date()]);
y.domain([0, yMax]);
x2.domain(x.domain());
y2.domain(y.domain());
// append scatter plot to main chart area
var messages = focus.append("g");
messages.attr("clip-path", "url(#clip)");
messages.selectAll("message")
.data(data)
.enter().append("rect")
.style("fill", function(d) {
return colorScale(d.intensityInverted);
})
.attr("class", "message")
.attr("x", function(d) {
return x(d.date);
})
.attr("y", function(d) {
return y(d.distance);
})
.attr("width", function(d) {
return dur(d.duration);
})
.attr("height", function(d) {
return height - y(d.distance);
})
// .on("mouseover", onit);
.on("mouseover", () => console.log("I am now on it for sure!"));
// function onit(d) {
// console.log("I am on it now!")
// }
focus.append("g")
.attr("class", "axis x-axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
// Summary Stats
focus.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x", 0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Distance in meters");
// focus.append("text")
// .attr("x", width - margin.right)
// .attr("dy", "1em")
// .attr("text-anchor", "end")
// // .text("Messages: " + num_messages(data, x));
// .text("Total distance: " + total + "m");
svg.append("text")
.attr("transform",
"translate(" + ((width + margin.right + margin.left) / 2) + " ," +
(height + margin.top + margin.bottom) + ")")
.style("text-anchor", "middle")
.text("Date");
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
// append scatter plot to brush chart area
var messages = context.append("g");
messages.attr("clip-path", "url(#clip)");
messages.selectAll("message")
.data(data)
.enter().append("rect")
.style("fill", function(d) {
return colorScale(d.intensityInverted);
})
.attr("class", "message")
.attr("x", function(d) {
return x2(d.date);
})
.attr("y", function(d) {
return y2(d.distance);
})
.attr("width", function(d) {
return dur(d.duration);
})
.attr("height", function(d) {
return height2 - y2(d.distance);
});
context.append("g")
.attr("class", "axis x-axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
});
//create brush function redraw scatterplot with selection
function brushed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
var s = d3.event.selection || x2.range();
x.domain(s.map(x2.invert, x2));
focus.selectAll(".message")
.attr("x", function(d) {
return x(d.date);
})
.attr("y", function(d) {
return y(d.distance);
})
.attr("width", function(d) {
return dur(d.duration);
})
.attr("height", function(d) {
return height - y(d.distance);
});
focus.select(".x-axis").call(xAxis);
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(width / (s[1] - s[0]))
.translate(-s[0], 0));
var e = d3.event.selection;
var selectedMessages = focus.selectAll('.message').filter(function() {
var xValue = this.getAttribute('x');
return e[0] <= xValue && xValue <= e[1];
});
// console.log(selectedMessages.nodes().length);
}
function zoomed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
var t = d3.event.transform;
x.domain(t.rescaleX(x2).domain());
focus.selectAll(".message")
// .enter().append("rect")
// .style("fill", function(d) {
// return colorScale(d.intensityInverted);
// })
// .attr("class", "message")
.attr("x", function(d) {
return x(d.date);
})
.attr("y", function(d) {
return y(d.distance);
})
.attr("width", function(d) {
return dur(d.duration);
})
.attr("height", function(d) {
return height - y(d.distance);
});
focus.select(".x-axis").call(xAxis);
context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
}
function handleMouseOver(d) {
d3.select(this)
.style("fill", "lightBlue");
g.select('text')
.attr("x", 15)
.attr("y", 5)
.text("Session no. " + d.number)
.append('tspan')
.text("Date: " + mouseoverTime(d.mouseoverDisplay))
.attr("x", 15)
.attr("y", 30)
.append('tspan')
.text("Distance: " + d.distance + "m")
.attr("x", 15)
.attr("y", 50)
.append('tspan')
.text("Duration: " + d.duration + " mins")
.attr("x", 15)
.attr("y", 70)
.append('tspan')
.text("Intensity: " + d.intensity + " meters/mins")
.attr("x", 15)
.attr("y", 90)
.append('tspan')
.text("Pool: " + d.pool + " (" + d.course + ")")
.attr("x", 15)
.attr("y", 110);
console.log("handleMouseOver function");
}
function handleMouseOut(d) {
d3.select(this)
.style("fill", function(d) {
return colorScale(d.intensityInverted);
});
g.select('text').text("Total distance since " + minTime(minDate) + ": " + total + "m");
}
</script>
Sample data,
[{
"number": "1",
"date": "2016-11-09 11:15",
"end": "2016-11-09 11:45",
"distance": "1100",
"course": "LC",
"pool": "UCD"
},
{
"number": "2",
"date": "2016-11-10 10:40",
"end": "2016-11-10 11:20",
"distance": "1500",
"course": "LC",
"pool": "UCD"
},
{
"number": "3",
"date": "2016-11-11 16:45",
"end": "2016-11-11 17:50",
"distance": "2000",
"course": "LC",
"pool": "UCD"
},
{
"number": "4",
"date": "2016-11-12 12:48",
"end": "2016-11-12 13:53",
"distance": "2500",
"course": "LC",
"pool": "UCD"
}
]
I added the last two lines here, but still no luck,
var messages = focus.append("g");
messages.attr("clip-path", "url(#clip)");
messages.selectAll("message")
.data(data)
.enter().append("rect")
.style("fill", function(d) {
return colorScale(d.intensityInverted);
})
.attr("class", "message")
.attr("x", function(d) {
return x(d.date);
})
.attr("y", function(d) {
return y(d.distance);
})
.attr("width", function(d) {
return dur(d.duration);
})
.attr("height", function(d) {
return height - y(d.distance);
})
// .on("mouseover", onit);
.on("mouseover", () => console.log("I am now on it for sure!"));
// function onit(d) {
// console.log("I am on it now!")
// }
I suspect the problem is because I am using brushX() and zoom.

When you do this:
.on("mouseover", console.log("I am on it"))
You're passing the result of the console.log function to the callback. Instead of that, you want to pass its reference:
.on("mouseover", function(){
console.log("I am on it")
})
Check this snippet (don't hover over the circle!):
var circle = d3.select("circle");
circle.on("mouseover", console.log("I'm on it!"));
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg>
<circle cx="50" cy="50" r="15" fill="teal"></circle>
</svg>
Now the same code, with the reference to console.log:
var circle = d3.select("circle");
circle.on("mouseover", () => console.log("I'm on it!"));
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg>
<circle cx="50" cy="50" r="15" fill="teal"></circle>
</svg>

The issue is that you are calling the function at the time you are declaring it:
.on("mouseover", console.log("I am on it")) //function call
should be something like this:
.on("mouseover", console.log) //function ref
.on("mouseover", function(d) { console.log("I am on it") }) //function ref

Related

Multiline chart x-axis ticks not aligned with data points

I am trying to draw a multi line chart with D3.js. The chart is drawn properly but the x-axis ticks are not aligned correctly with the data points circle.
Find the example code here: https://jsfiddle.net/gopal31795/qsLd7pc5/9/
I assume that there is some error in the code for creating the dots.
// Creating Dots on line
segment.selectAll("dot")
.data(function(d) {
return d.linedata;
})
.enter().append("circle")
.attr("r", 5)
.attr("cx", function(d) {
//return x(parseDate(new Date(d.mins))) + x.rangeBand() / 2;
return x(d.mins);
})
.attr("cy", function(d) {
return y(d.value);
})
.style("stroke", "white")
.style("fill", function(d) {
return color(this.parentNode.__data__.name);
})
.on("mouseenter", function(d) {
d3.select(this).transition().style("opacity", "0.25");
tooltip.html("<span style='color:" + color(this.parentNode.__data__.name) + ";'>" + this.parentNode.__data__.name + "</span>: " + (d.value + "s")).style("visibility", "visible").style("top", (event.pageY + 10) + "px").style("left", (event.pageX) + "px");
})
.on("mouseleave", function(d) {
d3.select(this).transition().style("opacity", "1");
tooltip.style("visibility", "hidden");
});
The problem in your code (which uses the old v3) is that you're using rangeRoundBands. That would be the correct choice if you had a bar chart, for instance.
However, since you're dealing with data points, you should use rangePoints or rangeRoundPoints, which:
Sets the output range from the specified continuous interval. The array interval contains two elements representing the minimum and maximum numeric value. This interval is subdivided into n evenly-spaced points, where n is the number of (unique) values in the input domain.
So, it should be:
var x = d3.scale.ordinal()
.rangeRoundPoints([0, width]);
Here is your code with that change:
var Data = [{
"name": "R",
"linedata": [{
"mins": 0,
"value": 1120
},
{
"mins": 2,
"value": 1040
},
{
"mins": 4,
"value": 1400
},
{
"mins": 6,
"value": 1500
}
]
},
{
"name": "E",
"linedata": [{
"mins": 0,
"value": 1220
},
{
"mins": 2,
"value": 1500
},
{
"mins": 4,
"value": 1610
},
{
"mins": 6,
"value": 1700
}
]
}
];
var margin = {
top: 20,
right: 90,
bottom: 35,
left: 90
},
width = $("#lineChart").width() - margin.left - margin.right,
height = $("#lineChart").width() * 0.3745 - margin.top - margin.bottom;
//var parseDate = d3.time.format("%d-%b");
var x = d3.scale.ordinal()
.rangeRoundPoints([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5);
var xData = Data[0].linedata.map(function(d) {
return d.mins;
});
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) {
return x(d.mins);
})
.y(function(d) {
return y(d.value);
});
function transition(path) {
path.transition()
.duration(4000)
.attrTween("stroke-dasharray", tweenDash);
}
function tweenDash() {
var l = this.getTotalLength(),
i = d3.interpolateString("0," + l, l + "," + l);
return function(t) {
return i(t);
};
}
var svg = d3.select("#lineChart").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 + ")");
color.domain(Data.map(function(d) {
return d.name;
}));
x.domain(xData);
var valueMax = d3.max(Data, function(r) {
return d3.max(r.linedata, function(d) {
return d.value;
})
});
var valueMin = d3.min(Data, function(r) {
return d3.min(r.linedata, function(d) {
return d.value;
})
});
y.domain([valueMin, valueMax]);
//Drawing X Axis
svg.append("g")
.attr("class", "x-axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "xAxisText")
.attr("x", width)
.attr("dy", "-.41em")
.style("text-anchor", "end")
.style("fill", "white")
.text("Time(m)");
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")
.style("fill", "none")
.style("stroke", "white")
.style("stroke-width", 0.8)
.text("Duration(s)");
// Drawing Lines for each segments
var segment = svg.selectAll(".segment")
.data(Data)
.enter().append("g")
.attr("class", "segment");
segment.append("path")
.attr("class", "line")
.attr("id", function(d) {
return d.name;
})
.attr("visible", 1)
.call(transition)
//.delay(750)
//.duration(1000)
//.ease('linear')
.attr("d", function(d) {
return line(d.linedata);
})
.style("stroke", function(d) {
return color(d.name);
});
// Creating Dots on line
segment.selectAll("dot")
.data(function(d) {
return d.linedata;
})
.enter().append("circle")
.attr("r", 5)
.attr("cx", function(d) {
//return x(parseDate(new Date(d.mins))) + x.rangeBand() / 2;
return x(d.mins);
})
.attr("cy", function(d) {
return y(d.value);
})
.style("stroke", "white")
.style("fill", function(d) {
return color(this.parentNode.__data__.name);
})
.on("mouseenter", function(d) {
d3.select(this).transition().style("opacity", "0.25");
tooltip.html("<span style='color:" + color(this.parentNode.__data__.name) + ";'>" + this.parentNode.__data__.name + "</span>: " + (d.value + "s")).style("visibility", "visible").style("top", (event.pageY + 10) + "px").style("left", (event.pageX) + "px");
})
.on("mouseleave", function(d) {
d3.select(this).transition().style("opacity", "1");
tooltip.style("visibility", "hidden");
});
path {
fill: none;
stroke: black;
}
line {
stroke: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<div class="card-body" id="lineChart">
</div>
Finally, as a tip: don't mix D3 and jQuery.

I am facing problems while making a dragable stacked bar chart in d3 v4. The major issue I am facing is in the translation of svg when dragging

var drag = d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended)
function dragstarted(d) {
d3.event.sourceEvent.stopPropagation();
d3.event.sourceEvent.preventDefault;
start_x_old = +d3.event.x;
}
function dragged(e) {
xDrag.attr("transform", "translate(" + [( d3.event.x - start_x_old), 0] + ")");
xDrag1.attr("transform", "translate(" + [(d3.event.x - start_x_old), height] + ")");
}
function dragended(d) {
start_x_new = event.clientX;
console.log("old`enter code here`", start_x_old);
console.log("new", start_x_new);
//for future use
}`
This is the code that i wrote for drag where xDrag and xDrag1 are elements on which drag is being called. For the entire working code visit the fiddle https://jsfiddle.net/zaarkoevilor/vzqu1wrc/15/
You don't need to play around with start_x_old and start_x_new...
Just set a datum to your selections:
var xDrag = svg.selectAll(".serie")
.datum({x: 0})
.call(drag);
var xDrag1 = svg.selectAll(".axis--x")
.datum({x: 0})
.call(drag);
And use that in your drag:
function dragged(d) {
xDrag.attr("transform", "translate(" + [(d.x = d3.event.x), 0] + ")");
xDrag1.attr("transform", "translate(" + [(d.x = d3.event.x), height] + ")");
}
Here is your updated fiddle: https://jsfiddle.net/z0d8xpjg/
And the same code in the Stack snippet:
var start_x_old, start_x_new = 0,
x_diff, xtranslated,
svg = d3.select("svg"),
margin = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var data = [{
labelName: "Financial Data",
no: 27,
yes: 10
}, {
labelName: "Production & completion data",
no: 24,
yes: 32
}, {
labelName: "Support Center Data",
no: 18,
yes: 21
}];
/*var drag = d3.drag()
.on('start.interrupt', function () {
xDrag.interrupt();
xDrag1.interrupt();
})
.on('start drag', function () {
xDrag.attr("transform", "translate(" + (d3.event.x) + "," + 0 +")")
xDrag1.attr("transform", "translate(" + (d3.event.x) + "," + height +")")
});*/
var drag = d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended)
function dragstarted(d) {
d3.event.sourceEvent.stopPropagation();
d3.event.sourceEvent.preventDefault;
}
function dragged(d) {
//console.log("dragging");
//x_diff = start_x_old - start_x_new;
xDrag.attr("transform", "translate(" + [(d.x = d3.event.x), 0] + ")");
xDrag1.attr("transform", "translate(" + [(d.x = d3.event.x), height] + ")");
}
function dragended(d) {
xDrag.datum({
x: d3.event.x
});
xDrag1.datum({
x: d3.event.x
});
}
data.sort(function(a, b) {
return (b.yes + b.no) - (a.yes + a.no);
});
var x = d3.scaleBand()
.rangeRound([0, width])
.padding(0.1)
.align(0.1);
var y = d3.scaleLinear()
.rangeRound([height, 0]);
var z = d3.scaleOrdinal()
.range(['#42c8c5', '#d05a59']);
var stack = d3.stack();
data.sort(function(a, b) {
return (b.yes + b.no) - (a.yes + a.no);
});
x.domain(data.map(function(d) {
return d.labelName;
}));
y.domain([0, d3.max(data, function(d) {
return (d.yes + d.no);
})]).nice();
z.domain(Object.keys(data[0]).slice(1));
g.selectAll(".serie")
.data(stack.keys(Object.keys(data[0]).slice(1))(data))
.enter().append("g")
.attr("class", "serie")
.attr("fill", function(d) {
return z(d.key);
})
.selectAll("rect")
.data(function(d) {
return d;
})
.enter().append("rect")
.attr("x", function(d) {
return x(d.data.labelName);
})
.attr("y", function(d) {
return y(d[1]);
})
.attr("height", function(d) {
return y(d[0]) - y(d[1]);
})
.attr("width", x.bandwidth());
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.style("text-anchor", "end")
.attr("transform", "rotate(-60)");
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(10, "s"))
.append("text")
.attr("x", 2)
.attr("y", y(y.ticks(10).pop()))
.attr("dy", "0.35em")
.attr("text-anchor", "start")
.attr("fill", "#000");
var xDrag = svg.selectAll(".serie")
.datum({
x: 0
})
.call(drag);
var xDrag1 = svg.selectAll(".axis--x")
.datum({
x: 0
})
.call(drag);
.bar {
fill: steelblue;
}
.axis path {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="700" height="500"></svg>

How to calculate a probability density function in JavaScript

Note In this question, I asked how to add a distribution line to the chart.
This is my current status:
I don’t quite understand how to plot two distributions curves for the histograms. Like this:
This is my code (using D3.js version 4):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
.bar1 rect {
fill: rgba(0,0,255,0.6);
}
.bar1:hover rect{
fill: rgba(0,0,255,0.9);
}
.bar1 text {
fill: #fff;
font: 10px sans-serif;
}
.bar2 rect {
fill: rgba(255,0,0,0.6);
}
.bar2:hover rect{
fill: rgba(255,0,0,0.9);
}
.bar2 text {
fill: #fff;
font: 10px sans-serif;
}
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
function draw(data) {
var allCongruentData = data.map(function(e){ return e.Congruent;});
var allIncongruentData = data.map(function(e){ return e.Incongruent;});
var formatCount = d3.format(",.0f");
var svg = d3.select("svg"),
margin = {top: 10, right: 30, bottom: 30, left: 30},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleLinear()
.rangeRound([0, width])
.domain([8, 36]);
var bins1 = d3.histogram()
.domain(x.domain())
.thresholds(x.ticks(40))
(allCongruentData);
// var curve = d3.line()
// .x(function(d) { return ???; })
// .y(function(d) { return y(d.Congruent); })
// .curve(d3.curveCatmullRom.alpha(0.5));
var bins2 = d3.histogram()
.domain(x.domain())
.thresholds(x.ticks(40))
(allIncongruentData);
var y = d3.scaleLinear()
.domain([0, d3.max(bins1, function(d) { return d.length; })])
.range([height, 0]);
var bar1 = g.selectAll(".bar1")
.data(bins1)
.enter().append("g")
.attr("class", "bar1")
.attr("transform", function(d) { return "translate(" + x(d.x0) + "," + y(d.length) + ")"; });
bar1.append("rect")
.attr("x", 0.5)
.attr("width", x(bins1[0].x1) - x(bins1[0].x0) - 1)
.attr("height", function(d) { return height - y(d.length); });
var bar2 = g.selectAll(".bar2")
.data(bins2)
.enter().append("g")
.attr("class", "bar2")
.attr("transform", function(d) { return "translate(" + x(d.x0) + "," + y(d.length) + ")"; });
bar2.append("rect")
.attr("x", 0.5)
.attr("width", x(bins2[0].x1) - x(bins2[0].x0) - 1)
.attr("height", function(d) { return height - y(d.length); });
bar1.append("text")
.attr("dy", ".75em") // why?
.attr("y", 6)
.attr("x", (x(bins1[0].x1) - x(bins1[0].x0)) / 2)
.attr("text-anchor", "middle")
.text(function(d) { return formatCount(d.length); });
bar2.append("text")
.attr("dy", ".75em") // why?
.attr("y", 6)
.attr("x", (x(bins2[0].x1) - x(bins2[0].x0)) / 2)
.attr("text-anchor", "middle")
.text(function(d) { return formatCount(d.length); });
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
var legend = svg.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + (width - 245) + "," + 40 + ")")
.selectAll("g")
.data(["Congruent", "Incongruent"])
.enter().append("g");
legend.append("text")
.attr("y", function(d, i) {
return i * 30 + 5;
})
.attr("x", 200)
.text(function(d) {
return d;
});
legend.append("rect")
.attr("y", function(d, i) {
return i * 30 - 8;
})
.attr("x", 167)
.attr("width", 20)
.attr("height", 20)
.attr("fill", function(d) {
if (d == "Congruent") {
return 'rgba(0,0,255,0.6';
} else {
return 'rgba(255,0,0,0.6';
}
});
// g.append("path")
// .datum(data)
// .attr("d", line);
}
</script>
</head>
<body>
<h1>Stroop Test</h1>
<svg width="960" height="500"></svg>
<script type="text/javascript">
d3.csv("stroopdata.csv", function(d) {
d.Congruent = +d.Congruent;
d.Incongruent = +d.Incongruent;
return d;
}, draw);
</script>
</body>
</html>
The data looks like this:
Congruent,Incongruent
12.079,19.278
16.791,18.741
9.564,21.214
8.630,15.687
14.669,22.803
12.238,20.878
14.692,24.572
8.987,17.394
9.401,20.762
14.480,26.282
22.328,24.524
15.298,18.644
15.073,17.510
16.929,20.330
18.200,35.255
12.130,22.158
18.495,25.139
10.639,20.429
11.344,17.425
12.369,34.288
12.944,23.894
14.233,17.960
19.710,22.058
16.004,21.157
Any help appreciated.

Coordinated pie chart and bar chart in D3.js

I have a brush coordinated with a bar chart. When the brush is moved and resized the bar chart shows only the filtered bars. In the same page I have a pie chart that isn't coordinated with the bar chart and the brush, but I want it to be. I want that also the pie chart updates its content according to the filtered values. How can I do that?
This is my code, followed by the plnkr link where you can see what I've done so far:
<script type="text/javascript">
var margin = {
top: 20,
right: 20,
bottom: 70,
left: 40,
mid: 20
},
w = 750 - margin.left - margin.right,
h = 300 - margin.top - margin.bottom;
var barPadding = 1;
var padding = 20;
var miniHeight = 60;
var selected;
var svg = d3.select(".outer-wrapper .chart").append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.mid + miniHeight + margin.bottom)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var barsGroup = svg.append('g')
.attr("class","barsGroup");
var miniGroup = svg.append('g')
.attr("class","miniGroup")
.attr("transform","translate(" + 0 + "," + (margin.top + h + margin.mid) + ")");
var brushGroup = svg.append('g')
.attr("class","brushGroup")
.attr("transform","translate(" + 0 + "," + (margin.top + h + margin.mid) + ")");
var w2 = 400;
var h2 = 400;
var outerRadius = w2 / 2;
var innerRadius = w2 / 3;
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.values; });
var color = d3.scale.category20c();
var svg2 = d3.select("body")
.append("svg")
.attr("width", w2)
.attr("height", h2);
d3.csv("data.csv", function(data) {
var dataset = d3.nest()
.key(function(d) {
return d.Year;
})
.sortKeys(d3.ascending)
.rollup(function(values) {
return values.length;
})
.entries(data)
.filter(function(d) {
return d.key != "UNK" && d.key != "VAR" && d.key != 199 && d.key != 211 && d.key != 2017;
});
//SCALES
var xScale = d3.scale.ordinal()
.domain(dataset.map(function(d) {
return d.key
}))
.rangeRoundBands([0, w], 0.05);
var xScaleBrush = d3.scale.ordinal()
.domain(d3.range(dataset.length))
.rangeRoundBands([0, w], 0.05);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) {
return d.values;
})])
.range([h, 0]);
//AXIS
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.tickValues([1900,1920,1930,1940,1950,1960,1970,1980,1990,2000, 2010]);
var yAxis = d3.svg.axis()
.scale(yScale)
.ticks(6)
.orient("left");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)");
svg.append("g")
.attr("class","x2 axis")
.attr("transform", "translate(" + 0 + "," + (margin.top + h + margin.mid + miniHeight) + ")" )
.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")
.append("g")
.attr("class", "axisLabel")
.append("text")
.attr("transform", "translate(" + -(margin.left * 0.8) + "," + (h/2) + "), rotate(-90)")
.style("text-anchor", "middle")
.text("Score");
var brush = d3.svg.brush()
.x(xScaleBrush)
.extent([0, w])
.on("brush", display);
brushGroup.append("g")
.attr("class", "brush")
.call(brush)
.selectAll("rect")
.attr("opacity", 0.5)
.attr("height", miniHeight);
function display() {
selected = xScaleBrush.domain()
.filter(function(d){
return (brush.extent()[0] <= xScaleBrush(d)) && (xScaleBrush(d) <= brush.extent()[1]);
});
var start;
var end;
/* Keep a minimum amount of bars on there to avoid any jank */
if (selected.length > 2) {
start = selected[0];
end = selected[selected.length - 1] + 1;
} else {
start = 0;
end = dataset.length;
}
var updatedData = dataset.slice(start, end);
updateBars(updatedData);
}
function update(grp, data, main) {
grp.selectAll("rect").data(data, function(d) {
return d.key;
})
.attr("x", function(d) {
return xScale(d.key);
})
.attr("y", function(d) {
return main ? yScale(d.values) : 0;
})
.attr("width", function (d) {
return xScale.rangeBand();
})
.attr("height", function(d) {
return main ? h - yScale(d.values) : miniHeight;
});
}
function enter(grp, data, main) {
grp.selectAll("rect").data(data, function(d) {
return d.key;
})
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale(d.key);
})
.attr("y", function(d) {
return main ? yScale( d.values) : 0;
})
.attr("width", function(d) {
return xScale.rangeBand();
})
.attr("height", function(d) {
return main ? h - yScale(d.values) : miniHeight;
})
.attr("fill", function(d) {
var color = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) {
return d.values;
})])
.range([200, 244]);
var deg = color(d.values);
return "hsl(" + deg + ", 100%, 50%)";
})
.on("mouseover", function(d) {
if(main){
d3.select(this)
.attr("fill", "orange");
var xPosition = parseFloat(d3.select(this).attr("x"));
var yPosition = parseFloat(d3.select(this).attr("y")) / 2 + 100;
d3.select("#tooltip")
.style("left", xPosition + "px")
.style("top", yPosition + "px")
.style("z-index", "10")
.select("#value")
.text(d.values);
d3.select("#tooltip")
.select("#key")
.text("Film del " + d.key + " rilasciati su DVD");
d3.select("#tooltip").classed("hidden", false);
}
})
.on("mouseout", function(d) {
d3.select(this)
.transition()
.duration(250)
.attr("fill", function(d) {
var color = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) {
return d.values;
})])
.range([200, 244]);
var deg = color(d.values);
return "hsl(" + deg + ", 100%, 50%)";
});
d3.select("#tooltip").classed("hidden", true);
});
}
function exit(grp, data) {
grp.selectAll("rect").data(data, function(d) {
return d.key;
}).exit()
.remove();
}
function updateBars(data) {
xScale.domain(data.map(function(d) {
return d.key
}));
yScale.domain([0, d3.max(data, function(d) {
return d.values;
})]);
/* Update */
update(barsGroup, data, true);
/* Enter… */
enter(barsGroup, data, true);
/* Exit */
exit(barsGroup, data);
svg.select(".outer-wrapper .chart .y")
.transition()
.duration(10)
.call(yAxis);
svg.select(".outer-wrapper .chart .x")
.transition()
.duration(50)
.call(xAxis);
}
enter(miniGroup, dataset, false);
updateBars(dataset);
var dataset2 = d3.nest()
.key(function(d) { return d.Genre; })
.sortKeys(d3.ascending)
.rollup(function(values) { return values.length; })
.entries(data);
var text = svg2.append("text")
.attr("dx", 200)
.attr("dy", 200)
.attr("font-size", 30)
.style("text-anchor", "middle")
.attr("fill", "#36454f");
var text2 = svg2.append("text")
.attr("dx", 200)
.attr("dy", 230)
.attr("font-size", 20)
.style("text-anchor", "middle")
.attr("fill", "#36454f");
var text3 = svg2.append("text")
.attr("dx", 200)
.attr("dy", 260)
.attr("font-size", 20)
.style("text-anchor", "middle")
.attr("fill", "#36454f");
//Set up groups
var arcs = svg2.selectAll("g.arc")
.data(pie(dataset2))
.enter()
.append("g")
.attr("class", "arc")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")")
.on("mouseover", function(d) {
var total = data.length;
var percent = Math.round(1000 * d.value / total) / 10;
text.text(d.data.key).attr("class", "inner-circle");
text2.text(d.value + " DVD");
text3.text(percent +"%");
})
.on("mouseout", function(d) {
text.text(function(d) { return ""; });
text2.text(function(d) { return ""; });
text3.text(function(d) { return ""; });
});
//Draw arc paths
arcs.append("path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
});
</script>
http://plnkr.co/edit/cwNl6zUSOM4yPmUtSRr4?p=preview
You can do that by transforming the part where you build the pieChart into a function that receives the new data.
The only adjustment is that the first thing I'm doing is removing the previous pie chart, to draw it again with the new data:
function updatePie(data){
svg2.selectAll("g.arc").remove();
Here is the complete code:
<script type="text/javascript">
var margin = {
top: 20,
right: 20,
bottom: 70,
left: 40,
mid: 20
},
w = 750 - margin.left - margin.right,
h = 300 - margin.top - margin.bottom;
var barPadding = 1;
var padding = 20;
var miniHeight = 60;
var selected;
var svg = d3.select(".outer-wrapper .chart").append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.mid + miniHeight + margin.bottom)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var barsGroup = svg.append('g')
.attr("class","barsGroup");
var miniGroup = svg.append('g')
.attr("class","miniGroup")
.attr("transform","translate(" + 0 + "," + (margin.top + h + margin.mid) + ")");
var brushGroup = svg.append('g')
.attr("class","brushGroup")
.attr("transform","translate(" + 0 + "," + (margin.top + h + margin.mid) + ")");
var w2 = 400;
var h2 = 400;
var outerRadius = w2 / 2;
var innerRadius = w2 / 3;
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.values; });
var color = d3.scale.category20c();
var svg2 = d3.select("body")
.append("svg")
.attr("width", w2)
.attr("height", h2);
d3.csv("data.csv", function(data) {
var dataset = d3.nest()
.key(function(d) {
return d.Year;
})
.sortKeys(d3.ascending)
.rollup(function(values) {
return values.length;
})
.entries(data)
.filter(function(d) {
return d.key != "UNK" && d.key != "VAR" && d.key != 199 && d.key != 211 && d.key != 2017;
});
//SCALES
var xScale = d3.scale.ordinal()
.domain(dataset.map(function(d) {
return d.key
}))
.rangeRoundBands([0, w], 0.05);
var xScaleBrush = d3.scale.ordinal()
.domain(d3.range(dataset.length))
.rangeRoundBands([0, w], 0.05);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) {
return d.values;
})])
.range([h, 0]);
//AXIS
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.tickValues([1900,1920,1930,1940,1950,1960,1970,1980,1990,2000, 2010,2020,2030,2040,2050,2060]);
var yAxis = d3.svg.axis()
.scale(yScale)
.ticks(6)
.orient("left");
//Appendi asse x
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)");
//Asse x per brush
svg.append("g")
.attr("class","x2 axis")
.attr("transform", "translate(" + 0 + "," + (margin.top + h + margin.mid + miniHeight) + ")" )
.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")
.append("g")
.attr("class", "axisLabel")
.append("text")
.attr("transform", "translate(" + -(margin.left * 0.8) + "," + (h/2) + "), rotate(-90)")
.style("text-anchor", "middle")
.text("Score");
var brush = d3.svg.brush()
.x(xScaleBrush)
.extent([0, w])
.on("brush", display);
brushGroup.append("g")
.attr("class", "brush")
.call(brush)
.selectAll("rect")
.attr("opacity", 0.5)
.attr("height", miniHeight);
function display() {
selected = xScaleBrush.domain()
.filter(function(d){
return (brush.extent()[0] <= xScaleBrush(d)) && (xScaleBrush(d) <= brush.extent()[1]);
});
var start;
var end;
/* Keep a minimum amount of bars on there to avoid any jank */
if (selected.length > 2) {
start = selected[0];
end = selected[selected.length - 1] + 1;
} else {
start = 0;
end = dataset.length;
}
var updatedData = dataset.slice(start, end);
updateBars(updatedData);
updatePie(updatedData);
}
function update(grp, data, main) {
grp.selectAll("rect").data(data, function(d) {
return d.key;
})
.attr("x", function(d) {
return xScale(d.key);
})
.attr("y", function(d) {
return main ? yScale(d.values) : 0;
})
.attr("width", function (d) {
return xScale.rangeBand();
})
.attr("height", function(d) {
return main ? h - yScale(d.values) : miniHeight;
});
}
function enter(grp, data, main) {
grp.selectAll("rect").data(data, function(d) {
return d.key;
})
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale(d.key);
})
.attr("y", function(d) {
return main ? yScale( d.values) : 0;
})
.attr("width", function(d) {
return xScale.rangeBand();
})
.attr("height", function(d) {
return main ? h - yScale(d.values) : miniHeight;
})
.attr("fill", function(d) {
var color = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) {
return d.values;
})])
.range([200, 244]);
var deg = color(d.values);
return "hsl(" + deg + ", 100%, 50%)";
})
.on("mouseover", function(d) {
if(main){
d3.select(this)
.attr("fill", "orange");
var xPosition = parseFloat(d3.select(this).attr("x"));
var yPosition = parseFloat(d3.select(this).attr("y")) / 2 + 100;
d3.select("#tooltip")
.style("left", xPosition + "px")
.style("top", yPosition + "px")
.style("z-index", "10")
.select("#value")
.text(d.values);
d3.select("#tooltip")
.select("#key")
.text("Film del " + d.key + " rilasciati su DVD");
d3.select("#tooltip").classed("hidden", false);
}
})
.on("mouseout", function(d) {
d3.select(this)
.transition()
.duration(250)
.attr("fill", function(d) {
var color = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) {
return d.values;
})])
.range([200, 244]);
var deg = color(d.values);
return "hsl(" + deg + ", 100%, 50%)";
});
d3.select("#tooltip").classed("hidden", true);
});
}
function exit(grp, data) {
grp.selectAll("rect").data(data, function(d) {
return d.key;
}).exit()
.remove();
}
function updateBars(data) {
xScale.domain(data.map(function(d) {
return d.key
}));
yScale.domain([0, d3.max(data, function(d) {
return d.values;
})]);
/* Update */
update(barsGroup, data, true);
/* Enter… */
enter(barsGroup, data, true);
/* Exit */
exit(barsGroup, data);
svg.select(".outer-wrapper .chart .y")
.transition()
.duration(10)
.call(yAxis);
svg.select(".outer-wrapper .chart .x")
.transition()
.duration(50)
.call(xAxis);
}
enter(miniGroup, dataset, false);
updateBars(dataset);
var dataset2 = d3.nest()
.key(function(d) { return d.Genre; })
.sortKeys(d3.ascending)
.rollup(function(values) { return values.length; })
.entries(data);
var text = svg2.append("text")
.attr("dx", 200)
.attr("dy", 200)
.attr("font-size", 30)
.style("text-anchor", "middle")
.attr("fill", "#36454f");
var text2 = svg2.append("text")
.attr("dx", 200)
.attr("dy", 230)
.attr("font-size", 20)
.style("text-anchor", "middle")
.attr("fill", "#36454f");
var text3 = svg2.append("text")
.attr("dx", 200)
.attr("dy", 260)
.attr("font-size", 20)
.style("text-anchor", "middle")
.attr("fill", "#36454f");
function updatePie(data){
svg2.selectAll("g.arc").remove();
var arcs = svg2.selectAll("g.arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "arc")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")")
.on("mouseover", function(d) {
var total = data.length;
var percent = Math.round(1000 * d.value / total) / 10;
text.text(d.data.key).attr("class", "inner-circle");
text2.text(d.value + " DVD");
text3.text(percent +"%");
})
.on("mouseout", function(d) {
text.text(function(d) { return ""; });
text2.text(function(d) { return ""; });
text3.text(function(d) { return ""; });
});
arcs.append("path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
}
updatePie(dataset2);
});

how to align y axis label in D3

i am trying to create a stacked bar graph.
however i can't seem to get the alignment right.the graph has two axis.
because of the length of the y axis label it is partially blocked.
i tried solving this by using different CSS styles on the label and on the enclosing div,
but they did not have the desired affect.
i created a jsfidel to explain my case.
http://jsfiddle.net/2khbceut/1/
HTML
<title>Diverging Stacked Bar Chart with D3.js</title>
<body>
<div id="figure" align="center" style="margin-bottom: 50px;"></div>
</body>
javascript
$(document).ready(getTopolegy());
function getTopolegy(){
var data = null;
var links = parseTopology(data);
createChart(links);
}
function parseTopology(data){
var links=[{1:5,2:5,3:10,N:20,link_name: "Link 167772376>>167772375"}];
return links;
}
function jsonNameToId(name){
switch (allocated_priority) {
case "allocated_priority":
return 1;
case "allocated_default":
return 2;
case "spare_capacity":
return 3;
case "total":
return "N";
default:
return 999;
}
}
function createChart(data){
var margin = {top: 50, right: 20, bottom: 10, left: 65},
width = 1000 - margin.left - margin.right,
height = 1000 - margin.top - margin.bottom;
var y = d3.scale.ordinal()
.rangeRoundBands([0, height], .3);
var x = d3.scale.linear()
.rangeRound([0, width]);
var color = d3.scale.ordinal()
.range(["#cccccc", "#92c6db", "#086fad"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("top");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
var svg = d3.select("#figure").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("id", "d3-plot")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
color.domain(["Allocated Priority %", "Allocated Default %", "Spare Capacity %"]);
// d3.csv("js/raw_data.csv", function(error, data) {
data.forEach(function(d) {
d["Allocated Priority %"] = +d[1]*100/d.N;
d["Allocated Default %"] = +d[2]*100/d.N;
d["Spare Capacity %"] = +d[3]*100/d.N;
var x0 = 0;
var idx = 0;
d.boxes = color.domain().map(function(name) { return {name: name, x0: x0, x1: x0 += +d[name], N: +d.N, n: +d[idx += 1]}; });
});
var min_val = d3.min(data, function(d) {
return d.boxes["0"].x0;
});
var max_val = d3.max(data, function(d) {
return d.boxes["2"].x1;
});
x.domain([min_val, max_val]).nice();
y.domain(data.map(function(d) { return d.link_name; }));
svg.append("g")
.attr("class", "x axis")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
var vakken = svg.selectAll(".Link")
.data(data)
.enter().append("g")
.attr("class", "bar")
.attr("transform", function(d) { return "translate(0," + y(d.link_name) + ")"; });
var bars = vakken.selectAll("rect")
.data(function(d) { return d.boxes; })
.enter().append("g").attr("class", "subbar");
bars.append("rect")
.attr("height", y.rangeBand())
.attr("x", function(d) { return x(d.x0); })
.attr("width", function(d) { return x(d.x1) - x(d.x0); })
.style("fill", function(d) { return color(d.name); });
bars.append("text")
.attr("x", function(d) { return x(d.x0); })
.attr("y", y.rangeBand()/2)
.attr("dy", "0.5em")
.attr("dx", "0.5em")
.style("font" ,"10px sans-serif")
.style("text-anchor", "begin")
.text(function(d) { return d.n !== 0 && (d.x1-d.x0)>3 ? d.n : "" });
vakken.insert("rect",":first-child")
.attr("height", y.rangeBand())
.attr("x", "1")
.attr("width", width)
.attr("fill-opacity", "0.5")
.style("fill", "#F5F5F5")
.attr("class", function(d,index) { return index%2==0 ? "even" : "uneven"; });
svg.append("g")
.attr("class", "y axis")
.append("line")
.attr("x1", x(0))
.attr("x2", x(0))
.attr("y2", height);
var startp = svg.append("g").attr("class", "legendbox").attr("id", "mylegendbox");
// this is not nice, we should calculate the bounding box and use that
var legend_tabs = [0, 150, 300];
var legend = startp.selectAll(".legend")
.data(color.domain().slice())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(" + legend_tabs[i] + ",-45)"; });
legend.append("rect")
.attr("x", 0)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", 22)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "begin")
.style("font" ,"10px sans-serif")
.text(function(d) { return d; });
d3.selectAll(".axis path")
.style("fill", "none")
.style("stroke", "#000")
.style("shape-rendering", "crispEdges")
d3.selectAll(".axis line")
.style("fill", "none")
.style("stroke", "#000")
.style("shape-rendering", "crispEdges")
var movesize = width/2 - startp.node().getBBox().width/2;
d3.selectAll(".legendbox").attr("transform", "translate(" + movesize + ",0)");
// });
}
i will appreciate any insight you have on this matter.

Categories