I'm trying to create a combination bar and line graph. The bar is the primary y axis representing data.total and the line is the secondary y axis representing data.percent.
Disclaimer:I'm very new to javascript and D3.
I've been clunking away for hours trying to figure out why the chart won't render the line series. Some of this code was based upon other example templates I found online so there may be something in there that isn't kosher with my modifications and I completely missed it.
Thanks for the help in advance!!!
Here's what I have:
<!DOCTYPE HTML>
<HTML>
<HEAD>
<STYLE>`enter code here`
svg{ padding-left: 100 px}
path {
stroke: Black;
stroke-width: 1;
fill: none;
}
.chartTitle{
color: #002b80;
font-size: 32pt;
font-weight: bold;
text-align: left;
padding-left: 20px;
}
</STYLE>
</HEAD>
<BODY>
<div class="chartTitle">Estimate of "Everything is Awesome"</div>
<SCRIPT SRC = 'd3.min.js'></SCRIPT>
<SCRIPT>
var data = [
{'date': '4/1/2015', 'total':500, 'percent':0.535},
{'date': '5/1/2015', 'total': 650, 'percent': 0.593},
{'date': '6/1/2015', 'total': 700, 'percent': 0.687},
{'date': '7/1/2015', 'total': 750, 'percent': 0.734},
{'date': '8/1/2015', 'total': 800, 'percent': 0.988},
{'date': '9/1/2015', 'total': 850, 'percent': 0.99},
{'date': '10/1/2015', 'total': 900, 'percent': 1.0}
];
var margin = {top: 70, right: 70, bottom: 70, left:60},
width = 600,
height = 500;
var toolTip = d3.select('body').append('div')
.style('position', 'absolute')
.style('background', 'white')
.style('opacity', .9)
.style('padding', '0 20px')
.style('border-radius', '25px')
.style('border', ' 2px solid dodgerblue')
// X and Y Axis
var xScale = d3.time.scale()
.domain([new Date(data[0].date), d3.time.month.offset(new Date(data[data.length - 1].date), 0)])
.rangeRound([0, width - margin.left - margin.right ]);
var y1Scale = d3.scale.linear()
.domain([0, d3.max(data, function(d) { return d.total;})])
.range([height - margin.top - margin.bottom, 0]);
var y2Scale = d3.scale.linear()
.domain([0, d3.max(data, function(d) { return d.percent;})])
.range([height - margin.top - margin.bottom, 0]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient('bottom')
.ticks(d3.time.month, 1)
.tickFormat(d3.time.format('%b -%y'))
.tickSize(1)
.tickPadding(8);
var y1Axis = d3.svg.axis()
.scale(y1Scale)
.orient('left')
.tickPadding(8)
.tickSize(1);
var y2Axis = d3.svg.axis()
.scale(y2Scale)
.orient('right')
.tickPadding(8)
.tickSize(1);
var lineData = d3.svg.line()
.x(function(d) { return xScale(d.date); })
.y(function(d) { return -1 * y2Scale(d.percent); });
//Chart Body
var svg = d3.select('body').append('svg')
.attr('class', 'chart')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
//Chart Body Creation
svg.selectAll('.chart')
.data(data)
.enter().append('rect')
.style('fill', 'dodgerblue')
.attr('class', 'bar')
.attr('x', function(d) { return xScale(new Date(d.date)); })
.attr('y', function(d) { return height - margin.top - margin.bottom - (height - margin.top - margin.bottom - y1Scale(d.total)) })
.attr('width', 20)
.attr('height', function(d) { return height - margin.top - margin.bottom - y1Scale(d.total) })
// Roll over SFX
.on('mouseover', function (d) {
toolTip.transition()
.style('opacity', .9)
toolTip.html(d.total)
.style('left', (d3.event.pageX - 40) + 'px')
.style('top', (d3.event.pageY - 30) + 'px')
d3.select(this)
.style('opacity', 0.5)
})
.on('mouseout', function (d) {
toolTip.transition()
.delay(100)
.duration(600)
.style('opacity', 0)
.style('pointer-events', 'none')
d3.select(this)
.style('opacity', 1)
});
//lDraw Line
svg.append("path")
.attr("d", lineData(data))
.style('stroke', 'DarkOrange');
//Draw the X Axis
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0, ' + (height - margin.top - margin.bottom) + ')')
.call(xAxis);
//Draw the Y1 Axis
svg.append('g')
.attr('class', 'y axis')
.call(y1Axis);
//Draw the Y2 Axis
svg.append('g')
.attr('class', 'y axis')
.attr("transform", "translate(" + (height ) + " ,0)")
.call(y2Axis);
</SCRIPT>
</BODY>
</HTML>
Problem 1:
You have date in this format {'date': '10/1/2015', 'total': 900, 'percent': 1.0} in your JSON, you will need to convert it into date object.
var format = d3.time.format("%d/%m/%Y");
data.forEach(function(d){
d.date = format.parse(d.date);
});
For various date format parsing refer
Problem2:
You are defining the domain incorrectly
var xScale = d3.time.scale()
.domain([new Date(data[0].date), d3.time.month.offset(new Date(data[data.length - 1].date), 0)])
.rangeRound([0, width - margin.left - margin.right ]);
Domain should be min/max of the date.
var xScale = d3.time.scale()
.domain([d3.min(data, function(d){return d.date}), d3.max(data, function(d){return d.date})])
.rangeRound([0, width - margin.left - margin.right]);
Reason for why is line not drawing up
var lineData = d3.svg.line()
.x(function(d) { return xScale(d.date); })//this date is not in the correct format so d3 does not know what to do and so gives NaN.
.y(function(d) { return -1 * y2Scale(d.percent); });
Now Problem 1 will fix this issue since we have converted the data into date.
Working example here
Hope this helps!
Related
I have implemented one scatter chart using d3.js. I want to convert this chart to line chart, but i am not able to do so. I have tried to follow ( http://embed.plnkr.co/wJDcZmkEzXaLVhuLZmcQ/ ) but it didn't helped me.
This is the code for scatter chart.
var data = [{"buildName":"otfa_R5-10_a1","build":"Build 1","value":"19628"},{"buildName":"otfa_R5-91_a1","build":"Build 2","value":"19628"},{"buildName":"otfa_R5-9_a1","build":"Build 3","value":"19628"}]
var yValues = [], responseData = [];
data.map(function(key) {
var test = [];
test[0] = key.build;
test[1] = key.value;
responseData.push(test);
yValues = key.value;
})
var margin = {
top: 20,
right: 15,
bottom: 60,
left: 60
},
width = 300 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(responseData.map(function(d) {
return d[0];
}))
.rangePoints([0, width], 0.5)
var y = d3.scale.linear()
.domain([5000,20000])
.range([height, 0]);
var chart = d3.select(divId)
.append('svg:svg')
.attr('width', width + margin.right + margin.left)
.attr('height', height + margin.top + margin.bottom)
.attr('class', 'chart')
var colors = d3.scale.linear()
.domain([5, 20])
.range(['#4577bc', '#4577bc'])
var main = chart.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.attr('width', width)
.attr('height', height)
.attr('class', 'main')
// draw the x axis
var xAxis = d3.svg.axis()
.scale(x)
.orient('bottom');
main.append('g')
.attr('transform', 'translate(0,' + height + ')')
.attr('class', 'main axis date')
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-45)" );
// draw the y axis
var yAxis = d3.svg.axis()
.scale(y)
.orient('left');
main.append('g')
.attr('transform', 'translate(0,0)')
.attr('class', 'main axis date')
.call(yAxis);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var g = main.append("svg:g");
g.selectAll("scatter-dots")
.data(responseData)
.enter().append("svg:circle")
.attr("cx", function(d, i) {
return x(d[0]);
})
.attr("cy", function(d) {
return y(d[1]);
})
.attr("r", 6)
.style('stroke', function(d, i) {
return colors(i);
})
.style('fill', function(d, i) {
return colors(i);
})
.on("mouseover", function(d) {
d3.select(this).attr("r", 10).style("fill", "#fff8ee");
div.transition()
.duration(200)
.style("opacity", 2.9);
div .html((d[1]))
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 18) + "px");
})
.on("mouseout", function(d) {
d3.select(this).attr("r", 5.5).style("fill", "#4577bc");
div.transition()
.duration(500)
.style("opacity", 0);
});
How we can add a line connecting these points ?
Please help me !!
To add a line to your existing chart, just add it using path generators.
Line generator:
var line = d3.svg.line()
.x(function (d) { return x(d[0]); })
.y(function (d) { return y(d[1]); });
Append the line to the svg:
g.append('path').classed('line', true)
.style( { fill: 'none', 'stroke': 'steelblue'} )
.attr('d', line(responseData));
Snippet with the above code included and a few CSS styles to make it look better:
var data = [{"buildName":"otfa_R5-10_a1","build":"Build 1","value":"19628"},{"buildName":"otfa_R5-91_a1","build":"Build 2","value":"10628"},{"buildName":"otfa_R5-9_a1","build":"Build 3","value":"17628"}]
var yValues = [], responseData = [];
data.map(function(key) {
var test = [];
test[0] = key.build;
test[1] = key.value;
responseData.push(test);
yValues = key.value;
})
var margin = {
top: 20,
right: 15,
bottom: 60,
left: 60
},
width = 300 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(responseData.map(function(d) {
return d[0];
}))
.rangePoints([0, width], 0.5)
var y = d3.scale.linear()
.domain([5000,20000])
.range([height, 0]);
var chart = d3.select('body')
.append('svg:svg')
.attr('width', width + margin.right + margin.left)
.attr('height', height + margin.top + margin.bottom)
.attr('class', 'chart')
var colors = d3.scale.linear()
.domain([5, 20])
.range(['#4577bc', '#4577bc'])
var main = chart.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.attr('width', width)
.attr('height', height)
.attr('class', 'main')
// draw the x axis
var xAxis = d3.svg.axis()
.scale(x)
.orient('bottom');
main.append('g')
.attr('transform', 'translate(0,' + height + ')')
.attr('class', 'main axis date')
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-45)" );
// draw the y axis
var yAxis = d3.svg.axis()
.scale(y)
.orient('left');
main.append('g')
.attr('transform', 'translate(0,0)')
.attr('class', 'main axis date')
.call(yAxis);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var g = main.append("svg:g");
g.selectAll("scatter-dots")
.data(responseData)
.enter().append("svg:circle")
.attr("cx", function(d, i) {
return x(d[0]);
})
.attr("cy", function(d) {
return y(d[1]);
})
.attr("r", 6)
.style('stroke', function(d, i) {
return colors(i);
})
.style('fill', function(d, i) {
return colors(i);
})
.on("mouseover", function(d) {
d3.select(this).attr("r", 10).style("fill", "#fff8ee");
div.transition()
.duration(200)
.style("opacity", 2.9);
div .html((d[1]))
.style("left", (d3.event.pageX+4) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
d3.select(this).attr("r", 5.5).style("fill", "#4577bc");
div.transition()
.duration(500)
.style("opacity", 0);
});
var line = d3.svg.line()
.x(function (d) { return x(d[0]); })
.y(function (d) { return y(d[1]); });
g.append('path').classed('line', true)
.style( { fill: 'none', 'stroke': 'steelblue'} )
.attr('d', line(responseData));
path.domain {
fill: none;
stroke: #000;
}
.axis text {
font-size: 12px;
}
div.tooltip {
position: absolute;
background: #FFF;
padding: 5px;
border: 1px solid #DDD;
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.0/d3.min.js"></script>
I have a line chart. And just the first and last tick of yAxis shows the outer line.
The result as below image:
The expected result is that every tick of yAxis shows outer line.
Example:
https://bl.ocks.org/d3noob/c506ac45617cf9ed39337f99f8511218
And here is my reproduce code:
var margin = { top: 70, right: 30, bottom: 50, left: 40 }
var width = 720 - margin.left - margin.right
var height = 430 - margin.top - margin.bottom
var data = [
{angle:0.6933744221879815,x:0.1},
{angle:0.6933744221879815,x:0.1},
{angle:0.6933744221879815,x:0.3},
{angle:0.6933744221879815,x:0.4},
{angle:0.6933744221879815,x:0.4},
{angle:0.6933744221879815,x:0.5},
{angle:0.6933744221879815,x:0.7},
{angle:0.6933744221879815,x:0.8},
{angle:0.6933744221879815,x:0.8},
{angle:0.6933744221879815,x:0.9},
{angle:0.6933744221879815,x:1},
{angle:0.6933744221879815,x:1.1},
{angle:0.6933744221879815,x:1.2},
{angle:0.6933744221879815,x:1.3},
{angle:0.6933744221879815,x:1.4},
{angle:0.6933744221879815,x:1.5}
]
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 x = d3.scaleLinear()
.range([0, width])
.domain([data[0].x , data[data.length - 1].x])
var y = d3.scaleLinear()
.range([height, 0])
.domain([-30, 120])
var xAxis = d3.axisBottom()
.scale(x)
.tickValues(x.ticks(8).concat(x.domain()[0]))
.tickFormat(d => d +'s')
.tickPadding(8)
.tickSizeOuter(0)
var yAxis = d3.axisLeft()
.scale(y)
.ticks(8)
.tickSizeInner(-width)
.tickSizeOuter(4)
.tickPadding(8);
var line = d3.line()
.x(function (d) {
return x(d.x);
})
.y(function (d) {
return y(d.angle);
})
.curve(d3.curveCatmullRom);
svg.append('path')
.attr('d', line(data))
.attr('stroke', '#ff5722')
.attr('stroke-width', '2')
.attr('fill', 'none');
svg.append('g')
.call(xAxis)
.attr('transform', `translate(0, ${height})`)
svg.append('g')
.call(yAxis)
.tick line{
opacity: 0.2;
}
.tick text{
font-size: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
There is no missing tick, all those inner ticks are there! However, they are going to the right hand side of the chart, because you did this:
yAxis.tickSizeInner(-width)
In other words, your light grey gridlines are your ticks.
If you want to keep those light grey gridlines and draw the regular ticks, you have to do a different approach. Like this:
svg.append('g')
.call(yAxis)
.selectAll(".tick")
.append("line")
.attr("x2", width)
.style("stroke", "#eee")
Here is your code with that change:
var margin = { top: 70, right: 30, bottom: 50, left: 40 }
var width = 720 - margin.left - margin.right
var height = 430 - margin.top - margin.bottom
var data = [
{angle:0.6933744221879815,x:0.1},
{angle:0.6933744221879815,x:0.1},
{angle:0.6933744221879815,x:0.3},
{angle:0.6933744221879815,x:0.4},
{angle:0.6933744221879815,x:0.4},
{angle:0.6933744221879815,x:0.5},
{angle:0.6933744221879815,x:0.7},
{angle:0.6933744221879815,x:0.8},
{angle:0.6933744221879815,x:0.8},
{angle:0.6933744221879815,x:0.9},
{angle:0.6933744221879815,x:1},
{angle:0.6933744221879815,x:1.1},
{angle:0.6933744221879815,x:1.2},
{angle:0.6933744221879815,x:1.3},
{angle:0.6933744221879815,x:1.4},
{angle:0.6933744221879815,x:1.5}
]
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 x = d3.scaleLinear()
.range([0, width])
.domain([data[0].x , data[data.length - 1].x])
var y = d3.scaleLinear()
.range([height, 0])
.domain([-30, 120])
var xAxis = d3.axisBottom()
.scale(x)
.tickValues(x.ticks(8).concat(x.domain()[0]))
.tickFormat(d => d +'s')
.tickPadding(8)
.tickSizeOuter(0)
var yAxis = d3.axisLeft()
.scale(y)
.ticks(8)
.tickSizeOuter(4)
.tickPadding(8);
var line = d3.line()
.x(function (d) {
return x(d.x);
})
.y(function (d) {
return y(d.angle);
})
.curve(d3.curveCatmullRom);
svg.append('path')
.attr('d', line(data))
.attr('stroke', '#ff5722')
.attr('stroke-width', '2')
.attr('fill', 'none');
svg.append('g')
.call(xAxis)
.attr('transform', `translate(0, ${height})`)
svg.append('g')
.call(yAxis)
.selectAll(".tick")
.append("line")
.attr("x2", width)
.style("stroke", "#eee")
.tick text{
font-size: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
I want to create a line chart using D3.js.
Here an example of line chart.
This is my code:
var margin = {top: 0, right: 0, bottom: 0, left: 0};
var svg = d3.select('#linechart')
.append('svg')
.attr('width', 600)
.attr('height', 200);
var values = createAxisLine(svg);
var x = values[0];
var y = values[1];
var width = values[2];
var height = values[3];
createChartLine(svg, x, y, width, height);
function createAxisLine(thisSvg) {
var width = thisSvg.attr('width') - margin.left - margin.right;
var height = thisSvg.attr('height') - margin.top - margin.bottom;
thisSvg = thisSvg.append('g').attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
var x = d3.scaleBand()
.rangeRound([0, width])
.domain([2016, 2015, 2014, 2013, 2012, 2011, 2010]);
var y = d3.scaleLinear()
.range([height, 0])
.domain([0, 100]);
var xAxis = d3.axisBottom(x).tickSize(0, 0);
var yAxis = d3.axisLeft(y);
thisSvg.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', 'rotate(-65)');
thisSvg.append('g')
.attr('class', 'y axis')
.attr('transform', 'translate(' + margin.left + ', 0)')
.call(yAxis)
.append('text')
.attr('transform', 'rotate(-90)')
.attr('y', 6)
.attr('dy', '.71em')
.style('text-anchor', 'end');
return [x, y, width, height];
}
function createChartLine(thisSvg, x, y, width, height) {
thisSvg.selectAll(null)
.data(mydata)
.attr('transform', function(d) {
return 'translate(' + margin.left + ', ' + margin.top + ')';
});
var line = d3.line()
.x(function(d) {
return x(d.year);
})
.y(function(d) {
if(isNaN(d.value)) return 0;
else return y(d.value);
});
lines.append('path')
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('stroke-width', 1.5)
.attr('d', line);
}
All the code is in this plunker.
When I run the code, nothing appears, no lines or axis are showed. But data are correctly getted so I don't understand what the problem is.
I get this error:
I need help
The problem for why nothing appears is that your the code inside script.js runs before the linechart element is loaded. One of the recommendation would be to include your script.js before the close of your body tag.
<body>
<div id='linechart'></div>
<script src="script.js"></script>
</body>
I've modified nice AlainRo’s Block for my needs (unfortunately can't link to it, because have not enough reputation), and I can't remove old data chart after entering new data. There is my codepen. In another example I've added merge(), and the chart is well aligned but the old one is still visible and text values are missed.
I spent a lot of time on it, and I run out of ideas.
There's code
barData = [
{ index: _.uniqueId(), value: _.random(1, 20) },
{ index: _.uniqueId(), value: _.random(1, 20) },
{ index: _.uniqueId(), value: _.random(1, 20) }
];
var margin = {top: 20, right: 20, bottom: 50, left: 70},
width = 400 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom,
delim = 4;
var scale = d3.scaleLinear()
.domain([0, 21])
.rangeRound([height, 0]);
var x = d3.scaleLinear()
.domain([0, barData.length])
.rangeRound([0, width]);
var y = d3.scaleLinear()
.domain([0, 21])
.rangeRound([height, 0]);
var svg = d3.select('#chart')
.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("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
svg.append("g")
.call(d3.axisLeft(y));
function draw() {
x.domain([0, barData.length]);
var brush = d3.brushY()
.extent(function (d, i) {
return [[x(i)+ delim/2, 0],
[x(i) + x(1) - delim/2, height]];})
.on("brush", brushmove);
var svgbrush = svg.selectAll('.brush')
.data(barData)
.enter()
.append('g')
.attr('class', 'brush')
.append('g')
.call(brush)
.call(brush.move, function (d){return [d.value, 0].map(scale);});
svgbrush
.append('text')
.attr('y', function (d){return scale(d.value) + 25;})
.attr('x', function (d, i){return x(i) + x(0.5);})
.attr('dx', '-.60em')
.attr('dy', -5)
.style('fill', 'white')
.text(function (d) {return d3.format('.2')(d.value);});
svgbrush
.exit()
.append('g')
.attr('class', 'brush')
.remove();
function brushmove() {
if (!d3.event.sourceEvent) return; // Only transition after input.
if (!d3.event.selection) return; // Ignore empty selections.
if (d3.event.sourceEvent.type === "brush") return;
var d0 = d3.event.selection.map(scale.invert);
var d = d3.select(this).select('.selection');;
var d1 =[d0[0], 0];
d.datum().value = d0[0]; // Change the value of the original data
d3.select(this).call(d3.event.target.move, d1.map(scale));
svgbrush
.selectAll('text')
.attr('y', function (d){return scale(d.value) + 25;})
.text(function (d) {return d3.format('.2')(d.value);});
}
}
draw();
function upadateChartData() {
var newBarsToAdd = document.getElementById('charBarsCount').value;
var newBarData = function() {
return { index: _.uniqueId(), value: _.random(1, 20) }
};
newBarData = _.times(newBarsToAdd, newBarData);
barData = _.concat(barData, newBarData)
draw();
};
Is it also possible to remove cross pointer and leave only resize, when I'm dragging top bar border?
You're appending g elements twice. This:
svgbrush.enter()
.append('g')
.attr('class', 'brush')
.merge(svgbrush)
.append('g')
.call(brush)
.call(brush.move, function (d){return [d.value, 0].map(scale);});
Should be:
svgbrush.enter()
.append('g')
.attr('class', 'brush')
.merge(svgbrush)
.call(brush)
.call(brush.move, function (d){return [d.value, 0].map(scale);});
Here is your updated Pen: http://codepen.io/anon/pen/VmavyX
PS: I also made other changes, declaring some new variables, just to organize your enter and update selections and solving the texts problem.
Please look at http://bl.ocks.org/HoffmannP/95392bf4a37344793786 and help me find an explenation why it just doesn't work in FF but works like a charm in Chrome.
because you're using .style for width, height and x when you need to use .attr.
Having these as .styles is part of SVG 2 and not SVG 1.1 and SVG 2 is unfinished. Firefox does not yet implement this part of SVG 2, although it does implement other parts that Chrome does not.
var margin = {top: 50, right: 20, bottom: 60, left: 70};
var width = 800 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([0, 4])
.range([0, width]);
var y = d3.scale.linear()
.domain([0, 60])
.range([height, 0]);
var yVal = d3.scale.linear()
.domain([60, 0])
.range([height, 0]);
var yAxisMinor = d3.svg.axis()
.scale(y)
.ticks(13)
.tickSize(width, 0)
.orient('right');
var yAxisMajor = d3.svg.axis()
.scale(y)
.ticks(7)
.tickSize(width, 0)
.tickPadding(-(width + 5))
.tickFormat(d3.format('d'))
.orient('right');
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 xLabel = svg.append('g')
.attr('class', 'x label')
.attr('transform', 'translate(0, ' + height/2 + ') rotate(-90)')
.append('text')
.attr('text-anchor', 'middle')
.attr('dy', '-40')
.text('Prozent');
var gx = svg
.append('g').attr('class', 'x axis');
gx.append('g')
.attr('transform', 'translate(7, -15)')
.append('line')
.attr('x2', '0')
.attr('y2', height + 15);
gx.append('g')
.attr('transform', 'translate(0, -26) scale(0.15, 0.15)')
.append('path')
.attr('d', 'M0,86.6L50,0L100,86.6C50,75 50,75 0,86.6z');
var gyMinor = svg.append('g')
.attr('class', 'y axis minor')
.call(yAxisMinor);
gyMinor.selectAll('text').remove();
var gyMajor = svg.append('g')
.attr('class', 'y axis major')
.call(yAxisMajor);
gyMajor.selectAll('text')
.style('text-anchor', 'end')
.attr('dy', '7px');
var drawArea = svg.append('g')
.attr('class', 'block')
.attr('transform', 'translate(' + 20 + ', ' + height + ') scale(1, -1)');
var backBlocks = drawArea
.selectAll('rect.back')
.data([64, 64, 64, 64])
.enter()
.append('rect')
.attr('class', 'back')
.attr('width', width/5)
.attr('height', yVal)
.attr('x', function (d, i) { return x(i); });
var frontBlocks = drawArea
.selectAll('rect.front')
.data([0,0,0,0])
.enter()
.append('rect')
.attr('class', 'front')
.attr('width', width/5)
.attr('height', yVal)
.attr('x', function (d, i) { return x(i); });
var newHeight = function (d, i) {
var y = d3.event.clientY;
d3.select(frontBlocks[0][i % 4]).style('height', height + margin.bottom - y);
};
var currentActiveBlock = false;
drawArea.selectAll('rect')
.on('mouseover', function (d, i) {
d3.select(backBlocks[0][i % 4]).style('opacity', '0.5');
})
.on('mouseout', function () {
backBlocks.style('opacity', '0');
})
.on('mousedown', function (d, i) {
d3.select(backBlocks[0][i % 4]).style('opacity', '0.5');
newHeight.call(this, d, i);
currentActiveBlock = i % 4;
})
.on('mousemove', function (d, i) {
if (currentActiveBlock === false) {
return;
}
newHeight.call(this, d, currentActiveBlock);
})
.on('mouseup', function (d, i) {
d3.select(frontBlocks[0][currentActiveBlock]).style('opacity', '1');
newHeight.call(this, d, currentActiveBlock);
currentActiveBlock = false;
});
body {
font: 18px sans-serif;
}
svg {
}
.label text {
font-weight: bold;
}
.y.axis path {
display: none;
}
.x.axis path {
fill: #333;
}
.axis line {
shape-rendering: crispEdges;
stroke: #333;
stroke-width: 2px;
}
.axis.minor line {
stroke-width: 1px;
}
.axis text {
text-anchor: end;
}
.block rect {
cursor: ns-resize;
}
.block rect.back {
opacity: 0.0;
fill: #ddd;
}
}
.block rect.front {
fill: #222;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>