Я строю карту Choropleth в D3.js.
Учитывая, что шкала квантования делит значения на несколько отдельных сегментов, назначая цвет каждому в зависимости от того, в какой сегмент он попадает.Как можно понять из приведенного ниже кода, я решил передать массив цветов, зная, что функция масштабирования затем создает корзину для каждого цвета.
var color = d3.scaleQuatize().range([
'rgb(247,251,255)', 'rgb(222,235,247)', 'rgb(198,219,239)',
'rgb(158,202,225)', 'rgb(107,174,214)', 'rgb(66,146,198)',
'rgb(33,113,181)', 'rgb(8,81,156)', 'rgb(8,48,107)'
]);
Поскольку я собираюсь создать легенду на основе«Ведра», которые scaleQuantize создает из данных, приветствуют любые советы о том, как это сделать.
Легенда, которую я пытаюсь воспроизвести, такова: https://beta.observablehq.com/@mbostock/d3-choropleth
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VI - Gonçalo Peres</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
<link rel="stylesheet" type="text/css"
href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<nav class="navbar navbar-default">
<div id="mySidenav" class="sidenav">
<a href="javascript:void(0)" class="closebtn" onclick="closeNav()">×</a>
<a href="#">Contexto</a>
<a href="#">1.ª Codificação Visual</a>
<a href="#">2.ª Codificação Visual</a>
<a href="#">3.ª Codificação Visual</a>
</div>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ Menu</span>
<br>
<br>
<div class="container">
<a class="navbar-brand" href="#"><img id="logo" src="img/logo.png"></a>
</div>
</nav>
<div id="intro">
<h2>1.ª Codificação Visual</h2>
<span>Lorem ipsum.</span><br>
<span>Lorem Ipsum.</span><br>
</div>
<div id="legenda">
<h4>Legenda</h4>
<span>Lorem ipsum.</span><br>
<span>Lorem ipsum.</span><br>
</div>
<div id="chart"></div>
<div id="buttons">
<button type="button" class="panning up"><i class="fa fa-arrow-up"></i></button>
<button type="button" class="panning down"><i class="fa fa-arrow-down"></i></button>
<button type="button" class="panning left"><i class="fa fa-arrow-left"></i></button>
<button type="button" class="panning right"><i class="fa fa-arrow-right"></i></button>
<button type="button" class="zooming in"><i class="fa fa-plus"></i></button>
<button type="button" class="zooming out"><i class="fa fa-minus"></i></button>
</div>
<div id="note">
<span>Gonçalo Peres | <b><a href="http://goncaloperes.com/" target="_blank">GoncaloPeres.com</a></b></span><br>
<span>Data from: <a href="https://public.enigma.com/datasets/u-s-department-of-agriculture-honey-production-2013/41cf2441-e96f-4113-a02f-402d167a9cd8" target="_blank">Enigma Public</a></span>
</div>
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="js/app.js"></script>
</body>
</html>
app.js
// Width and height
var chart_width = 800;
var chart_height = 600;
var color = d3.scaleQuantize().range([
'rgb(247,251,255)', 'rgb(222,235,247)', 'rgb(198,219,239)',
'rgb(158,202,225)', 'rgb(107,174,214)', 'rgb(66,146,198)',
'rgb(33,113,181)', 'rgb(8,81,156)', 'rgb(8,48,107)'
]);
//Navbar
function openNav() {
document.getElementById("mySidenav").style.width = "100%";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
}
// Projection
var projection = d3.geoAlbersUsa()
.translate([ 0,0 ]);
var path = d3.geoPath( projection );
// .projection( projection );
// Create SVG
var svg = d3.select("#chart")
.append("svg")
.attr("width", chart_width)
.attr("height", chart_height);
var zoom_map = d3.zoom()
.scaleExtent([ 0.5, 3.0 ])
.translateExtent([
[ -1000, -500 ],
[ 1000, 500 ]
])
.on( 'zoom', function(){
// console.log( d3.event );
var offset = [
d3.event.transform.x,
d3.event.transform.y
];
var scale = d3.event.transform.k * 2000;
projection.translate( offset )
.scale( scale );
svg.selectAll( 'path' )
.transition()
.attr( 'd', path );
svg.selectAll( 'circle' )
.transition()
.attr( "cx", function(d) {
return projection([d.lon, d.lat])[0];
})
.attr( "cy", function(d) {
return projection([d.lon, d.lat])[1];
});
});
var map = svg.append( 'g' )
.attr( 'id', 'map' )
.call( zoom_map )
.call(
zoom_map.transform,
d3.zoomIdentity
.translate( chart_width / 2, chart_height / 2 )
.scale( 1 )
);
map.append( 'rect' )
.attr( 'x', 0 )
.attr( 'y', 0 )
.attr( 'width', chart_width )
.attr( 'height', chart_height )
.attr( 'opacity', 0 );
// Data
d3.json( 'data/USDepartmentofAgriculture-HoneyProduction-2013_properties.json', function( honey_data ){
color.domain([
d3.min( honey_data, function(d){
return d.honey_producing_colonies;
}),
d3.max( honey_data, function(d){
return d.honey_producing_colonies;
})
]);
d3.json( 'data/us.json', function( us_data ){
us_data.features.forEach(function(us_e, us_i){
honey_data.forEach(function(h_e,h_i){
if( us_e.properties.name !== h_e.state ){
return null;
}
us_data.features[us_i].properties.average_price_per_pound = parseFloat(h_e.average_price_per_pound);
});
});
// console.log(us_data);
map.selectAll( 'path' )
.data( us_data.features )
.enter()
.append( 'path' )
.attr( 'd', path )
.attr( 'fill', function( d ){
var average_price_per_pound = d.properties.average_price_per_pound;
return average_price_per_pound ? color( average_price_per_pound ) : '#525252';
})
.attr( 'stroke', '#fff' )
.attr( 'stroke-width', 1 );
// draw_cities();
});
});
// function draw_cities(){
// d3.json( 'data/us-cities.json', function( city_data ){
// map.selectAll("circle")
// .data(city_data)
// .enter()
// .append( "circle" )
// .style( "fill", "#9D497A" )
// .style( "opacity", 0.8 )
// .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 Math.sqrt( parseInt(d.population) * 0.00005 );
// })
// .append( 'title' )
// .text(function(d){
// return d.city;
// });
// });
// }
d3.selectAll( '#buttons button.panning' ).on( 'click', function(){
var x = 0;
var y = 0;
var distance = 100;
var direction = d3.select( this ).attr( 'class' ).replace( 'panning ', '' );
if( direction === "up" ){
y += distance; // Increase y offset
}else if( direction === "down" ){
y -= distance; // Decrease y offset
}else if( direction === "left" ){
x += distance; // Increase x offset
}else if( direction === "right" ){
x -= distance; // Decrease x offset
}
map.transition()
.call( zoom_map.translateBy, x, y );
});
d3.selectAll( '#buttons button.zooming' ).on( 'click', function(){
var scale = 1;
var direction = d3.select(this).attr("class").replace( 'zooming ', '' );
if( direction === "in" ){
scale = 1.25;
}else if(direction === "out"){
scale = 0.75;
}
map.transition()
.call(zoom_map.scaleBy, scale);
});
style.css
#intro {
position: absolute;
top: 250px;
left: 125px;
width: 180px;
text-align: left;
color: #B5B5B5;
}
#intro h2{
font-family: Oswald;
font-size: 25px;
font-weight: 300;
text-align: center;
color: white;
-webkit-margin-before: 0.5em;
-webkit-margin-after: 0.3em;
}
#legenda {
position: absolute;
top: 250px;
right: 125px;
width: 180px;
text-align: left;
color: #B5B5B5;
}
#legenda h4{
font-family: Oswald;
font-size: 20px;
font-weight: 300;
text-align: center;
color: white;
-webkit-margin-before: 0.5em;
-webkit-margin-after: 0.3em;
}
body {
font-size: 11px;
font-weight: 400;
font-family: 'Open Sans', sans-serif;
text-align: center;
vertical-align: middle;
background: #111;
fill: white;
color: white;
cursor:default;
}
.navbar-brand {
height: 60px;
padding: 5px 0px;
}
#chart{
width: 800px;
height: 600px;
background-color: #111;
margin: 25px auto;
}
#buttons{
width: 800px;
margin: 25px auto;
text-align: center;
}
button{
background-color: white;
color: black;
width: 100px;
padding: 10px;
font-size: 20px;
text-align: center;
border: 0;
outline: 0;
transition: all .2s linear;
cursor: pointer;
}
button:hover{
background-color: #50B98C;
}
#note {
top: -10px;
left: 10px;
font-size: 12px;
font-weight: 300;
color: #6E6E6E;
text-align: center;
}
a {
color: #6E6E6E;
}
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: black;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
text-align:center;
}
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s;
}
.sidenav a:hover{
color: #f1f1f1;
}
.sidenav .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
@media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
.sidenav a {font-size: 18px;}
}