I'm having difficulty centering my D3 map on the webpage. The map is in a map class and within a div, but CSS won't appear to center it.
Any margins I apply to the class ".map", which the SVG is in, doesn't appear to work either. I'm not sure why I'm unable to apply any CSS to the map, but maybe I'm supposed to do something in the actual D3 code? Unsure. Thanks!
Here's my code:
<!DOCTYPE html>
<html>
<head>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.js'></script>
<meta charset='utf-8'>
<meta name="viewport" content='width=device-width, initial-scale=1.0'>
<title></title>
<style>
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 10px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 10px;
}
.active {
fill: rgba(149, 165, 166, 0.8);
}
body {
background: rgba(32, 32, 32, 1);
color: rgba(255, 255, 255, 0.8);
}
h1 {
font-family: Impact, Charcoal, sans-serif;
text-align: center;
}
h2 {
font-family: Impact, Charcoal, sans-serif;
text-align: center;
}
p {
font-family: "Arial Black", Gadget, sans-serif;
text-align: center;
}
#box {
border: 10px solid black;
margin: auto;
padding: 10px;
width: 75%;
border-radius: 10px;
}
.map {
margin-left: auto;
margin-right: auto;
}
</style>
<script>
function draw(geo_data) {
var margin = 0,
width = 2000 - margin,
height = 700 - margin;
var centered;
var svg = d3.select('#map')
.append('svg')
.attr('width', width + margin)
.attr('height', height + margin)
.append('g')
.attr('class', 'map');
var formatComma = d3.format(",")
var projection = d3.geoAlbersUsa();
var path = d3.geoPath().projection(projection);
var map = svg.selectAll('path')
.data(geo_data.features)
.enter()
.append('path')
.attr('d', path)
.attr('fill', 'rgba(105, 105, 105, 1)')
.attr('stroke', 'rgba(0, 0, 0, 1)')
.attr('stroke-width', 0.5)
.on('mouseover', function(d) {
d3.select(this).attr('fill', 'rgba(108, 122, 137, 0.5)')
})
.on('mouseout', function() {
if (d3.select(this).classed('clicked')) {
console.log('is clicked')
d3.select(this).attr('fill', 'rgba(105, 105, 105, 1)')
} else {
console.log('is not clicked')
d3.select(this).attr('fill', 'rgba(105, 105, 105, 1)')
}
})
// Calls click-to-zoom function defined below.
.on('click', clicked);
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<p><font size='4rem'>" + d.city + ", " + d.state + "</p></font>" + "<p><font size='3rem'><strong>Guns Manufactured: </strong>" + formatComma(d.guns) + "</p>" +
"<p><strong>Top Manufacturer:</strong> " + d.manufacturer +
"</p></font>";
})
svg.call(tip);
// Click-to-zoom function adapted from Mike Bostock's code: https://bl.ocks.org/mbostock/2206590
function clicked(d) {
d3.select(this).attr('fill', 'rgba(108, 122, 137, 0.5)');
if (d3.select(this).classed('clicked')) {
d3.select(this).attr('clicked', false);
} else {
d3.select(this).attr('clicked', true);
}
var x, y, k;
if (d && centered !== d) {
var centroid = path.centroid(d);
x = centroid[0];
y = centroid[1];
k = 4;
centered = d;
} else {
x = width / 2;
y = height / 2;
k = 1;
centered = null;
}
map.selectAll('path')
.classed('active', centered && function(d) {
return d === centered;
});
map.transition()
.duration(1000)
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')scale(' + k + ')translate(' + -x + ',' + -y + ')')
.style('stroke-width', 1 / k + 'px');
// Transitions circles upon zoom.
svg.selectAll('circle')
.transition()
.duration(1000)
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')scale(' + k + ')translate(' + -x + ',' + -y + ')')
.style('stroke-width', 1 / k + 'px');
}
d3.csv('https://raw.githubusercontent.com/dieterholger/US-Gun-Manufacturing-Interactive/master/top100cities.csv', function(error, data) {
// Converts strings in csv to integers so they can be used.
data.forEach(function(d) {
return d.guns = +d.guns;
})
// This returns the max number of guns.
var guns = data.map(function(d) {
return d.guns;
});
var guns_extent = d3.extent(data, function(d) {
return d.guns;
});
var radius = d3.scaleSqrt()
.domain(guns_extent)
.range([2, 40]);
svg.append('g')
.attr('class', 'bubble')
.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return projection([d.lon, d.lat])[0];
})
.attr('cy', function(d) {
return projection([d.lon, d.lat])[1];
})
.attr('r', function(d) {
return radius(d.guns);
})
.attr('fill', 'rgba(248, 148, 6, 0.5)')
.attr('stroke', 'black')
.on('mouseover', function(d) {
tip.show(d);
return d3.select(this).attr('fill', 'rgba(248, 148, 6, 0.9)');
})
.on('mouseout', function(d) {
tip.hide(d);
return d3.select(this).attr('fill', 'rgba(248, 148, 6, 0.5)');
})
});
};
</script>
</head>
<body>
<div id='box'>
</div>
<div id='map'>
<h2>Hover your mouse to see data on the cities and click a state to zoom in.</h2>
</div>
<div id='box'>
</div>
<script>
d3.json('https://raw.githubusercontent.com/dieterholger/US-Gun-Manufacturing-Interactive/master/us_states.json', draw);
</script>
</body>