I've got this d3js v3 chart and was wondering if it's possible to append the values in a text format to both the bar and the donut chart, and if so, how you would go about doing it?
Here is the code:
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<style>
body {
font-family:arial;
font-size:10px;
margin:auto;
width:1100px;
}
.axis text {
font: 10px sans-serif;
}
.axis line,
.axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
select {
background-color: #fff;
border: 1px solid #fff;
border-bottom: 1px solid #ccc;
color: #000;
padding: 3px 3px;
text-align: center;
text-decoration: none;
font-size: 10px;
margin: 2px 2px;
cursor: pointer;
}
select:focus {outline:0;}
.Row
{
display: table;
width: 100%;
table-layout: fixed;
}
.Column
{
display: table-cell;
position:relative;
}
</style>
</head>
<body>
<div class="Row">
<div class="Column" id="chart"></div>
</div>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var dispatch = d3.dispatch("load", "statechange");
var groups = [
"Team 1",
"Team 2",
"Team 3"
];
d3.csv("data.csv", type, function(error, states) {
if (error) throw error;
var stateById = d3.map();
states.forEach(function(d) { stateById.set(d.id, d); });
dispatch.load(stateById);
dispatch.statechange(stateById.get("CA"));
});
// A drop-down menu for selecting a state; uses the "menu" namespace.
dispatch.on("load.menu", function(stateById) {
var select = d3.select("#chart")
.append("div")
.append("select")
.on("change", function() { dispatch.statechange(stateById.get(this.value)); });
select.selectAll("option")
.data(stateById.values())
.enter().append("option")
.attr("value", function(d) { return d.id; })
.text(function(d) { return d.id; });
dispatch.on("statechange.menu", function(state) {
select.property("value", state.id);
});
});
// A bar chart to show total population; uses the "bar" namespace.
dispatch.on("load.bar", function(stateById) {
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 80 - margin.left - margin.right,
height = 290 - margin.top - margin.bottom;
var y = d3.scale.linear()
.domain([0, d3.max(stateById.values(), function(d) { return d.total; })])
.rangeRound([height, 0])
.nice();
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
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("class", "y axis")
.call(yAxis);
var rect = svg.append("rect")
.attr("x", 4)
.attr("width", width - 4)
.attr("y", height)
.attr("height", 0)
.style("fill", "#aaa");
dispatch.on("statechange.bar", function(d) {
rect.transition()
.attr("y", y(d.total))
.attr("height", y(0) - y(d.total));
});
});
// A pie chart to show population by age group; uses the "pie" namespace.
dispatch.on("load.pie", function(stateById) {
var width = 260,
height = 300,
radius = Math.min(width, height) / 2;
var color = d3.scale.ordinal()
.domain(groups)
.range(["steelblue", "lightblue", "darkorange"]);
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(radius - 60);
var pie = d3.layout.pie()
.sort(null);
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var path = svg.selectAll("path")
.data(groups)
.enter().append("path")
.style("fill", color)
.each(function() { this._current = {startAngle: 0, endAngle: 0}; });
dispatch.on("statechange.pie", function(d) {
path.data(pie.value(function(g) { return d[g]; })(groups)).transition()
.attrTween("d", function(d) {
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
return arc(interpolate(t));
};
});
});
});
// Coerce population counts to numbers and compute total per state.
function type(d) {
d.total = d3.sum(groups, function(k) { return d[k] = +d[k]; });
return d;
}
</script>
</body>
</html>
And here's the dataset:
id,Team 1,Team 2,Team 3
AL,3105,5523,2590
AK,5208,8564,4215
AZ,5159,8286,3626
AR,2020,3432,1572
CA,2704,4499,2159
CO,3582,5871,2617
CT,2116,4036,1969
DE,5931,9949,4741
DC,3635,5043,2522
FL,1140,1938,9250
GA,7405,1250,5578
HI,8720,1340,6401
You have to create the label :
var label = svg.append("text")
.attr("x", 4)
.attr("y", height)
.attr("dy", ".35em")
.text(function(d) { return "0"; });
Then add a transition on this new text
label.transition()
.attr("y", y(d.total) + 5)
.text(d.total);
See https://plnkr.co/edit/wtq96BAZ3Zh1SaczjLT6?p=preview
Related
I am trying to animate the bars when the user clicks on the legend. I've built the update function - but I am unsure on how to do the required filter and animation for this feature
http://jsfiddle.net/0ht35rpb/211/
function update(){
console.log("data", data);
var barData = data.filter(function(d1) {
console.log("d1", d1);
return !d1.disabled;
});
console.log("barData", barData);
var bar = chartHolder.selectAll(".bar")
.data(data)
console.log("bar", bar);
bar.transition()
.attr("width", x0.rangeBand())
.attr("y", function(d) {
return 0;
//return y(d.value);
})
.attr("height", function(d) {
return 0;
//return height - y(d.value);
});
bar.exit().remove();
/*
var bar = bar.selectAll("rect")
bar.transition()
//.attr("id", function(d){ return 'tag'+d.state.replace(/\s|\(|\)|\'|\,+/g, '');})
.attr("x", function(d) { return x1(d.name); })
.attr("width", x0.rangeBand())
.attr("y", function(d) {
return 0;
//return y(d.value);
})
.attr("height", function(d) {
return 0;
//return height - y(d.value);
});
//bar.exit().remove();
*/
This code var bar = chartHolder.selectAll(".bar") returns empty selection. You should select all .bars apply new data with method data, after that select all react, set animation parameters transition, duration, delay and set new values for approptiate attributes.
I rewrite your code - http://jsfiddle.net/168x28p3/1/ Here, I simply animate height of bars after click on legend. But this way you can create the another animation which you need.
var $this = document.querySelector('.chart');
var data = [{
label: "a",
"Current Period": 20,
"Prior Year": 10
}, {
label: "b",
"Current Period": 15,
"Prior Year": 30
}, {
label: "c",
"Current Period": 25,
"Prior Year": 40
}, {
label: "d",
"Current Period": 5,
"Prior Year": 60
}];
var configuration = [{
"yLabel": "People Count"
}];
var w = 660;
var h = 500;
function colores_google(n) {
var colores_g = ["#f7b363", "#448875", "#c12f39", "#2b2d39", "#f8dd2f", "#8bf41b"];
return colores_g[n % colores_g.length];
}
var margin = {
top: 20,
right: 110,
bottom: 30,
left: 20
},
width = w - margin.left - margin.right,
height = h - margin.top - margin.bottom;
var svg = d3.select($this).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 axisHolder = svg.append("g")
.attr("class", "axis");
var chartHolder = svg.append("g")
.attr("class", "chart");
var legendHolder = svg.append("g")
.attr("class", "legend");
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
//var colorRange = d3.scale.category20();
//var color = d3.scale.ordinal()
//.range(colorRange.range());
var xAxis = d3.svg.axis()
.scale(x0)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
var divTooltip = d3.select("body").append("div").attr("class", "toolTip");
var options = d3.keys(data[0]).filter(function(key) {
return key !== "label";
});
data.forEach(function(d) {
d.valores = options.map(function(name) {
return {
name: name,
value: +d[name]
};
});
});
x0.domain(data.map(function(d) {
return d.label;
}));
x1.domain(options).rangeRoundBands([0, x0.rangeBand()]);
y.domain([0, d3.max(data, function(d) {
return d3.max(d.valores, function(d) {
return d.value;
});
})]);
axisHolder.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
axisHolder.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(configuration[0].yLabel);
var bar = chartHolder.selectAll(".bar")
.data(data)
.enter().append("g")
.attr("class", "bars")
.attr("transform", function(d) {
return "translate(" + x0(d.label) + ",0)";
});
bar.selectAll("rect")
.data(function(d) {
return d.valores;
})
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function(d) {
return x1(d.name);
})
.attr("y", function(d) {
return y(d.value);
})
.attr("value", function(d) {
return d.name;
})
.attr("height", function(d) {
return height - y(d.value);
})
.style("fill", function(d, i) {
return colores_google(i);
});
bar
.on("mousemove", function(d) {
divTooltip.style("left", d3.event.pageX + 10 + "px");
divTooltip.style("top", d3.event.pageY - 25 + "px");
divTooltip.style("display", "inline-block");
var x = d3.event.pageX,
y = d3.event.pageY
var elements = document.querySelectorAll(':hover');
l = elements.length
l = l - 1
elementData = elements[l].__data__
divTooltip.html((d.label) + "<br>" + elementData.name + "<br>" + elementData.value + "%");
});
bar
.on("mouseout", function(d) {
divTooltip.style("display", "none");
});
var legend = legendHolder.selectAll(".legend")
.data(options.slice())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) {
return "translate(" + margin.right + "," + i * 20 + ")";
});
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d, i) {
return colores_google(i);
})
.on("click", function(d) {
console.log("d", d);
d.disabled = !d.disabled;
update();
});
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {
return d;
});
function update() {
var barData = data.map(item => {
item.valores = item.valores.map(valor => {
return Object.assign({}, valor, { value: Math.random() * 40 })
})
return item;
})
var bar = chartHolder.selectAll(".bars")
.data(barData)
var rect = bar.selectAll("rect")
.data(function(d) {
return d.valores;
})
rect
.transition()
.duration(1000)
.delay(100)
.attr("width", x0.rangeBand() / 2)
.attr("y", function(d) {
return y(d.value);
})
.attr("height", function(d) {
return height - y(d.value);
});
}
* {
margin: 0;
padding: 0;
border: 0;
}
body {
background: #ffd;
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
position: relative;
}
text {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.toolTip {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
position: absolute;
display: none;
width: auto;
height: auto;
background: none repeat scroll 0 0 white;
border: 0 none;
border-radius: 8px 8px 8px 8px;
box-shadow: -3px 3px 15px #888888;
color: black;
font: 12px sans-serif;
padding: 5px;
text-align: center;
}
.legend {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 60%;
}
rect {
stroke-width: 2;
}
text {
font: 10px sans-serif;
}
.axis text {
font: 10px sans-serif;
}
.axis path {
fill: none;
stroke: #000;
}
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis .tick line {
stroke-width: 1;
stroke: rgba(0, 0, 0, 0.2);
}
.axisHorizontal path {
fill: none;
}
.axisHorizontal line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axisHorizontal .tick line {
stroke-width: 1;
stroke: rgba(0, 0, 0, 0.2);
}
.bar {
fill: steelblue;
fill-opacity: .9;
}
/*
.x.axis path {
display: none;
}*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div class="chart"></div>
I'm trying to get day of the month(i.e 1,2,3,4 ...etc) on the x axis and time period of the hour 0-24 on Y axis. I am unable to get the axis line i dont know why.Can someone tell me why? In the console window, it says padding is not defined.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
/*set the axis line color, dot stroke, font size, and font position*/
body {
font: 13px helvetica;
}
.name{
position: relative;
top: 90px;
text-align: left;
font-weight: bold;
}
.title {
position: relative;
text-align: left;
font-size: 25px;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.dot {
stroke: #000;
}
#filter {
position: absolute;
}
#mark {
padding-left: 150px;
position: inherit;
}
#xAXs {
position: relative;
left: 290px;
bottom: 30px;
}
#yAXs {
position: relative;
bottom: 30px;
left: 315px;
}
#label {
position: absolute;
top: 599px;
bottom: 125px;
left: 300px;
right: 0px;
}
#label2 {
position: absolute;
top: 599px;
bottom: 125px;
left: 430px;
right: 0px;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var axisNames = {
Hour: 'Hour',
Day: 'Day',
};
// define the x scale (horizontal)
var mindate = new Date(2012,0,1),
maxdate = new Date(2012,0,31);
var xScale = d3.time.scale()
.domain([mindate, maxdate]) // values between for month of january
.range([padding, width - padding * 2]); // map these the the chart width = total width minus padding at both sides
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("file1.csv", function(error, data) {
data.forEach(function(d) {
d.Day = +d.Day;
d.Hour = +d.Hour;
});
x.domain(d3.extent(data, function(d) { return d.Day; })).nice();
y.domain(d3.extent(data, function(d) { return d.Hour; })).nice();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("Day");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Hour")
var circles = svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.Hour); })
.attr("cy", function(d) { return y(d.day); })
.style("fill", function(d) { return color(d.name); });
var legend = svg.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
d3.selectAll("[name=v]").on("change", function() {
var selected = this.value;
display = this.checked ? "inline" : "none";
svg.selectAll(".dot")
.filter(function(d) {return selected == d.name;})
.attr("display", display);
});
d3.selectAll("[name=sepal]").on("change", function(d) {
radius = this.value;
svg.selectAll(".dot")
console.log(radius);
circles.attr("r", function(d) { return d[radius]; });
});
d3.select("[name=xAX]").on("change", function(){
xAxy = this.value;
console.log(xAxy)
x.domain(d3.extent(data, function(d) { return d[xAxy]; })).nice();
svg.select(".x.axis").transition().call(xAxis);
svg.selectAll(".dot").transition().attr("cx", function(d) {
return x(d[xAxy]);
});
svg.selectAll(".x.axis").selectAll("text.label").text(axisNames[xAxy] + " (cm)");
});
d3.select("[name=yAX]").on("change", function(){
yAxy = this.value;
console.log(yAxy)
y.domain(d3.extent(data, function(d) { return d[yAxy]; })).nice();
svg.select(".y.axis").transition().call(yAxis);
svg.selectAll(".dot").transition().attr("cy", function(d) {
return y(d[yAxy]);
});
svg.selectAll(".y.axis").selectAll("text.label").text(axisNames[yAxy] + " (cm)");
});
});
</script>
<br><br>
<br>
</body>
You set a time scale in which the range uses padding and width:
var xScale = d3.time.scale()
.domain([mindate, maxdate])
.range([padding, width - padding * 2]);
Despite you had previously defined width:
width = 960 - margin.left - margin.right;
You didn't define padding anywhere in your code.
So, just give it any value you want, before defining the time scale:
var padding = 42; //tweak this value
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Testing Pie Chart</title>
<script src="d3.v3.min.js" charset="utf-8"></script>
<style type="text/css">
#chart {
margin-top: 100px;
position: absolute;
margin-right: 50px;
margin-left: 50px;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #900C3F;
display: inline-block;
font-size: 12px;
left: 600px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
width: 150px;
z-index: 10;
opacity: 1;
}
rect {
stroke-width: 2;
}
path {
stroke: #ffffff;
stroke-width: 0.5;
}
div.tooltip {
position: absolute;
z-index: 999;
padding: 10px;
background: #f4f4f4;
border: 0px;
border-radius: 3px;
pointer-events: none;
font-size: 11px;
color: #000;
line-height: 16px;
border: 1px solid #d4d4d4;
}
.legend{
margin-left: 300px;
}
</style>
</head>
<body>
<div id="chart"></div>
<div id="toolTip" class="tooltip" style="opacity: 0;"></div>
<script type="text/javascript">
var div = d3.select("#toolTip");
var data = [ ["IP", "count"]
["192.168.12.1", "20"],
["76.09.45.34", "40"],
["34.91.23.76", "80"],
["192.168.19.32", "16"],
["192.168.10.89", "50"],
["192.178.34.07", "18"],
["192.168.12.98", "30"]];
var width = 300,
height = 300;
var margin = {top: 15, right: 15, bottom: 20, left: 40},
radius = Math.min(width, height) / 2 - 10;
var legendRectSize = 18,
legendSpacing = 4;
var color = d3.scale.category20b();
var arc = d3.svg.arc()
.outerRadius(radius);
var arcOver = d3.svg.arc()
.outerRadius(radius + 10);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.data.count; });
var labelArc = d3.svg.arc()
.outerRadius(radius - 40)
.innerRadius(radius - 40);
var svg = d3.select("#chart").append("svg")
.datum(data)
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var arcs = svg.selectAll(".arc")
.data(pie)
.enter().append("g")
.attr("class", "arc");
var arcs2 = svg.selectAll(".arc2")
.data(pie)
.enter().append("g")
.attr("class", "arc2");
arcs.append("path")
.attr("fill", function(d, i) { return color(i); })
.on("mouseover", function(d) {
var htmlMsg="";
div.transition()
.style("opacity",0.9);
var total = d3.sum(data.map(function(d) {
return d.count;
}));
var percent = Math.round(1000 * d.data.count / total) / 10;
div.html(
"IP :"+ d.data.IP +""+"<br/>"+
"Count : " + d.data.count +"<br/>" +
"Percent: " + percent + '%'+ htmlMsg)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
svg.selectAll("path").sort(function (a, b) {
if (a != d) return -1;
else return 1;
});
var endAngle = d.endAngle + 0.1;
var startAngle = d.startAngle - 0.1;
var arcOver = d3.svg.arc()
.outerRadius(radius + 10).endAngle(endAngle).startAngle(startAngle);
d3.select(this)
.attr("stroke","white")
.transition()
.ease("bounce")
.duration(1000)
.attr("d", arcOver)
.attr("stroke-width",6);
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
d3.select(this).transition()
.attr("d", arc)
.attr("stroke","none");
})
.transition()
.ease("bounce")
.duration(2000)
.attrTween("d", tweenPie);
function tweenPie(b) {
b.innerRadius = 0;
var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
return function(t) { return arc(i(t)); };
}
var k=0;
arcs2.append("text")
.transition()
.ease("elastic")
.duration(2000)
.delay(function (d, i) {
return i * 250;
})
.attr("x","6")
.attr("dy", ".35em")
.text(function(d) { if(d.data.count >0){ k = k+1; return d.data.count;} })
.attr("transform", function(d) { if (k >1){return "translate(" + labelArc.centroid(d) + ") rotate(" + angle(d) + ")";} else{return "rotate(-360)";} })
.attr("font-size", "10px");
function type(d) {
d.count = +d.count;
return d;
}
function angle(d) {
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
return a > 90 ? a - 180 : a;
}
var legend = d3.select("#chart")
.append("svg")
.attr("class", "legend")
.attr("width", radius+50)
.attr("height", radius * 2)
.selectAll("g")
.data(color.domain())
.enter()
.append("g")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.style('fill', color)
.style('stroke', color);
legend.append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.data(data)
.text(function(d,i) { return d.IP; });
</script>
</body>
</html>
I am trying to make a pie chart with the provided dataset and I am facing error. How to define the parameter d to fetch the data from the variable "data" and its subsequent values "IP" and "count"? I dont know what mistake I am doing in my codes. What should I change in my current codes so that I can get a pie chart with current data format? Please help me. I am stuck. The condition is I should not use any kind of .csv or .tsv file in this code for importing. Thanks for any help.
One issue is with your data array... you need to remove the first item in it [ Also, you are missing a ',' after the item. but the item is itself not required as its an array ].
Second is with d.data.count inside the pie function... you need to refer it as d[1] as you need to plot the second item in data array in your chart.
Working code below:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Testing Pie Chart</title>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<style type="text/css">
#chart {
margin-top: 100px;
position: absolute;
margin-right: 50px;
margin-left: 50px;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #900C3F;
display: inline-block;
font-size: 12px;
left: 600px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
width: 150px;
z-index: 10;
opacity: 1;
}
rect {
stroke-width: 2;
}
path {
stroke: #ffffff;
stroke-width: 0.5;
}
div.tooltip {
position: absolute;
z-index: 999;
padding: 10px;
background: #f4f4f4;
border: 0px;
border-radius: 3px;
pointer-events: none;
font-size: 11px;
color: #000;
line-height: 16px;
border: 1px solid #d4d4d4;
}
.legend{
margin-left: 300px;
}
</style>
</head>
<body>
<div id="chart"></div>
<div id="toolTip" class="tooltip" style="opacity: 0;"></div>
<script type="text/javascript">
var div = d3.select("#toolTip");
var data = [
["192.168.12.1", "20"],
["76.09.45.34", "40"],
["34.91.23.76", "80"],
["192.168.19.32", "16"],
["192.168.10.89", "50"],
["192.178.34.07", "18"],
["192.168.12.98", "30"]];
var width = 300,
height = 300;
var margin = {top: 15, right: 15, bottom: 20, left: 40},
radius = Math.min(width, height) / 2 - 10;
var legendRectSize = 18,
legendSpacing = 4;
var color = d3.scale.category20b();
var arc = d3.svg.arc()
.outerRadius(radius);
var arcOver = d3.svg.arc()
.outerRadius(radius + 10);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d[1]; });
var labelArc = d3.svg.arc()
.outerRadius(radius - 40)
.innerRadius(radius - 40);
var svg = d3.select("#chart").append("svg")
.datum(data)
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var arcs = svg.selectAll(".arc")
.data(pie)
.enter().append("g")
.attr("class", "arc");
var arcs2 = svg.selectAll(".arc2")
.data(pie)
.enter().append("g")
.attr("class", "arc2");
arcs.append("path")
.attr("fill", function(d, i) { return color(i); })
.on("mouseover", function(d) {
var htmlMsg="";
div.transition()
.style("opacity",0.9);
var total = d3.sum(data.map(function(d) {
return d.count;
}));
var percent = Math.round(1000 * d.data.count / total) / 10;
div.html(
"IP :"+ d.data.IP +""+"<br/>"+
"Count : " + d.data.count +"<br/>" +
"Percent: " + percent + '%'+ htmlMsg)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px");
svg.selectAll("path").sort(function (a, b) {
if (a != d) return -1;
else return 1;
});
var endAngle = d.endAngle + 0.1;
var startAngle = d.startAngle - 0.1;
var arcOver = d3.svg.arc()
.outerRadius(radius + 10).endAngle(endAngle).startAngle(startAngle);
d3.select(this)
.attr("stroke","white")
.transition()
.ease("bounce")
.duration(1000)
.attr("d", arcOver)
.attr("stroke-width",6);
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
d3.select(this).transition()
.attr("d", arc)
.attr("stroke","none");
})
.transition()
.ease("bounce")
.duration(2000)
.attrTween("d", tweenPie);
function tweenPie(b) {
b.innerRadius = 0;
var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
return function(t) { return arc(i(t)); };
}
var k=0;
arcs2.append("text")
.transition()
.ease("elastic")
.duration(2000)
.delay(function (d, i) {
return i * 250;
})
.attr("x","6")
.attr("dy", ".35em")
.text(function(d) { if(d.data.count >0){ k = k+1; return d.data.count;} })
.attr("transform", function(d) { if (k >1){return "translate(" + labelArc.centroid(d) + ") rotate(" + angle(d) + ")";} else{return "rotate(-360)";} })
.attr("font-size", "10px");
function type(d) {
d.count = +d.count;
return d;
}
function angle(d) {
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
return a > 90 ? a - 180 : a;
}
var legend = d3.select("#chart")
.append("svg")
.attr("class", "legend")
.attr("width", radius+50)
.attr("height", radius * 2)
.selectAll("g")
.data(color.domain())
.enter()
.append("g")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.style('fill', color)
.style('stroke', color);
legend.append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.data(data)
.text(function(d,i) { return d.IP; });
</script>
</body>
</html>
Your data input format is wrong.
Change from:
var data = [ ["IP", "count"]
["192.168.12.1", "20"],
["76.09.45.34", "40"],
["34.91.23.76", "80"],
["192.168.19.32", "16"],
["192.168.10.89", "50"],
["192.178.34.07", "18"],
["192.168.12.98", "30"]];
to
var data = [
{"IP":"192.168.12.1", "count":"20"},
{"IP":"76.09.45.34", "count":"40"},
{"IP":"34.91.23.76", "count":"80"},
{"IP":"192.168.19.32", "count":"16"},
{"IP":"192.168.10.89", "count":"50"},
{"IP":"192.178.34.07", "count":"18"},
{"IP":"192.168.12.98", "count":"30"}
];
I have a simple bar chart here that should nicely transition all the bars over slightly to the left to make room for a new bar to appear on the right of the graph whenever new data is submitted via a button click event, however they all seem to fire over to the left side on top of each other.
Here is my code for my transition:
bars.transition()
.duration(1000)
.attr("x", function(d, i) {
return x(i);
})
.attr("y", function(d) {
return y(d.count);
})
.attr("width", x.rangeBand())
.attr("height", function(d) {
return height - y(d.count);
});
Here is a jsfiddle of the code so far: https://jsfiddle.net/foL2Lcg1/1/
The test data for entry on the button submission I'm using is 'Service: blah' and 'Count: 60000' which you can enter below the graph.
Any suggestions?
From the example here : https://bl.ocks.org/RandomEtc/cff3610e7dd47bef2d01
I have created this fiddle with your data : https://jsfiddle.net/thatOneGuy/foL2Lcg1/5/
I have added a draw function which you pass data. So instead of rewriting code as you were, you start by calling this function, and once you add/remove some data, you call this function again with the new set of data and it updates. Here is the function :
function draw(data) {
// measure the domain (for x, unique letters) (for y [0,maxFrequency])
// now the scales are finished and usable
x.domain(data.map(function(d) { return d.service; }));
y.domain([0, d3.max(data, function(d) { return d.count; })]);
// another g element, this time to move the origin to the bottom of the svg element
// someSelection.call(thing) is roughly equivalent to thing(someSelection[i])
// for everything in the selection\
// the end result is g populated with text and lines!
svg.select('.x.axis').transition().duration(300).call(xAxis);
// same for yAxis but with more transform and a title
svg.select(".y.axis").transition().duration(300).call(yAxis)
// THIS IS THE ACTUAL WORK!
var bars = svg.selectAll(".bar").data(data) // (data) is an array/iterable thing, second argument is an ID generator function
bars.exit()
.transition()
.duration(300)
.attr("y", y(0))
.attr("height", height - y(0))
.style('fill-opacity', 1e-6)
.remove();
// data that needs DOM = enter() (a set/selection, not an event!)
bars.enter().append("rect")
.attr("class", "bar")
.attr("y", function(d) {
return y(d.count);
})
.attr("height", function(d) {
return height - y(d.count);
})
// the "UPDATE" set:
bars.transition().duration(300).attr("x", function(d) { return x(d.service); }) // (d) is one item from the data array, x is the scale object from above
.attr("width", x.rangeBand()) // constant, so no callback function(d) here
.attr("y", function(d) { return y(d.count); })
.attr("height", function(d) { return height - y(d.count); }); // flip the height, because y's domain is bottom up, but SVG renders top down
}
Now update as you were on button click :
d3.select("button")
.attr("id", "submit")
.on("click", function() {
var service = document.getElementById("service").value;
var count = document.getElementById("count").value;
var json = {
"count": count,
"service": service
};
data.push(json);
draw(data)
})
Here is working code if fiddle isn't working :
var data = [
{
service: "QA",
count: "25262"
}, {
service: "QB",
count: "42386"
}, {
service: "QUERY_NOTICICATIONS",
count: "14042"
}, {
service: "TTL",
count: "4088"
}
];
// Mike Bostock "margin conventions"
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = window.innerWidth - margin.left - margin.right,
height = window.innerHeight/1.5 - margin.top - margin.bottom;
// D3 scales = just math
// x is a function that transforms from "domain" (data) into "range" (usual pixels)
// domain gets set after the data loads
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
// D3 Axis - renders a d3 scale in SVG
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
//.ticks(10, "%");
// create an SVG element (appended to body)
// set size
// add a "g" element (think "group")
// annoying d3 gotcha - the 'svg' variable here is a 'g' element
// the final line sets the transform on <g>, not on <svg>
var svg = d3.select(".chart")
.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 + ")")
svg.append("g")
.attr("class", "y axis")
.append("text") // just for the title (ticks are automatic)
.attr("transform", "rotate(-90)") // rotate the text!
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Frequency");
// d3.tsv is a wrapper around XMLHTTPRequest, returns array of arrays (?) for a TSV file
// type function transforms strings to numbers, dates, etc.
draw(data);
function type(d) {
// + coerces to a Number from a String (or anything)
d.count = +d.count;
return d;
}
function draw(data) {
// measure the domain (for x, unique letters) (for y [0,maxFrequency])
// now the scales are finished and usable
x.domain(data.map(function(d) { return d.service; }));
y.domain([0, d3.max(data, function(d) { return d.count; })]);
// another g element, this time to move the origin to the bottom of the svg element
// someSelection.call(thing) is roughly equivalent to thing(someSelection[i])
// for everything in the selection\
// the end result is g populated with text and lines!
svg.select('.x.axis').transition().duration(300).call(xAxis);
// same for yAxis but with more transform and a title
svg.select(".y.axis").transition().duration(300).call(yAxis)
// THIS IS THE ACTUAL WORK!
var bars = svg.selectAll(".bar").data(data) // (data) is an array/iterable thing, second argument is an ID generator function
bars.exit()
.transition()
.duration(300)
.attr("y", y(0))
.attr("height", height - y(0))
.style('fill-opacity', 1e-6)
.remove();
// data that needs DOM = enter() (a set/selection, not an event!)
bars.enter().append("rect")
.attr("class", "bar")
.attr("y", function(d) {
return y(d.count);
})
.attr("height", function(d) {
return height - y(d.count);
})
// the "UPDATE" set:
bars.transition().duration(300).attr("x", function(d) { return x(d.service); }) // (d) is one item from the data array, x is the scale object from above
.attr("width", x.rangeBand()) // constant, so no callback function(d) here
.attr("y", function(d) { return y(d.count); })
.attr("height", function(d) { return height - y(d.count); }); // flip the height, because y's domain is bottom up, but SVG renders top down
}
d3.select("button")
.attr("id", "submit")
.on("click", function() {
var service = document.getElementById("service").value;
var count = document.getElementById("count").value;
var json = {
"count": count,
"service": service
};
data.push(json);
draw(data)
})
#tooltip {
position: absolute;
width: 200px;
height: auto;
padding: 10px;
background-color: white;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
pointer-events: none;
}
#tooltip.hidden {
display: none;
}
#tooltip p {
margin: 0;
font-family: sans-serif;
font-size: 16px;
line-height: 20px;
}
.chart rect {
fill: steelblue;
}
.chart text {
font: 10px sans-serif;
text-anchor: end;
}
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
svg text {
pointer-events: none;
}
rect {
-moz-transition: all 0.3s;
-o-transition: all 0.3s;
-webkit-transition: all 0.3s;
transition: all 0.3s;
}
rect:hover {
fill: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<body>
<svg class="chart"></svg>
<div class="input">
<p>Service :
<input id="service" type="text"></input> Count :
<input id="count" type="text"></input>
</p>
<br/>
<button id="submit">Submit</button>
</div>
<div id="tooltip" class="hidden">
<p><strong>Tooltip</strong></p>
<p><span id="service"></span></p>
<p><span id="count"></span></p>
</div>
</body>
There is a small mistake in your code. Use x(d.service) instead of x(i) to calculate x position of bars in click function.
bars.transition()
.duration(1000)
.attr("x", function(d, i) {
return x(d.service); //instead of x(i);
})
.attr("y", function(d) {
return y(d.count);
})
.attr("width", x.rangeBand())
.attr("height", function(d) {
return height - y(d.count);
});
var data = [
{
service: "QA",
count: "25262"
}, {
service: "QB",
count: "42386"
}, {
service: "QUERY_NOTICICATIONS",
count: "14042"
}, {
service: "TTL",
count: "4088"
}
];
var width = 960,
barHeight = 500;
var margin = {
top: 20,
right: 30,
bottom: 50,
left: 60
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
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 chart = d3.select(".chart")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
x.domain(data.map(function(d) {
return d.service;
}));
y.domain([0, d3.max(data, function(d) {
return d.count
})]);
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
chart.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("Count");
chart.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.service);
})
.attr("y", function(d) {
return y(d.count);
})
.attr("height", function(d) {
return height - y(d.count);
})
.attr("width", x.rangeBand())
.on("mouseover", function(d) {
var xPos = parseFloat(d3.select(this).attr("x")) + x.rangeBand() / 2;
var yPos = parseFloat(d3.select(this).attr("y")) / 2 + height / 2;
//update tooltip positiom
d3.select("#tooltip")
.style("left", xPos + "px")
.style("top", yPos + "px")
.select("#service")
.text("Service: " + d.service);
d3.select("#tooltip")
.style("left", xPos + "px")
.style("top", yPos + "px")
.select("#count")
.text("Count: " + d.count);
//show tooltip
d3.select("#tooltip").classed("hidden", false);
})
.on("mouseout", function() {
d3.select("#tooltip").classed("hidden", true);
});
d3.select("button")
.attr("id", "submit")
.on("click", function() {
var service = document.getElementById("service").value;
var count = document.getElementById("count").value;
var json = {
"count": count,
"service": service
};
data.push(json);
console.log(data);
x.domain(data.map(function(d) {
return d.service;
}));
y.domain([0, d3.max(data, function(d) {
return d.count
})]);
chart.select(".x.axis")
.transition()
.duration(1000)
.call(xAxis);
chart.select(".y.axis")
.transition()
.duration(1000)
.call(yAxis);
var bars = chart.selectAll(".bar")
.data(data);
bars.enter().append("rect");
bars.attr("class", "bar")
.attr("x", function(d) {
return x(d.service);
})
.attr("y", function(d) {
return y(d.count);
})
.attr("height", function(d) {
return height - y(d.count);
})
.attr("width", x.rangeBand())
.on("mouseover", function(d) {
var xPos = parseFloat(d3.select(this).attr("x")) + x.rangeBand() / 2;
var yPos = parseFloat(d3.select(this).attr("y")) / 2 + height / 2;
//update tooltip positiom
d3.select("#tooltip")
.style("left", xPos + "px")
.style("top", yPos + "px")
.select("#service")
.text("Service: " + d.service);
d3.select("#tooltip")
.style("left", xPos + "px")
.style("top", yPos + "px")
.select("#count")
.text("Count: " + d.count);
//show tooltip
d3.select("#tooltip").classed("hidden", false);
})
.on("mouseout", function() {
d3.select("#tooltip").classed("hidden", true);
});
bars.transition()
.duration(1000)
.attr("x", function(d, i) {
return x(d.service);
})
.attr("y", function(d) {
return y(d.count);
})
.attr("width", x.rangeBand())
.attr("height", function(d) {
return height - y(d.count);
});
})
#tooltip {
position: absolute;
width: 200px;
height: auto;
padding: 10px;
background-color: white;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
pointer-events: none;
}
#tooltip.hidden {
display: none;
}
#tooltip p {
margin: 0;
font-family: sans-serif;
font-size: 16px;
line-height: 20px;
}
.chart rect {
fill: steelblue;
}
.chart text {
font: 10px sans-serif;
text-anchor: end;
}
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
svg text {
pointer-events: none;
}
rect {
-moz-transition: all 0.3s;
-o-transition: all 0.3s;
-webkit-transition: all 0.3s;
transition: all 0.3s;
}
rect:hover {
fill: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg class="chart"></svg>
<div class="input">
<p>Service :
<input id="service" type="text" />Count :
<input id="count" type="text" />
</p>
<br/>
<button id="submit">Submit</button>
</div>
<div id="tooltip" class="hidden">
<p><strong>Tooltip</strong>
</p>
<p><span id="service"></span>
</p>
<p><span id="count"></span>
</p>
</div>
I want to create stacked bar chart with d3.
I have this data in CSV file:
Type Sum Color
Regular 29756.85897 green
Regular 9756.85897 blue
and I want that each row will appear above the other in Y axis.
for example in this photo, the blue area should start in y=9756 until y=39512.
what should I change?
this is the relevant html code:
the whole code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
margin:auto;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar1 {
fill: #00FF66;
}
.bar1:hover {
fill: black ;
}
.x.axis path {
display: none;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script>
var margin = {top: 80, right: 90, bottom: 30, left: 90},
width = 1000 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
//יצירת X
//יאכלס את סוגי הרכב השונים
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
//יצירת ציר y
//יציג בר עבור מחיר הרכב המוצע לדילרים
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
//יצירת ציר הY
//והצמדתו לצד שמאל
var yAxis = d3.svg.axis()
.scale(y)
.orient("left").ticks(4)
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong></strong>"+d.Type+"<br><strong></strong> <span style='color:#00FF66'>" + d.Sum + "</span>";
})
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.call(tip);
//קליטת הטבלה והגדרת הטווחים על הצירים
d3.csv("Targil2.csv", type, function(error, data) {
x.domain(data.map(function(d) { return d.Type; }));
y.domain([0, d3.max(data, function(d) { return d.Sum*2; })]);
var stack = d3.layout.stack();
.x(function(d) { return d.Type }) // tell d3 to use Type as x value
.y(function(d) { return d.Sum }); // tell d3 to use Sum as y value
var stackData = stack(data);
//הוספה של 2 הצירים
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis axisLeft")
.attr("transform", "translate(0,0)")
.call(yAxis)
.append("text")
.attr("y", 6)
.attr("dy", "-2em")
.style("text-anchor", "end")
.style("text-anchor", "end")
.text("Price");
//הוספת בר הנתונים
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("x", function(d) { return x(d.Type); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return d.y0 })
.attr("height", function(d) { return (height - y(d.Sum)); })
.style("fill", function(d){
if(d["Color"] == "green"){ return "green";}
else return "#0066FF";})
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
});
function type(d) {
d.Sum = +d.Sum;
return d;
}
</script>
</body>
</html>
I tried to use that stack function as you told me, and changed the attribute of "y" , but it's not work for me now. I think I did something wrong.
Here you go.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
margin:auto;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar1 {
fill: #00FF66;
}
.bar1:hover {
fill: black ;
}
.x.axis path {
display: none;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script>
var margin = {top: 80, right: 90, bottom: 30, left: 90},
width = 1000 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
//יצירת X
//יאכלס את סוגי הרכב השונים
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
//יצירת ציר y
//יציג בר עבור מחיר הרכב המוצע לדילרים
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
//יצירת ציר הY
//והצמדתו לצד שמאל
var yAxis = d3.svg.axis()
.scale(y)
.orient("left").ticks(4)
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong></strong>"+d.Type+"<br><strong></strong> <span style='color:#00FF66'>" + d.Sum + "</span>";
})
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.call(tip);
//קליטת הטבלה והגדרת הטווחים על הצירים
d3.csv("Targil2.csv", type, function(error, data) {
window.dataSet = data;
data.sort(function(x,y){
var a = x.Sum;
var b = y.Sum;
return a > b ? -1 : a < b ? 1 : 0
})
x.domain(data.map(function(d) { return d.Type; }));
y.domain([0, d3.max(data, function(d) { return d.Sum*2; })]);
var stack = d3.layout.stack()
.x(function(d) { return d.Type }) // tell d3 to use Type as x value
.y(function(d) { return d.Sum }); // tell d3 to use Sum as y value
// var stackData = stack(data);
//הוספה של 2 הצירים
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis axisLeft")
.attr("transform", "translate(0,0)")
.call(yAxis)
.append("text")
.attr("y", 6)
.attr("dy", "-2em")
.style("text-anchor", "end")
.style("text-anchor", "end")
.text("Price");
var stackSoFar = 0;
//הוספת בר הנתונים
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("x", function(d) { return x(d.Type); })
.attr("width", x.rangeBand())
.attr("y", function(d){
d3.select(this)
.attr("height", function(d2){
var thisHeight = height - y(d.Sum);
stackSoFar += thisHeight
return thisHeight
});
return (height - stackSoFar)
})
.style("fill", function(d){
if(d["Color"] == "green"){ return "green";}
else return "#0066FF";})
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
});
function type(d) {
d.Sum = +d.Sum;
return d;
}
</script>
</body>
</html>
first of all, I guess that when you say
for example in this photo, the blue area should start in y=9756 until
y=39512
You actually mean
for example in this photo, the blue area should start in y=29756 until
y=39512
What happens is that your green area is painted from 0 to 29756 then your blue area on top of it from 0 to 9756. You need to shift each area on top of the previous one.
Easiest is to preprocess your data to do it.
D3.js can do it for you, see Stack Layout. This computes the y0 and y for all of your layers.
EDIT:
var stack = d3.layout.stack()
.x(function(d) { return d.Type }) // tell d3 to use Type as x value
.y(function(d) { return d.Sum }); // tell d3 to use Sum as y value
var stackData = stack(data);
After that, you data is augmented, i.e. each entry contains an additional y and y0 values that you can use directly to plot (in your y and height attribute).