Hitogram colors added thanks to @IagoLast. UPDATE: this is not working as expected, I recommend using this other approach.
Last active
January 4, 2018 08:41
-
-
Save ramiroaznar/e2e263c00e791e4057062be26d46a018 to your computer and use it in GitHub Desktop.
Histogram widget as legend with CARTO.js v4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Histogram widget as legend with CARTO.js v4</title> | |
| <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> | |
| <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
| <link rel="shortcut icon" href="https://cartodb.com/assets/favicon.ico" /> | |
| <link href="https://fonts.googleapis.com/css?family=Montserrat:400,600,700|Open+Sans:300,400,600" rel="stylesheet"> | |
| <!-- leaflet + jquery --> | |
| <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" /> | |
| <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script> | |
| <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> | |
| <!-- chartjs --> | |
| <script src="http://www.chartjs.org/dist/2.7.1/Chart.bundle.js"></script> | |
| <script src="http://www.chartjs.org/samples/latest/utils.js"></script> | |
| <!-- carto.js --> | |
| <script src="https://cartodb-libs.global.ssl.fastly.net/carto.js/v4.0.0-beta.10/carto.min.js"></script> | |
| <style> | |
| * { | |
| box-sizing: border-box; | |
| } | |
| body, | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| } | |
| #map { | |
| position: absolute; | |
| height: 100%; | |
| width: 100%; | |
| z-index: 0; | |
| } | |
| #histogram { | |
| position: absolute; | |
| bottom: 12px; | |
| left: 12px; | |
| height: auto; | |
| width: auto; | |
| padding: 20px 24px; | |
| background: white; | |
| box-shadow: 0 0 16px rgba(0, 0, 0, 0.12); | |
| border-radius: 4px; | |
| opacity: 0.8; | |
| z-index: 1; | |
| width: 450px; | |
| } | |
| #histogram>h1 { | |
| font: 800 12px/16px 'Montserrat'; | |
| text-transform: uppercase; | |
| color: #2D3C43; | |
| margin-bottom: 12px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- map div --> | |
| <div id="map"></div> | |
| <!-- histogram div --> | |
| <div id="histogram"> | |
| <h1>Airbnb price distribution in Madrid</h1> | |
| <canvas id="chart" width="400" height="400"></canvas> | |
| </div> | |
| <script type="text/cartocss" id="style"> | |
| #layer { | |
| marker-width: 5; | |
| marker-fill: ramp([price], cartocolor(Sunset), equal(10)); | |
| marker-fill-opacity: 0.7; | |
| marker-allow-overlap: true; | |
| marker-line-width: 0; | |
| marker-comp-op: multiply; | |
| } | |
| </script> | |
| <script type="text/sql" id="query"> | |
| SELECT | |
| * | |
| FROM | |
| listings | |
| WHERE | |
| price < 150 | |
| </script> | |
| <script> | |
| function main() { | |
| // get styles & query | |
| const style = $("#style").text(), | |
| query = $("#query").text(), | |
| // add map variable | |
| map = L.map('map', { | |
| zoomControl: false, | |
| center: [40.43, -3.7], | |
| zoom: 13 | |
| }); | |
| // add Voyager Basemap | |
| L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', { | |
| maxZoom: 18, | |
| attribution: '©<a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, ©<a href="https://carto.com/attribution">CARTO</a>' | |
| }).addTo(map); | |
| // Adding Voyager Labels | |
| L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_only_labels/{z}/{x}/{y}.png', { | |
| maxZoom: 18, | |
| attribution: '©<a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, ©<a href="https://carto.com/attribution">CARTO</a>', | |
| zIndex: 100 | |
| }).addTo(map); | |
| // add client | |
| const client = new carto.Client({ | |
| apiKey: 'API_KEY', | |
| username: 'ramirocartodb' | |
| }); | |
| // add CARTO layer | |
| const airbnbDataset = new carto.source.SQL(query), | |
| airbnbStyle = new carto.style.CartoCSS(style), | |
| airbnbLayer = new carto.layer.Layer(airbnbDataset, airbnbStyle); | |
| // Listen for metadata changes | |
| airbnbLayer.on('metadataChanged', metadata => { | |
| histogram.setMetadata(metadata); | |
| histogram.render(); | |
| }); | |
| client.addLayer(airbnbLayer); | |
| client.getLeafletLayer().addTo(map); | |
| // get histogram dataview | |
| const histogramDataview = new carto.dataview.Histogram(airbnbDataset, 'price', { bins: 7 }); | |
| // Create an histogram widget | |
| const histogram = new HistogramWidget(); | |
| // When the data is changed render the histogram | |
| histogramDataview.on('dataChanged', data => { | |
| histogram.render(data); | |
| }); | |
| client.addDataview(histogramDataview); | |
| const bboxFilter = new carto.filter.BoundingBoxLeaflet(map); | |
| histogramDataview.addFilter(bboxFilter); | |
| } | |
| // create HistogramWidget function | |
| function HistogramWidget() { | |
| this.metadata = { colors: ['red'] } | |
| this.element = document.getElementById("chart").getContext("2d"); | |
| this.options = { | |
| legend: { | |
| display: false, | |
| }, | |
| title: { | |
| display: true, | |
| text: 'Average price ($)', | |
| position: 'bottom', | |
| }, | |
| scales: { | |
| yAxes: [{ | |
| barPercentage: 0.2, | |
| gridLines: { | |
| display: false, | |
| } | |
| }], | |
| xAxes: [{ | |
| barPercentage: 1, | |
| gridLines: { | |
| display: false, | |
| } | |
| }] | |
| }, | |
| elements: { | |
| rectangle: { | |
| borderSkipped: 'left', | |
| } | |
| } | |
| }; | |
| } | |
| // get colors | |
| HistogramWidget.prototype.setMetadata = function (metadata) { | |
| this.metadata.colors = metadata.styles[0]._buckets.map(element => element.value); | |
| } | |
| // render data | |
| HistogramWidget.prototype.render = function (data) { | |
| if (!data) { | |
| return this._lastData && this.render(this._lastData); | |
| } | |
| this._lastData = data; | |
| const bins = data.bins; | |
| const labels = data.bins.map(bin => Math.round(bin.avg)); | |
| const frequencies = data.bins.map(bin => bin.freq); | |
| new Chart(this.element, { | |
| type: 'bar', | |
| data: { | |
| labels: labels, | |
| datasets: [{ | |
| label: 'Total', | |
| data: frequencies, | |
| backgroundColor: this.metadata.colors, | |
| borderWidth: 0 | |
| }] | |
| }, | |
| options: this.options, | |
| }); | |
| } | |
| window.onload = main; | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment