CartoDB / airship

A design library for building Location Intelligence applications.
https://carto.com/developers/airship/
BSD 3-Clause "New" or "Revised" License
75 stars 14 forks source link

Bridge setup does not work for feature-dependent expression values #654

Open elenatorro opened 5 years ago

elenatorro commented 5 years ago

What is happening?

When adding a Legend through the Bridge, Airship creates a baseStyle object with default values for each style property from the viz. This is not 100% accurate, cause it's getting a single value for each property. When the property is an expression that depends on a feature, this doesn't work.

https://github.com/CartoDB/airship/blob/1b52c881f758828baaa23f8faa39d5544d47dfdc/packages/bridge/src/vl/legends/index.ts#L28-L40

What should happen?

From my perspective, the best solution is to use the getLegendData for each style property. This will imply some changes in the widget data, but it's the correct way to proceed.

Steps to Reproduce

Use this html example:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <title>DEMO</title>

    <script src="https://libs.cartocdn.com/airship-components/v2.1.1/airship.js"></script>
    <script src="https://libs.cartocdn.com/airship-bridge/v2.1.1/asbridge.js"></script>
    <script src="http://libs.cartocdn.com/carto-vl/v1.4.1/carto-vl.js"></script>
    <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.0.0/mapbox-gl.js"></script>

    <link rel="stylesheet" href="https://libs.cartocdn.com/airship-style/v2.1.1/airship.css">
    <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.0.0/mapbox-gl.css" rel="stylesheet" />

    <style>
      html, body {
        margin: 0;
      }
      #map {
        position: absolute;
        width: 100%;
        height: 100%;
      }
      .as-panel {
        flex-direction: column;
      }

      as-legend {
        width: 100%;
      }

      #widget {
        font-size: 2em;
        margin-top: 20px;
      }
    </style>
  </head>

  <body class="as-app-body as-app">
    <div class="as-content">
      <main class="as-main">
        <div class="as-map-area">
          <div id="map"></div>
          <div class="as-map-panels">
            <div class="as-panel as-panel--top as-panel--left" id="legends">
              <as-legend
                id="spend-data-legend"
                heading="Spend Data"
                description="Color intensity defined by Spend Data">
                <as-legend-color-continuous-polygon id="spend-data" slot="legends" />
              </as-legend>
            </div>
          </div>
        </div>
      </main>
      <aside class="as-sidebar as-sidebar--right">
        <section class="as-box">
          <as-widget-header>
            <h2 class="as-widget-header__header">Spend Data</h2>
          </as-widget-header>
          <p class="as-body" id="widget"></p>
        </section>

        <section class="as-box">
          <as-histogram-widget
            show-clear
            id="histogramWidget"
            heading="spend-data"
          >
          </as-histogram-widget>
        </section>

        <section class="as-box">
          <as-category-widget
            show-clear
            id="categoryWidget"
            heading="Type"
          ></as-category-widget>
        </section>
      </aside>
    </div>

    <script>
      const map = new mapboxgl.Map({
        container: 'map',
        style: carto.basemaps.darkmatter,
        center: [0, 40],
        zoom: 1
      });

      map.addControl(new mapboxgl.NavigationControl());

      carto.setDefaultAuth({
        username: 'cartovl',
        apiKey: 'default_public'
      });

      const source = new carto.source.SQL(`
        SELECT * FROM spend_data
      `);

      const viz = new carto.Viz(`
        color: opacity(ramp(clusterAVG($amount), sunset),0.9)
        width: clusterCount()
      `);

      const layer = new carto.Layer('spend_data', source, viz);

      layer.addTo(map, 'watername_ocean');

      AsBridge.VL.Legends.rampLegend('#spend-data',
        layer,
        'color'
      );
    </script>
  </body>
</html>
alonsogarciapablo commented 5 years ago

Thank you @elenatorro!