D3.js: Change imported file through a slider

Asked

Viewed 38 times

1

I’m creating a slider for a view, a choropleth map on D3.js.

To do this, I added it to the app.js file:

function update(year){
     slider.property("value", year);
     d3.select(".year").text(year);
     // us_data.style("fill", function(d) {
     //     return color(d.properties.years[year][0].rate)
     // });
}


var slider = d3.select(".slider")
    .append("input")
    .attr("type", "range")
    .attr("min", 2009)
    .attr("max", 2013)
    .attr("step", 1)
    .on("input", function() {
         var year = this.value;
         update(year);
     });

update(2013);

As I intend the selected year in the slider to assign a number (one year in this case), which is passed to a string with the file path containing that year, I added a id at the h2 (what changes when I move the slider) in index.html:

<h2 id="vardatayear" class="year"></h2>
        <div class="slider"></div>

Considering that "vardatayear" will influence the file I want to import, I created a variable, in the app.js, that will fetch the value of the slider and, in case it does not return a value, has 2013 as default:

var honeyyear = document.getElementById("vardatayear").value || 2013;

The import of the file is done through the following:

d3.json( `data/HoneyProduction-${honeyyear}.json`, function( honey_data ){...

I am, however, having a problem: by changing the year in the slider, the map always stays the same, which indicates that the year change in the slider is not affecting the file being imported (always the same, the file associated with the year 2013).

I appreciate any help.

Btw, the inspiration for the slider I’m creating is on this side.


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://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
    <nav class="navbar navbar-default">
        <div class="container">
            <a class="navbar-brand" href="#"><img id="logo" src="img/logo.png"></a>
            <br>
            <div id="mySidenav" class="sidenav">
                <a href="javascript:void(0)" class="closebtn" onclick="closeNav()">&times;</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>
        </div>
        <span style="font-size:30px;cursor:pointer" onclick="openNav()">&#9776;</span>
        <br>
        <br>
    </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>
    <br>
    <div id="content">
        <h1>U.S. Department of Agriculture - Honey Production, 2009-2013</h1>
        <h2 id="vardatayear" class="year"></h2>
        <div class="slider"></div>
        <div id="map"></div>
    </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 class="website" href="http://goncaloperes.com/" target="_blank">GoncaloPeres.com</a></b></span><br>
        <span>Data from: <a class="website" 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>

app js.

// Width and height
var chart_width     =   800;
var chart_height    =   600;
var color           =   d3.scaleQuantize().range([
    "#f7fbff","#f6faff","#f5fafe","#f5f9fe",
    "#f4f9fe","#f3f8fe","#f2f8fd","#f2f7fd",
    "#f1f7fd","#f0f6fd","#eff6fc","#eef5fc",
    "#eef5fc","#edf4fc","#ecf4fb","#ebf3fb",
    "#eaf3fb","#eaf2fb","#e9f2fa","#e8f1fa",
    "#e7f1fa","#e7f0fa","#e6f0f9","#e5eff9",
    "#e4eff9","#e3eef9","#e3eef8","#e2edf8",
    "#e1edf8","#e0ecf8","#e0ecf7","#dfebf7",
    "#deebf7","#ddeaf7","#ddeaf6","#dce9f6",
    "#dbe9f6","#dae8f6","#d9e8f5","#d9e7f5",
    "#d8e7f5","#d7e6f5","#d6e6f4","#d6e5f4",
    "#d5e5f4","#d4e4f4","#d3e4f3","#d2e3f3",
    "#d2e3f3","#d1e2f3","#d0e2f2","#cfe1f2",
    "#cee1f2","#cde0f1","#cce0f1","#ccdff1",
    "#cbdff1","#cadef0","#c9def0","#c8ddf0",
    "#c7ddef","#c6dcef","#c5dcef","#c4dbee",
    "#c3dbee","#c2daee","#c1daed","#c0d9ed",
    "#bfd9ec","#bed8ec","#bdd8ec","#bcd7eb",
    "#bbd7eb","#b9d6eb","#b8d5ea","#b7d5ea",
    "#b6d4e9","#b5d4e9","#b4d3e9","#b2d3e8",
    "#b1d2e8","#b0d1e7","#afd1e7","#add0e7",
    "#acd0e6","#abcfe6","#a9cfe5","#a8cee5",
    "#a7cde5","#a5cde4","#a4cce4","#a3cbe3",
    "#a1cbe3","#a0cae3","#9ec9e2","#9dc9e2",
    "#9cc8e1","#9ac7e1","#99c6e1","#97c6e0",
    "#96c5e0","#94c4df","#93c3df","#91c3df",
    "#90c2de","#8ec1de","#8dc0de","#8bc0dd",
    "#8abfdd","#88bedc","#87bddc","#85bcdc",
    "#84bbdb","#82bbdb","#81badb","#7fb9da",
    "#7eb8da","#7cb7d9","#7bb6d9","#79b5d9",
    "#78b5d8","#76b4d8","#75b3d7","#73b2d7",
    "#72b1d7","#70b0d6","#6fafd6","#6daed5",
    "#6caed5","#6badd5","#69acd4","#68abd4",
    "#66aad3","#65a9d3","#63a8d2","#62a7d2",
    "#61a7d1","#5fa6d1","#5ea5d0","#5da4d0",
    "#5ba3d0","#5aa2cf","#59a1cf","#57a0ce",
    "#569fce","#559ecd","#549ecd","#529dcc",
    "#519ccc","#509bcb","#4f9acb","#4d99ca",
    "#4c98ca","#4b97c9","#4a96c9","#4895c8",
    "#4794c8","#4693c7","#4592c7","#4492c6",
    "#4391c6","#4190c5","#408fc4","#3f8ec4",
    "#3e8dc3","#3d8cc3","#3c8bc2","#3b8ac2",
    "#3a89c1","#3988c1","#3787c0","#3686c0",
    "#3585bf","#3484bf","#3383be","#3282bd",
    "#3181bd","#3080bc","#2f7fbc","#2e7ebb",
    "#2d7dbb","#2c7cba","#2b7bb9","#2a7ab9",
    "#2979b8","#2878b8","#2777b7","#2676b6",
    "#2574b6","#2473b5","#2372b4","#2371b4",
    "#2270b3","#216fb3","#206eb2","#1f6db1",
    "#1e6cb0","#1d6bb0","#1c6aaf","#1c69ae",
    "#1b68ae","#1a67ad","#1966ac","#1865ab",
    "#1864aa","#1763aa","#1662a9","#1561a8",
    "#1560a7","#145fa6","#135ea5","#135da4",
    "#125ca4","#115ba3","#115aa2","#1059a1",
    "#1058a0","#0f579f","#0e569e","#0e559d",
    "#0e549c","#0d539a","#0d5299","#0c5198",
    "#0c5097","#0b4f96","#0b4e95","#0b4d93",
    "#0b4c92","#0a4b91","#0a4a90","#0a498e",
    "#0a488d","#09478c","#09468a","#094589",
    "#094487","#094386","#094285","#094183",
    "#084082","#083e80","#083d7f","#083c7d",
    "#083b7c","#083a7a","#083979","#083877",
    "#083776","#083674","#083573","#083471",
    "#083370","#08326e","#08316d","#08306b"
]);


//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.longitude, d.latitude])[0];
        })
        .attr( "cy", function(d) {
            return projection([d.longitude, d.latitude])[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
var honeyyear = document.getElementById("vardatayear").value || 2013;

// if(!honeyyear){
//     honeyyear  = 2013
// }

// Select what are we analyzing
// var honeyattribute = document.getElementById('some_input_id').value;

d3.json( `data/HoneyProduction-${honeyyear}.json`, function( honey_data ){

    color.domain([
        d3.min( honey_data, function(d){
            return d.average_price_per_pound;
        }),
        d3.max( honey_data, function(d){
            return d.average_price_per_pound;
        })
    ]);

    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 )
            .append('title')
            // .text(d => console.log(d))
            .text(d => d.properties.average_price_per_pound);

        // draw_cities();

    });
});

function draw_cities(){
    d3.json( 'data/us-city.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.longitude, d.latitude ])[0];
            })
            .attr( 'cy', function( d ){
                return projection([ d.longitude, d.latitude ])[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);
});



// Slider
function update(year){
     slider.property("value", year);
     d3.select(".year").text(year);
     // us_data.style("fill", function(d) {
     //     return color(d.properties.years[year][0].rate)
     // });
}


var slider = d3.select(".slider")
    .append("input")
    .attr("type", "range")
    .attr("min", 2009)
    .attr("max", 2013)
    .attr("step", 1)
    .on("input", function() {
         var year = this.value;
         update(year);
     });

update(2013);

css style.

#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: midnightblue;
}

#note {
    top: -10px;
    left: 10px;
    font-size: 12px;
    font-weight: 300;
    color: #6E6E6E;
    text-align: center;
}

.website {
    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;}
}

1 answer

1


Solved using Async/Await

const slider = d3.select('.slider')
  .append('input')
  .attr('type', 'range')
  .attr('min', 2009)
  .attr('max', 2013)
  .attr('step', 1)
  .on('input', function () {
    const value = this.value
    updateYear(this.value)

  });

const updateYear = async year => {
  slider.attr('value', year);
  d3.select('.year').text(year);

  const honey_data = await d3.json(`data/HoneyProduction-${year}.json`)
  color.domain([
    d3.min(honey_data, d => d.average_price_per_pound),
    d3.max(honey_data, d => d.average_price_per_pound)
  ]);

  const us_data = await d3.json('data/us.json')
  us_data.features.forEach((us_e, us_i) => {
    honey_data.forEach((h_e, h_i) => {
      if (us_e.properties.name !== h_e.state) {
        return null;
      }
}

updateYear(2013)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.