Related
Does anyone know how I would add a grid to the background of a d3 line graph I have made and does anyone know how I would make my line graph curve rather than be rather rigid like it is now. the code below is for the line graph and it all works with the data file I have I just need it to have a grid on the background and be curved rather than how it is now. I also need to have the y axis display a percent rather than a decimal
any help would be appreciated.
JS, CSS and HTML --
var margin = { top: 20 , right: 20, bottom: 30 , left: 40} ,
width= 960 - margin.left - margin.right ,
height = 500 - margin.top - margin.bottom;
var y = d3.scaleLinear()
.range([height, 0]) ; //remember: up / down are flipped
var x = d3.scaleBand()
.range([0, width]).padding([0.1]); //the last peramter adds padding
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(event,d) {
return "<strong>Frequency:</strong> <span style='color: rgba(223,222,79,255)'>" + d.frequency + "</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("data/data.csv").then(function(data) {
x.domain(data.map(function(d){return d.letter;}));
y.domain([0, d3.max(data, function(d){return d.frequency;})]);
// Remember to add all data dependant calls in here
var xAxis = d3.axisBottom().scale(x); // Positions the Lables Under the xAxis
var yAxis = d3.axisLeft().scale(y); // positions the lables on the left of the yAxis
var line = d3.line()
.x(function(d) { return x(d.letter); })
.y(function(d) { return y(d.frequency); })
x.domain(data.map(function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Frequency");
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
svg.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("class", "circle")
.attr("cx", function(d) {return x (d.letter);})
.attr("cy", function(d) {return y (d.frequency);})
.attr("r", 4)
.attr("width", x.bandwidth())
.attr("height", function(d) {return height - y (d.frequency);})
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
svg.append("text")
.attr("x", (width / 2))
.attr("y", 0 + (margin.top / 2))
.attr("text-anchor", "middle")
.text("Relative Frequence of Letters in the English Alphabet") ;
});
.bar {
fill:rgba(55,125,34,255);
}
.bar:hover {
fill: rgba(55,125,34,255);
}
.axis--x path {
display: none;
}
.line {
fill: none;
stroke: rgba(55,125,34,255);
stroke-width: 3px;
}
.circle {
fill: rgba(55,125,34,255);
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
font-family: 'Courier New', Courier, monospace;
}
/* 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;
}
<!DOCTYPE html>
<html>
<head>
<title>Demo</title>
<link rel="stylesheet" href="css/mystyle.css">
</head>
<body>
<svg class="chart"></svg>
<script type="text/javascript"src="js/d3/d3.js"></script>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/bumbeishvili/d3-tip-for-v6#4/d3-tip.min.js"></script>
<script type="text/javascript"src="js/myscript1.js"></script>
</body>
</html>
You can add gridlines to an axis by using axis.tickSize([size]) or axis.tickSizeInner([size]).
Ex:
var xAxis = d3.axisBottom().scale(x).tickSize(.width);
As for the lines, you can make them curves by using the .curve method of the line, eg:
var line = d3.line()
.x(function(d) { return x(d.letter); })
.y(function(d) { return y(d.frequency); })
.curve(d3.curveBasis)
Check these pages for the full reference:
https://github.com/d3/d3-axis
https://github.com/d3/d3-shape
I am trying to create a slider which reveals data as you slide the bar across from left to right. When I slide from right to left, my data does not show up. And secondly, the highest number the x-axis scales to is 9. I have played around with my data, if I put 8 as the highest value for the x-axis, 8 will be the highest value. But I cannot go beyond 9 for some reason. And not all my data displays even if I have all the numbers under 9.
In my data, I have two columns. One called "ep" (this is for the x-axis), and the other called "char" (this is for the y-axis).
Any ideas on how I can get the x-axis to scale properly and have my data show up?
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title>LD V6</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body {
font-family:"avenir next", Arial, sans-serif;
font-size: 12px;
color: #696969;
}
.ticks {
font-size: 10px;
}
.track,
.track-inset,
.track-overlay {
stroke-linecap: round;
}
.track {
stroke: #000;
stroke-opacity: 0.3;
stroke-width: 10px;
}
.track-inset {
stroke: #dcdcdc;
stroke-width: 8px;
}
.track-overlay {
pointer-events: stroke;
stroke-width: 50px;
stroke: transparent;
cursor: crosshair;
}
.handle {
fill: #fff;
stroke: #000;
stroke-opacity: 0.5;
stroke-width: 1.25px;
}
</style>
</head>
<body>
<div id="vis">
</div>
<script>
var margin = {top:50, right:30, bottom:30, left:30},
width = 960 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var svg = d3.select("#vis")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
////////// slider //////////
var moving = false;
var currentValue = 0;
var targetValue = 200;
var playButton = d3.select("#play-button");
var x = d3.scaleLinear().range([0, width])
.clamp(true);
var y = d3.scaleLinear().range([height, 0]);
var slider = svg.append("g")
.attr("class", "slider")
.attr("transform", "translate(" + 50 + "," + (height) + ")");
slider.append("line")
.attr("class", "track")
.attr("x1", x.range()[0])
.attr("x2", x.range()[1])
.select(function() { return this.parentNode.appendChild(this.cloneNode(true)); })
.attr("class", "track-inset")
.select(function() { return this.parentNode.appendChild(this.cloneNode(true)); })
.attr("class", "track-overlay")
.call(d3.drag()
.on("start.interrupt", function() { slider.interrupt(); })
.on("start drag", function() {
currentValue = d3.event.x;
update(x.invert(currentValue));
})
);
//Attributes of the slider
slider.insert("g", ".track-overlay")
.attr("class", "ticks")
.attr("transform", "translate(0," + 18 + ")")
/* .selectAll("text")
.data(x.ticks(8))
.enter()
.append("text")
.attr("x", x)
.attr("y", 10)
.attr("text-anchor", "middle")
.text(function(d) { return d.ep); }); */
//Attributes of the slider handle
var handle = slider.insert("circle", ".track-overlay")
.attr("class", "handle")
.attr("r", 8);
/*
var label = slider.append("text")
.attr("class", "label")
.attr("text-anchor", "middle")
.text(formatDate(startDate))
.attr("transform", "translate(0," + (-25) + ")")
*/
////////// plot //////////
var dataset;
var plot = svg.append("g")
.attr("class", "plot")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("trial_v3.csv", prepare, function(data) {
dataset = data;
drawPlot(dataset);
// scale the range of the data
y.domain([0, d3.max(data, function(d) { return d.char; })]);
x.domain([0, d3.max(data, function(d) { return d.ep; })]);
// add the Y Axis
svg.append("g")
.call(d3.axisLeft(y))
.attr("transform", "translate(" + 50 + ",0)");
// add the X Axis
svg.append("g")
.call(d3.axisBottom(x))
.attr("transform", "translate(" + 50 +"," + height + ")")
})
function prepare(d) {
d.ep = d.ep;
d.char = d.char;
return d;
}
function drawPlot(data) {
var locations = plot.selectAll(".location")
.data(data);
// if filtered dataset has more circles than already existing, transition new ones in
locations.enter()
.append("circle")
.attr("class", "location")
.attr("cx", function(d) { return x(d.ep); })
.attr("cy", function(d){ return y(d.char)})
.style("opacity", 0.5)
.attr("r", 5)
.transition()
.duration(1200)
.attr("r", 11
);
// if filtered dataset has less circles than already existing, remove excess
locations.exit()
.remove();
}
function update(h) {
// update position and text of label according to slider scale circle
handle.attr("cx", x(h));
/*label
.attr("x", x(h))
.text(formatDate(h)); */
// filter data set and redraw plot
var newData = dataset.filter(function(d) {
return d.ep < h;
})
drawPlot(newData);
};
/////////////////////////////////////////////////// SVG 2 /////////////////////////////////////////////
/*
var svg2 = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg2.append("rect")
.attr("width", 50)
.attr("height",50)
*/
</script>
</body>
I am trying to make a stacked bar chart for a simple dataset (Below you can find codes and the data).
For the bar my mouse hovers on, I try to use CSS hover effect to change the color of the bar (A rect svg element with a class of .bar), and use d3-tip to show a tooltip displaying the region name that bar belongs.
Problems I am having are:
1 - The CSS hover effect is not working at all. (Please find the style sheet below)
2 - the tooltip is showing, but only if I move my mouse cursor from under the bar to enter it. If I move my mouse cursor from left/right/top of the bar, the "mouseover" seems like not being detected. When it is not detected, however if you click on the bar, it will be detected and tooltip will show.
3 - The tooltip is supposed to show the data for "d.State" (which is the region's abbreviation text), but it gives me undefined. "d.State" is working fine with the bar chart itself though - the axis ticks are created using these data.
The stacked bar is made based on this one: https://bl.ocks.org/mbostock/3886208
The tooltip and hover effect is based on this one: http://bl.ocks.org/Caged/6476579
The index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
</head>
<body>
<script type="text/javascript" src="viz.js"></script>
</body>
</html>
The viz.js:
// begin of the js file
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 320 - margin.left - margin.right,
height = 320 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.rangeRound([height, 0]);
var color = d3.scale.ordinal()
.range(["#98abc5", "#7b6888", "#a05d56", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
//define tooltip
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([0, 0])
.html(function(d) {
return "<strong>Region:</strong> <span style='color:red'>" + d.State + "</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 + ")");
//call tooltip
svg.call(tip);
d3.csv("data.csv", function(error, data) {
if (error) throw error;
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "State"; }));
data.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
d.total = d.ages[d.ages.length - 1].y1;
});
data.sort(function(a, b) { return b.total - a.total; });
x.domain(data.map(function(d) { return d.State; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("font-size", 7);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -40)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Number of Organizations");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x(d.State) + ",1)"; });
state.selectAll(".bar")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("class", "bar")
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.style("fill", function(d) { return color(d.name); })
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
var legend = svg.selectAll(".legend")
.data(color.domain().slice().reverse())
.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; });
});
// end of the js file
The style.css:
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar:hover {
fill: steelblue;
pointer-events: all;
}
.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;
}
The data.csv:
State,Non Profit,For Profit,Developer Group,Other
EP,28,142,15,16
EC,81,292,39,22
LC,73,91,23,9
MN,3,5,2,1
NA,102,561,26,19
SA,11,49,9,4
SS,28,10,10,3
If there is any part not clear please let me know. I am new to d3 and stackoverflow. Thanks!
The CSS hover effect is not working at all.(not was missing I guess ?)
The problem was it was already filled using d3. To override it just add !important to on hover fill
fill: steelblue !important;
The tooltip is showing, but only if I move my mouse cursor from under the bar to enter it. If I move my mouse cursor from left/right/top of the bar.(I didn't face any issue with your code ?)
I am not sure what exactly is the problem but, my guess is that, onmouseover will work only when you hover on it. So if the mouse pointer is already on the graph before it was generated, it won't show the tooltip.
The tooltip is supposed to show the data for "d.State".
The problem here is the State data is not attached to the element i.e, d.ages doesn't contain state value. Just attach the state value while binding data.
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 320 - margin.left - margin.right,
height = 320 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.rangeRound([height, 0]);
var color = d3.scale.ordinal()
.range(["#98abc5", "#7b6888", "#a05d56", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
//define tooltip
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([0, 0])
.html(function(d) {
return "<strong>Region:</strong> <span style='color:red'>" + d.State + "</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 + ")");
//call tooltip
svg.call(tip);
d3.csv("data.csv", function(error, data) {
if (error) throw error;
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "State"; }));
data.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
d.total = d.ages[d.ages.length - 1].y1;
});
data.sort(function(a, b) { return b.total - a.total; });
x.domain(data.map(function(d) { return d.State; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("font-size", 7);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -40)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Number of Organizations");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x(d.State) + ",1)"; });
state.selectAll(".bar")
.data(function(d) {
for(var l = 0 ; l < d.ages.length ; l++) {
d.ages[l].State = d.State;
}
return d.ages; })
.enter().append("rect")
.attr("class", "bar")
.attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.style("fill", function(d) { return color(d.name); })
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
var legend = svg.selectAll(".legend")
.data(color.domain().slice().reverse())
.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; });
});
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar:hover {
fill: steelblue !important;
pointer-events: all;
}
.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;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
</head>
<body>
<script type="text/javascript" src="viz.js"></script>
</body>
</html>
I am trying to combine two D3 Visualizations. I found a question before, but it did not really have a solution.
When I combine the two files the visualizations overlap and produce this:
the streamgraph component:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.chart {
background: #fff;
}
p {
font: 12px helvetica;
}
.axis path, .axis line {
fill: none;
stroke: #000;
stroke-width: 2px;
shape-rendering: crispEdges;
}
button {
position: absolute;
right: 50px;
top: 10px;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.js"></script>
<div class="chart">
</div>
<script>
chart("Data.csv", "blue");
var datearray = [];
var colorrange = [];
function chart(csvpath, color) {
if (color == "blue") {
colorrange = ["#045A8D", "#2B8CBE", "#74A9CF", "#A6BDDB", "#D0D1E6", "#F1EEF6"];
}
else if (color == "pink") {
colorrange = ["#980043", "#DD1C77", "#DF65B0", "#C994C7", "#D4B9DA", "#F1EEF6"];
}
else if (color == "orange") {
colorrange = ["#B30000", "#E34A33", "#FC8D59", "#FDBB84", "#FDD49E", "#FEF0D9"];
}
strokecolor = colorrange[0];
var format = d3.time.format("%m/%d/%y");
var margin = {top: 20, right: 40, bottom: 30, left: 50};
var width = document.body.clientWidth - margin.left - margin.right;
var height = 400 - margin.top - margin.bottom;
var tooltip = d3.select("body")
.append("div")
.attr("class", "remove")
.style("position", "absolute")
.style("z-index", "20")
.style("visibility", "hidden")
.style("top", "30px")
.style("left", "75px");
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height-10, 0]);
var z = d3.scale.ordinal()
.range(colorrange);
var xAxis = d3.svg.axis()
.orient("bottom")
.scale(x)
.ticks(d3.time.years, 10); //tick on every 10 years
/*.scale(x)
.orient("bottom")
.text(date)
//;*/
//. tickFormat(x)
//. tickValues(date)
//was already there but out of view -> changed the left margin
var yAxis = d3.svg.axis()
.scale(y);
var stack = d3.layout.stack()
.offset("silhouette")
.values(function(d) { return d.values; })
.x(function(d) { return d.date; })
.y(function(d) { return d.value; });
var nest = d3.nest()
.key(function(d) { return d.key; });
var area = d3.svg.area()
.interpolate("cardinal")
.x(function(d) { return x(d.date); })
.y0(function(d) { return y(d.y0); })
.y1(function(d) { return y(d.y0 + d.y); });
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 + ")");
/* correct this function
var graph = d3.csv(csvpath, function(data) {
data.forEach(function(d) {
d.date = format.parse(d.date);
d.value = +d.value;
});*/
var graph = d3.csv(csvpath, function(raw) {
var data = [];
raw.forEach(function (d) {
data.push({
key: d.Country,
date : new Date(1980,0,1), //I had a bug in creating the right dates
value : parseInt(d['1980-1989'].replace(',','')) //get rid of the thousand separator
});
data.push({
key: d.Country,
date : new Date(1990,0,1),
value : parseInt(d['1990-1999'].replace(',',''))
});
data.push({
key: d.Country,
date : new Date(2000,0,1),
value : parseInt(d['2000-2009'].replace(',','') )
});
});
var layers = stack(nest.entries(data));
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]);
svg.selectAll(".layer")
.data(layers)
.enter().append("path")
.attr("class", "layer")
.attr("d", function(d) { return area(d.values); })
.style("fill", function(d, i) { return z(i); });
//adding .text causes axis to dissapear
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
//.text(date)
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + ", 0)")
//.text(value)
.call(yAxis.orient("right"));
svg.append("g")
.attr("class", "y axis")
.call(yAxis.orient("left"));
var pro;
svg.selectAll(".layer")
.attr("opacity", 1)
.on("mouseover", function(d, i) {
svg.selectAll(".layer").transition()
.duration(250)
.attr("opacity", function(d, j) {
return j != i ? 0.6 : 1;
})})
.on("mousemove", function(d, i) {
var mousex = d3.mouse(this);
mousex = mousex[0];
var invertedx = x.invert(mousex);
//find the largest smaller element
var dd = d.values.filter(function(d) { return d.date <= invertedx; });
dd = dd[dd.length -1]; //use the last element
pro = dd.value;
d3.select(this)
.classed("hover", true)
.attr("stroke", strokecolor)
.attr("stroke-width", "0.5px");
tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "visible");
})
.on("mouseout", function(d, i) {
svg.selectAll(".layer")
.transition()
.duration(250)
.attr("opacity", "1");
d3.select(this)
.classed("hover", false)
.attr("stroke-width", "0px");
tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "hidden");
})
var vertical = d3.select(".chart")
.append("div")
.attr("class", "remove")
.style("position", "absolute")
.style("z-index", "19")
.style("width", "1px")
.style("height", "380px")
.style("top", "10px")
.style("bottom", "30px")
.style("left", "0px")
.style("background", "#fff");
d3.select(".chart")
.on("mousemove", function(){
var mousex = d3.mouse(this);
mousex = mousex[0] + 5;
vertical.style("left", mousex + "px" )})
.on("mouseover", function(){
var mousex = d3.mouse(this);
mousex = mousex[0] + 5;
vertical.style("left", mousex + "px")});
});
}
</script>
Map component:
<!DOCTYPE html>
<meta charset="utf-8">
<title>U.S Immigration Data Visualization</title>
<style>
.country:hover{
stroke: #fff;
stroke-width: 1.5px;
}
.text{
font-size:10px;
text-transform:capitalize;
}
#container {
margin: 10px 10%;
border:2px solid #000;
border-radius: 5px;
height:100%;
overflow:hidden;
background: #e1eafe;
}
.hidden {
display: none;
}
div.tooltip {
color: #222;
background: #fff;
padding: .5em;
text-shadow: #f5f5f5 0 1px 0;
border-radius: 2px;
box-shadow: 0px 0px 2px 0px #a6a6a6;
opacity: 0.9;
position: absolute;
}
.graticule {
fill: none;
stroke: #bbb;
stroke-width: .5px;
stroke-opacity: .5;
}
.equator {
stroke: #ccc;
stroke-width: 1px;
}
</style>
</head>
<br>
<h1><center>U.S Immigration Data Visualization</center></h1>
<h2><b>Work in Progress</b></h2>
<h3><b>Ex-USSR countries included in Russia</b></h3>
<h3><b>Ex-Yugoslavia included in Macedonia</b></h3>
<div id="container"></div>
<script src="js/d3.min.js"></script>
<script src="js/topojson.v1.min.js"></script>
<script src="http://d3js.org/d3.geo.tile.v0.min.js"></script>
<script>
d3.select(window).on("resize", throttle);
var zoom = d3.behavior.zoom()
.scaleExtent([1, 9])
.on("zoom", move);
var width = document.getElementById('container').offsetWidth;
var height = width / 2;
var topo,projection,path,svg,g;
var graticule = d3.geo.graticule();
var tooltip = d3.select("#container").append("div").attr("class", "tooltip hidden");
setup(width,height);
function setup(width,height){
projection = d3.geo.mercator()
.translate([(width/2), (height/2)])
.scale( width / 2 / Math.PI);
path = d3.geo.path().projection(projection);
svg = d3.select("#container").append("svg")
.attr("width", width)
.attr("height", height)
.call(zoom)
.on("click", click)
.append("g");
g = svg.append("g");
}
d3.json("data/world-topo-min.json", function(error, world) {
var countries = topojson.feature(world, world.objects.countries).features;
topo = countries;
draw(topo);
});
function draw(topo) {
svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
g.append("path")
.datum({type: "LineString", coordinates: [[-180, 0], [-90, 0], [0, 0], [90, 0], [180, 0]]})
.attr("class", "equator")
.attr("d", path);
var country = g.selectAll(".country").data(topo);
country.enter().insert("path")
.attr("class", "country")
.attr("d", path)
.attr("id", function(d,i) { return d.id; })
.attr("title", function(d,i) { return d.properties.name; })
.style("fill", function(d, i) { return d.properties.color; });
//offsets for tooltips
var offsetL = document.getElementById('container').offsetLeft+20;
var offsetT = document.getElementById('container').offsetTop+10;
//tooltips
country
.on("mousemove", function(d,i) {
var mouse = d3.mouse(svg.node()).map( function(d) { return parseInt(d); } );
tooltip.classed("hidden", false)
.attr("style", "left:"+(mouse[0]+offsetL)+"px;top:"+(mouse[1]+offsetT)+"px")
.html(d.properties.name);
})
.on("mouseout", function(d,i) {
tooltip.classed("hidden", true);
});
//EXAMPLE: adding some capitals from external CSV file
d3.csv("Data.csv", function(err, capitals) {
capitals.forEach(function(i){
addpoint(i.CapitalLongitude, i.CapitalLatitude );
});
});
}
function redraw() {
width = document.getElementById('container').offsetWidth;
height = width / 2;
d3.select('svg').remove();
setup(width,height);
draw(topo);
}
function move() {
var t = d3.event.translate;
var s = d3.event.scale;
zscale = s;
var h = height/4;
t[0] = Math.min(
(width/height) * (s - 1),
Math.max( width * (1 - s), t[0] )
);
t[1] = Math.min(
h * (s - 1) + h * s,
Math.max(height * (1 - s) - h * s, t[1])
);
zoom.translate(t);
g.attr("transform", "translate(" + t + ")scale(" + s + ")");
//adjust the country hover stroke width based on zoom level
d3.selectAll(".country").style("stroke-width", 1.5 / s);
}
var throttleTimer;
function throttle() {
window.clearTimeout(throttleTimer);
throttleTimer = window.setTimeout(function() {
redraw();
}, 200);
}
//geo translation on mouse click in map
function click() {
var latlon = projection.invert(d3.mouse(this));
console.log(latlon);
}
//function to add points and text to the map (used in plotting capitals)
function addpoint(lat,lon,text) {
var gpoint = g.append("g").attr("class", "gpoint");
var x = projection([lat,lon])[0];
var y = projection([lat,lon])[1];
gpoint.append("svg:circle")
.attr("cx", x)
.attr("cy", y)
.attr("class","point")
.attr("r", 1);
//conditional in case a point has no associated text
//if(text.length>0){
// gpoint.append("text")
// .attr("x", x+2)
// .attr("y", y+2)
// .attr("class","text")
// .text(text);
//}
}
</script>
</body>
</html>
This is hard to answer without the code you actually use when you 'combine' the two SVG elements, and without the data or a working example.
What I've done is take the 2 basic components, the streamgraph (and svg node inside <div class="chart">) and the map (a separate svg node in <div id="container"></div>), and create working code that combines the 2:
http://plnkr.co/edit/WjlObRIasLYXOuEL4HDE?p=preview
This is the basic code:
<body>
<div class="chart">
</div>
<div id="container">
</div>
<script type="text/javascript">
var width = 300;
var height = width / 2;
// Equivalent of streamgraph code...
var svg_stream = d3.select(".chart")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("rect")
... // rect attributes
// Equivalent of map code...
var svg_map = d3.select("#container")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("circle")
... // circle attributes
</script>
</body>
What's inside each svg shouldn't make a difference to the positioning, so I've just used a rect to represent the streamgraph and a circle for the map. I've taken as much of the CSS and code from your snippets as it makes sense to. If you combine the two components as in the example above, you should not see any overlap. I'm not really able to correct your version as I don't know how you did it.
Note - You should also avoid defining duplicate variable names (like var svg for both SVGs) when combining the components
I have a simple stacked bar chart :
The code is here.
I would like to have scroll-bar on the axis but as you can see in the link the scroll appears for the div container with the help of CSS.
But i need something like this chart with scroll!
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<script src="https://ajax.goquery.min.js"></script>
<style>
.axis path,
.axis line {
fill: none;
stroke: #BDBDBD;
}
.axis text {
font-family: 'Open Sans regular', 'Open Sans';
font-size: 13px;
}
.y.axis{
direction: ltr;
}
.grid .tick {
stroke: lightgrey;
opacity: 0.7;
}
.grid path {
stroke-width: 0;
}
.rect {
stroke: lightgrey;
fill-opacity: 0.6;
}
.wrapperDiv {
Width: 984px;
height: 35px;
border: thin solid black;
#margin-top: 36px;
#margin-bottom: 48px;
#margin-right: 20px;
#margin-left: 0px;
}
.divChart {
float:left;
font-size:13px;
color : #424242;
font-family: 'Open Sans regular', 'Open Sans';
#border: thin solid white;
margin-top: -0px;
#margin-bottom: 48px;
#margin-right: 150px;
margin-left: 50px;
#background-color: lightgrey;
width: 984px;
height: 500px;
#padding: 25px;
border: thin solid navy;
#margin: 25px;
#max-height:500px;
overflow-y:scroll;
direction: rtl;
}
</style>
</head>
<body>
<div class="divChart" id="wrapper-chart">
<div id ="chartID" ></div>
</div>
<script src="http://d3js.org/d3.v3.min.js"></script><script>
<script>
var dataset = [{"key":"Completion","values":[{"name":"Module 1","value":0},{"name":"Module 2","value":0},{"name":"Module 3","value":0},{"name":"Module 4","value":0},{"name":"Module 5","value":0},{"name":"Module 6","value":0},{"name":"Module 7","value":0},{"name":"Module 8","value":0.56},{"name":"Module 9","value":13.24},{"name":"Module 10","value":12.66}]},{"key":"NonCompletion","values":[{"name":"Module 1","value":100},{"name":"Module 2","value":100},{"name":"Module 3","value":100},{"name":"Module 4","value":100},{"name":"Module 5","value":100},{"name":"Module 6","value":100},{"name":"Module 7","value":100},{"name":"Module 8","value":99.44},{"name":"Module 9","value":86.76},{"name":"Module 10","value":87.34}]}];
function intChart(chartID, dataset) {
var margins = {top: 20, right: 20, bottom: 30, left: 120};
var width = 880 - margins.left -margins.right;
var height = 5250- margins.top - margins.bottom;
var old_width = width,old_height= height;
var module_fixed = 80;
height = Math.floor((dataset[0].values.length * height)/module_fixed)
var x = d3.scale.ordinal().rangeRoundBands([0, width], .1,.1)
var y = d3.scale.linear().rangeRound([height, 0], .1);
var series = dataset.map(function(d) {
return d.key;
});
dataset = dataset.map(function(d) {
return d.values.map(function(o, i) {
// Structure it so that your numeric
// axis (the stacked amount) is y
return {
y: o.value,
x: o.name
};
});
});
var stack = d3.layout.stack();
stack(dataset);
var dataset = dataset.map(function(
group) {
return group.map(function(d) {
// Invert the x and y values, and y0 becomes x0
return {
x: d.y,
y: d.x,
x0: d.y0
};
});
});
var xMax = d3.max(dataset, function(
group) {
return d3.max(group, function(d) {
return d.x + d.x0;
});
});
var xScale = d3.scale.linear()
.domain([0, xMax])
.range([0, width]);
var moduleName = dataset[0]
.map(function(d) {
return d.y;
});
var yScale = d3.scale.ordinal()
.domain(moduleName)
.rangeRoundBands([height,0]);
var svg = d3.select('#chartID')
.append('svg')
.attr("width", width + margins.left +
margins.right)
.attr("height", height + margins.top +
margins.bottom)
.append('g')
.attr('transform', 'translate(60,' + margins.top +
')');
var xAxis = d3.svg.axis()
.scale(xScale)
.orient('bottom')
.ticks(2)
.tickSize(0)
.tickPadding(20)
.tickFormat(function(d) {
return d + "%";
});
var yAxis = d3.svg.axis()
.scale(yScale)
.orient('left')
.tickSize(0);
var colours = d3.scale.ordinal().range(
["#8bc34a", "#ff8a65"]);
var groups = svg.selectAll('g')
.data(dataset)
.enter()
.append('g').attr('class', 'stacked')
.style('fill', function(d, i) {
return colours(i);
});
var rects = groups.selectAll(
'stackedBar')
.data(function(d, i) {
return d;
})
.enter()
.append('rect')
.attr('class', 'stackedBar')
.attr('x', function(d) {
return xScale(d.x0);
})
.attr('y', function(d, i) {
return yScale(d.y);
})
.attr('height', 48)
.attr('width', 0)
rects.transition()
.delay(function(d, i) {
return i * 50;
})
.attr("x", function(d) {
return xScale(d.x0);
})
.attr("width", function(d) {
return xScale(d.x);
})
.duration(3000);
//Added
x.domain(dataset.map(function(d) {
return d.value;
}));
y.domain([0, d3.max(dataset, function(
d) {
return d.name;
})]);
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' +height + ')')
.call(xAxis)
.append("text")
.attr("transform", "rotate(360)")
.attr("y",10)
.attr("x", 140)
.attr("dy", ".30em")
.text("Percentage of Students");
svg.append('g')
.attr('class', 'y axis')
.call(yAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.5em")
.attr("dy", ".15em")
.attr("y", "-")
.attr("opacity", 1)
.attr("transform", function(d) {
return "rotate(-40)"
})
// Draw Y-axis grid lines
svg.selectAll("line.y")
.data(y.ticks(2))
.enter().append("line")
.attr("class", "y")
.attr("x1", 0)
.attr("x2", 450)
.attr("y1", y)
.attr("y2", y)
.style("stroke", "#ccc");
}
$(document).ready(function(){
intChart("chartID", dataset);
});
</script>
Would appreciate any help.
Thanks in advance.
I don't think this can be done using D3 only. If you want to use CSS, you need to fix the position of the x-axis. You can add a separate DIV and SVG container for the X axis (these are not scrollable), and the rest of the chart in another.
I modified you code to do this see here. Please note that you code needs a lot of cleaning, as there are several non-functional parts that makes it really confusing.
The modifications are as follows:
HTML
Added a new DIV (xaxis)
<div id="wrapper-chart">
<div class="divChart" id="chartID"></div>
<div id="xaxis"></div>
</div>
CSS
Added styling for the new div (same as divChart but without the scrolling)
#xaxis {
float: left;
font-size: 13px;
color: #424242;
font-family: 'Open Sans regular', 'Open Sans';
width: 984px;
direction: rtl;
}
JS
A new SVG container for the x-axis. Notice the height attribute.
var xaxis_svg = d3.select('#xaxis')
.append('svg')
.attr("width", width + margins.left + margins.right)
.attr("height", margins.bottom)
.append('g')
.attr('transform', 'translate(60,0)');
Append the x-axis to the container.
xaxis_svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + 0 + ')')
.call(xAxis)
.append("text")
.attr("y", 10)
.attr("x", 140)
.attr("dy", ".30em")
.text("Percentage of Students");
Hope this helps.