我在网页上将我的 D3 map 居中时遇到困难。 map 位于 map 类和 div 中,但 CSS 似乎不会使其居中。
我对 SVG 所在的类“.map”应用的任何边距似乎也不起作用。我不确定为什么我无法将任何 CSS 应用于 map ,但也许我应该在实际的 D3 代码中做一些事情?不确定。谢谢!
这是我的代码:
<!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>
最佳答案
将 map 包含在另一个 div 中,其宽度与其上方的框相同 (75%)。您可能希望将 div 样式移动到 CSS
类,如果它按您想要的方式工作的话。
<div style="display:block; margin-left:auto; margin-right:auto; width:75%">
<div id="map">
...
</div>
</div>
更新
我刚刚发现了真正的问题。您对 map 的 css
定义是针对类的,而不是针对 id 的。并且......如果你想使用自动边距,你需要定义一个宽度。
更改您的 css 以匹配以下内容:
#map {
width: 75%;
margin-left: auto;
margin-right: auto;
}
关于css - D3 map 不以页面为中心?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49278757/