我正在制作一张地图,其中附加到美国地图上城市的圆圈的大小取决于CSV中的值(guns列或JavaScript中的d.guns
)。
我可以在添加圈子的同时使用Math.sqrt()
让圈子调整大小,但我不认为这是正确的方法(或者它没问题?):
.attr('r', function(d) {
return Math.sqrt(d.guns * 0.0010);
})
我尝试使用d3.scaleSqrt()
和d3.extent
根据值调整圈子的大小,但是我在控制台中抛出了这些错误:
以下是我尝试使用d3.scaleSqrt
时的代码:
<head>
<script>
function draw(geo_data) {
'use strict';
var margin = 75,
width = 1920 - margin,
height = 1080 - margin;
var svg = d3.select('body')
.append('svg')
.attr('width', width + margin)
.attr('height', height + margin)
.append('g')
.attr('class', 'map');
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)
.style('fill', 'rgba(253, 227, 167, 0.8)')
.style('stroke', 'black')
.style('stroke-width', 0.4);
d3.csv('top100cities.csv', function(error, data) {
// Converts strings to integers.
data.forEach(function(d) {
return d.guns = +d.guns;
})
var guns_extent = d3.extent(function(d) {
return d.guns;
});
var radius = d3.scaleSqrt()
.domain(guns_extent)
.range([0, 12]);
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);
})
.style('fill', 'rgba(103, 65, 114, 0.5)');
});
};
</script>
<body>
<script>
d3.json('us_states.json', draw);
</script>
</body>
答案 0 :(得分:4)
虽然Xavier Guihot的answer在技术上是正确的并提出了一个有效的解决方案,但它略微偏离了D3赛道。您的代码中的错误是由于未向d3.extent()
提供所有参数而导致的。你只是忘了传入数组,即data
,从中确定范围(强调我的):
var guns_extent = d3.extent(data, function(d) { // Pass in data as first parameter
return d.guns;
});
以下是工作演示:
function draw(geo_data) {
'use strict';
var margin = 75,
width = 1920 - margin,
height = 1080 - margin;
var svg = d3.select('body')
.append('svg')
.attr('width', width + margin)
.attr('height', height + margin)
.append('g')
.attr('class', 'map');
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)
.style('fill', 'rgba(253, 227, 167, 0.8)')
.style('stroke', 'black')
.style('stroke-width', 0.4);
d3.csv("https://raw.githubusercontent.com/dieterholger/US-Gun-Manufacturing-Interactive/master/top100cities.csv", function(error, data) {
// Converts strings to integers.
data.forEach(function(d) {
return d.guns = +d.guns;
})
var guns_extent = d3.extent(data, function(d) { // Pass in data
return d.guns;
});
var radius = d3.scaleSqrt()
.domain(guns_extent)
.range([0, 12]);
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);
})
.style('fill', 'rgba(103, 65, 114, 0.5)');
});
};
d3.json('https://raw.githubusercontent.com/dieterholger/US-Gun-Manufacturing-Interactive/master/us_states.json', draw);
<script src="https://d3js.org/d3.v4.js"></script>
答案 1 :(得分:3)
我认为错误在于检索枪支的最大数量。
这是差异:
let guns = data.map( function(d) { return d.guns });
console.log(Math.max(...guns));
var radius = d3.scaleSqrt().domain([0, Math.max(...guns)]).range([0, 25]);
以下是经过修改的演示:
<head>
<script>
function draw(geo_data) {
'use strict';
var margin = 75,
width = 1920 - margin,
height = 1080 - margin;
var svg = d3.select('body')
.append('svg')
.attr('width', width + margin)
.attr('height', height + margin)
.append('g')
.attr('class', 'map');
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)
.style('fill', 'rgba(253, 227, 167, 0.8)')
.style('stroke', 'black')
.style('stroke-width', 0.4);
d3.csv('https://raw.githubusercontent.com/dieterholger/US-Gun-Manufacturing-Interactive/master/top100cities.csv', function(error, data) {
let guns = data.map( function(d) { return d.guns });
console.log(Math.max(...guns));
var radius = d3.scaleSqrt().domain([0, Math.max(...guns)]).range([0, 25]);
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);
})
.style('fill', 'rgba(103, 65, 114, 0.5)');
});
};
</script>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
d3.json('https://raw.githubusercontent.com/dieterholger/US-Gun-Manufacturing-Interactive/master/us_states.json', draw);
</script>
</body>
答案 2 :(得分:0)
设置圆形区域的公式可能会起作用。
公式为A=πr2
,其中A
等于圆的面积,r
等于半径。
如果A = d.guns
我们知道Area
和π
然后:
r = √(d.guns/π)
.attr("r", function (d) {return Math.sqrt(d.guns/3.1416);})