CartoDB multiple layer toggle

2019-08-04 01:15发布

问题:

I'm trying to make one map where you can toggle between three different layers, and keep the same legend visible for all. I'm currently following this documentation: http://docs.cartodb.com/tutorials/toggle_map_view.html

My map in CartoDB has three separate layers (w/ three datasets for the years 2013, 2014 and 2015).

I'm trying to make a toggle map like the one in the documentation. Here's what I go so far:

<html>
<head>
  <link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/3.11/themes/css/cartodb.css" />
  <script src="http://libs.cartocdn.com/cartodb.js/v3/3.11/cartodb.js"></script>
  <style>
    html, body {width:100%; height:100%; padding: 0; margin: 0;}
    #map { width: 100%; height:100%; background: black;}
    #menu { position: absolute; top: 5px; right: 10px; width: 400px; height:60px; background: transparent; z-index:10;}
    #menu a { 
      margin: 15px 10px 0 0;
      float: right;
      vertical-align: baseline;
      width: 70px;
      padding: 10px;
      text-align: center;
      font: bold 11px "Helvetica",Arial;
      line-height: normal;
      color: #555;
      border-radius: 4px;
      border: 1px solid #777777;
      background: #ffffff;
      text-decoration: none;
      cursor: pointer;
    }
    #menu a.selected,
    #menu a:hover { 
      color: #F84F40;
    }
  </style>

  <script>
var map;
    function init(){
  // initiate leaflet map
  map = new L.Map('map', { 
    center: [20,-20],
    zoom: 3
  })

  L.tileLayer('https://dnv9my2eseobd.cloudfront.net/v3/cartodb.map-4xtxp73f/{z}/{x}/{y}.png', {
    attribution: 'Mapbox <a href="http://mapbox.com/about/maps" target="_blank">Terms &amp; Feedback</a>'
  }).addTo(map);

  var layerUrl = 'http://heathermartino.cartodb.com/api/v2/viz/415f8ed2-d493-11e4-b129-0e018d66dc29/viz.json';

  var sublayers = [];

  cartodb.createLayer(map, layerUrl)
  .addTo(map)
  .on('done', function(layer) {
    // change the query for the first layer
    var subLayerOptions = {
      sql: "SELECT * FROM gdp_2014",
      cartocss: "#gdp_2014{marker-fill: #F84F40; marker-width: 8; marker-line-color: white; marker-line-width: 2; marker-clip: false; marker-gdp_2015ow-overlap: true;}"
    }

    var sublayer = layer.getSubLayer(0);

    sublayer.set(subLayerOptions);

    sublayers.push(sublayer);
  }).on('error', function() {
    //log the error
  });

  //we define the queries that will be performed when we click on the buttons, by modifying the SQL of our layer
  var LayerActions = {
    GDP_2015: function(){
      sublayers[0].setSQL("SELECT * FROM gdp_2015");
      return true;
    },
    GDP_2014: function(){
      sublayers[0].setSQL("SELECT * FROM gdp_2014");
      return true;
    },
    GDP_2013: function() {
      sublayers[0].set({
        sql: "SELECT * FROM gdp_2013 WHERE cartodb_georef_status = true",
        //as it is said, you can also add some CartoCSS code to make your points look like you want for the different queries
       // cartocss: "#ne_10m_populated_places_simple{ marker-fill: black; }"
      });
      return true;
    }
  }

  $('.button').click(function() {
    $('.button').removeClass('selected');
    $(this).addClass('selected');
    //this gets the id of the different buttons and cgdp_2015s to LayerActions which responds according to the selected id
    LayerActions[$(this).attr('id')]();
  });


    L.tileLayer('https://dnv9my2eseobd.cloudfront.net/v3/cartodb.map-4xtxp73f/{z}/{x}/{y}.png', {
      attribution: 'Mapbox <a href="http://mapbox.com/about/maps" target="_blank">Terms &amp; Feedback</a>'
    }).addTo(map);
  }
  </script>
</head>

<body onload="init()">
  <div id='map'></div>
  <div id='menu'>
    <a href="#gdp_2013" id="gdp_2013" class="button gdp_2013">2013</a> 
    <a href="#gdp_2014" id="gdp_2014" class="button gdp_2014">2014</a> 
    <a href="#gdp_2015" id="gdp_2015" class="button gdp_2015">2015</a>
  </div>
</body>
</html>

Right now when you click on the different buttons for 2013, 2014 and 2015, nothing happens. For reference, my map in carto is http://cdb.io/1Bzm2tD. Any ideas? Thanks in advance!

回答1:

You have the layers. No need to run SQL again. This should work.

<html>

<head>
    <link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/3.11/themes/css/cartodb.css" />
    <script src="http://libs.cartocdn.com/cartodb.js/v3/3.11/cartodb.js"></script>
    <style>
    html,
    body {
        width: 100%;
        height: 100%;
        padding: 0;
        margin: 0;
    }

    #map {
        width: 100%;
        height: 100%;
        background: black;
    }

    #menu {
        position: absolute;
        top: 5px;
        right: 10px;
        width: 400px;
        height: 60px;
        background: transparent;
        z-index: 10;
    }

    #menu a {
        margin: 15px 10px 0 0;
        float: right;
        vertical-align: baseline;
        width: 70px;
        padding: 10px;
        text-align: center;
        font: bold 11px "Helvetica", Arial;
        line-height: normal;
        color: #555;
        border-radius: 4px;
        border: 1px solid #777777;
        background: #ffffff;
        text-decoration: none;
        cursor: pointer;
    }

    #menu a.selected,
    #menu a:hover {
        color: #F84F40;
    }

    .cartodb-layer-selector-box,
    .cartodb-searchbox,
    .cartodb-share {
        display: none !important;
    }
    </style>
    <script>
    var layer;


    function init() {
        var url = 'http://heathermartino.cartodb.com/api/v2/viz/415f8ed2-d493-11e4-b129-0e018d66dc29/viz.json';
        var visualizacion = cartodb.createVis("map", url)
            .done(function(vis, layers) {
                layer = layers[1];
            });
    }

    function showLayer(layerToShow) {

        //turn off all layers
        layer.getSubLayers().forEach(function(i) {
            i.hide()
        });

        switch (layerToShow.id) {
            case "gdp_2013":
                layer.getSubLayer(0).show();
                break;
            case "gdp_2014":
                layer.getSubLayer(1).show();
                break;
            case "gdp_2015":
                layer.getSubLayer(2).show();
                break;
        }

        return true;
    }
    </script>
</head>

<body onload="init()">
    <div id='map'></div>
    <div id='menu'>
        <a href="#gdp_2013" id="gdp_2013" class="button gdp_2013" onclick="showLayer(this);">2013</a>
        <a href="#gdp_2014" id="gdp_2014" class="button gdp_2014" onclick="showLayer(this);">2014</a>
        <a href="#gdp_2015" id="gdp_2015" class="button gdp_2015" onclick="showLayer(this)">2015</a>
    </div>
</body>

</html>


回答2:

I have created something similar - see if this helps. The trick for me was getting the sublayers separated with a for loop, then creating the buttons to act on each.

 function loadPosition(position) {

                lati = position.coords.latitude;
                longi = position.coords.longitude;
                map = L.map('map', {zoomControl: false}).setView([lati, longi], 15);

                L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {maxZoom: 19,}).addTo(map);

                L.control.scale({position: 'bottomright'}).addTo(map);


                /*CARTODB LAYERS*/
                var layerSource = {
                    user_name: 'YOUR USER NAME',
                    type: 'cartodb',
                    cartodb_logo: false,
                    sublayers: [{
                        sql: "SELECT * FROM winston_survey_tool WHERE point_class LIKE 'Orientation point'",
                        cartocss: '#winston_survey_tool{marker-fill:#D94C38;marker-opacity:1;line-color:#FFF;line-width:1;line-opacity:1;marker-allow-overlap:true; [zoom >= 15] {marker-width: 15} [zoom >= 19] {marker-width: 20}}'
                        },
                        {
                        sql: "SELECT * FROM winston_survey_tool WHERE point_class LIKE 'Survey point'",
                        cartocss: '#winston_survey_tool{marker-fill:#E0D03D;marker-opacity:1;line-color:#FFF;line-width:1;line-opacity:1;marker-allow-overlap:true;  [zoom >= 15] {marker-width: 15} [zoom >= 19] {marker-width: 20}}'
                        }]
                    };

                // STORE SUBLAYERS
                var sublayers = [];


            // ADD LAYER TO MAP
            cartodb.createLayer(map,layerSource)
            .addTo(map)
            .done(function(layer) {

                // SEPARATE THE SUBLAYERS
                for (i = 0; i < layer.getSubLayerCount(); i++) {
                    sublayers[i] = layer.getSubLayer(i);
                    sublayers[i].hide();
                };


                // BUTTONS
                $('#orientationCheck').click(function () {

                    orientationValue = $("#orientationCheck").val();

                    var query = "SELECT * FROM winston_survey_tool WHERE date LIKE'%";    
                    yearSelectVal = $("#yearSelect").val();

                    query = query + yearSelectVal + "' AND point_class LIKE 'Orientation point'";

                    sublayers[0] = sublayers[0].setSQL(query);

                    if(orientationValue=="ON"){
                        sublayers[0].hide();
                        $('#orientationCheck').val("OFF");
                        $("#orientationCheck").addClass("off");
                        }
                    else{
                        sublayers[0].show();
                        $('#orientationCheck').val("ON");
                        $("#orientationCheck").removeClass("off");
                        };
                    });



                $('#surveyCheck').click(function () {

                    surveyValue = $("#surveyCheck").val();

                    var query = "SELECT * FROM winston_survey_tool WHERE date LIKE'%";    
                    yearSelectVal = $("#yearSelect").val();

                    query = query + yearSelectVal + "' AND point_class LIKE 'Survey point'";

                    sublayers[1] = sublayers[1].setSQL(query);

                    if(surveyValue=="ON"){
                        sublayers[1].hide();
                        $('#surveyCheck').val("OFF");
                        $("#surveyCheck").addClass("off");
                        }
                    else{
                        sublayers[1].show();
                        $('#surveyCheck').val("ON");
                        $("#surveyCheck").removeClass("off");
                        };           
                    });
                });