From 8e42a322216b157c0a9136eaa71138b920fbaf90 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Thu, 6 Nov 2014 17:08:57 -0700 Subject: [PATCH 1/3] Fit points to map, remove satellite view, make borders thinner --- .../components/vislib/styles/_tilemap.less | 7 +++ .../vislib/visualizations/tile_map.js | 58 ++++++++++++------- 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/kibana/components/vislib/styles/_tilemap.less b/src/kibana/components/vislib/styles/_tilemap.less index 1b5f80ea29b687..7df1ccd4fdee58 100644 --- a/src/kibana/components/vislib/styles/_tilemap.less +++ b/src/kibana/components/vislib/styles/_tilemap.less @@ -55,6 +55,13 @@ color: #444; } +.leaflet-control-fit { + text-align: center; + background: #fff; + width: 26px; + height: 26px; + outline: 1px black; +} /* over-rides leaflet popup styles to look like kibana tooltip */ diff --git a/src/kibana/components/vislib/visualizations/tile_map.js b/src/kibana/components/vislib/visualizations/tile_map.js index 668b52f6138dc4..d333856c58abb0 100644 --- a/src/kibana/components/vislib/visualizations/tile_map.js +++ b/src/kibana/components/vislib/visualizations/tile_map.js @@ -5,16 +5,15 @@ define(function (require) { var L = require('leaflet'); require('heat'); require('markercluster'); - + var Chart = Private(require('components/vislib/visualizations/_chart')); var errors = require('errors'); require('css!components/vislib/styles/main'); - + var mapData; var mapCenter = [15, 5]; var mapZoom = 2; - /** * Tile Map Visualization: renders maps @@ -32,7 +31,7 @@ define(function (require) { return new TileMap(handler, chartEl, chartData); } TileMap.Super.apply(this, arguments); - + // add allmin and allmax to geoJSON var mapDataExtents = handler.data.mapDataExtents(handler.data.data.raw); chartData.geoJSON.properties.allmin = mapDataExtents[0]; @@ -87,19 +86,37 @@ define(function (require) { subdomains: '1234' }); var worldBounds = L.latLngBounds([-200, -220], [200, 220]); - + var map = L.map(div[0], { layers: mapLayer, center: mapCenter, zoom: mapZoom, - maxBounds: worldBounds + maxBounds: worldBounds, + scrollWheelZoom: false, + fadeAnimation: false }); - // switch map types - L.control.layers({ - 'Map': mapLayer, - 'Satellite': satLayer - }).addTo(map); + function fitBounds() { + if (data.geoJSON) { + map.fitBounds(_.map(data.geoJSON.features, function (feature) { + return _.clone(feature.geometry.coordinates).reverse(); + })); + } + } + + // Add button to fit container to points + var fitControl = L.Control.extend({ + options: { + position: 'topleft' + }, + onAdd: function (map) { + var container = L.DomUtil.create('div', 'leaflet-control leaflet-bar leaflet-control-zoom leaflet-control-fit'); + $(container).html(''); + $(container).on('click', fitBounds); + return container; + } + }); + map.addControl(new fitControl()); map.on('zoomend dragend', function () { mapZoom = self._attr.lastZoom = map.getZoom(); @@ -117,6 +134,7 @@ define(function (require) { self.coloredCircleMarkers(map, data.geoJSON); } } + if (data.geoJSON.properties.label) { self.addLabel(data.geoJSON.properties.label, map); } @@ -257,7 +275,7 @@ define(function (require) { var featureLayer = L.geoJson(mapData, { pointToLayer: function (feature, latlng) { var count = feature.properties.count; - + var rad = zoomScale * self.radiusScale(count, max, precision); return L.circleMarker(latlng, { radius: rad @@ -271,7 +289,7 @@ define(function (require) { return { fillColor: defaultColor, color: self.darkerColor(defaultColor), - weight: 1.4, + weight: 0.5, opacity: 1, fillOpacity: 0.7 }; @@ -297,17 +315,17 @@ define(function (require) { */ TileMap.prototype.coloredCircleMarkers = function (map, mapData) { var self = this; - + // TODO: add UI to select local min max or super min max // min and max from chart data for just this map // var min = mapData.properties.min; // var max = mapData.properties.max; - + // super min and max from all chart data var min = mapData.properties.allmin; var max = mapData.properties.allmax; - + var length = mapData.properties.length; var precision = mapData.properties.precision; var zoomScale = self.zoomScale(mapZoom); @@ -361,10 +379,10 @@ define(function (require) { TileMap.prototype.resizeFeatures = function (map, min, max, precision, featureLayer) { var self = this; var zoomScale = self.zoomScale(mapZoom); - + featureLayer.eachLayer(function (layer) { var latlng = L.latLng(layer.feature.geometry.coordinates[1], layer.feature.geometry.coordinates[0]); - + var count = layer.feature.properties.count; var rad; if (self._attr.mapType === 'Colored Circle Markers') { @@ -419,7 +437,7 @@ define(function (require) { /** * radiusScale returns a circle radius from - * approx. square root of count + * approx. square root of count * which is multiplied by a factor based on the geohash precision * for relative sizing of markers * @@ -460,7 +478,7 @@ define(function (require) { }; /** - * returns a number to scale circle markers + * returns a number to scale circle markers * based on the geohash precision * * @method quantRadiusScale From c67d847328b27b4bb0927a3e323c4894fb86734f Mon Sep 17 00:00:00 2001 From: Spencer Alger Date: Thu, 6 Nov 2014 16:38:53 -0700 Subject: [PATCH 2/3] [vislib/vis] [vislib/handler] propogate resize and destroy down to the handler if possible --- .../components/vislib/lib/handler/handler.js | 8 ++++ src/kibana/components/vislib/vis.js | 39 ++++++++++++------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/kibana/components/vislib/lib/handler/handler.js b/src/kibana/components/vislib/lib/handler/handler.js index 1dbbe2f16fe360..7ff7236be53e4f 100644 --- a/src/kibana/components/vislib/lib/handler/handler.js +++ b/src/kibana/components/vislib/lib/handler/handler.js @@ -162,6 +162,14 @@ define(function (require) { .text(message); }; + Handler.prototype.destroy = function () { + this.charts.forEach(function (chart) { + if (_.isFunction(chart.destroy)) { + chart.destroy(); + } + }); + }; + return Handler; }; }); diff --git a/src/kibana/components/vislib/vis.js b/src/kibana/components/vislib/vis.js index 9ee07f9346180f..3a9ff8c134f746 100644 --- a/src/kibana/components/vislib/vis.js +++ b/src/kibana/components/vislib/vis.js @@ -52,19 +52,7 @@ define(function (require) { this.data = data; this.handler = handlerTypes[chartType](this) || handlerTypes.column(this); - - try { - this.handler.render(); - } catch (error) { - // If involving height and width of the container, log error to screen. - // Because we have to wait for the DOM element to initialize, we do not - // want to throw an error when the DOM `el` is zero - if (error instanceof errors.ContainerTooSmall) { - this.handler.error(error.message); - } else { - console.error(error.stack); - } - } + this._runOnHandler('render'); }; /** @@ -77,7 +65,27 @@ define(function (require) { // TODO: need to come up with a solution for resizing when no data is available return; } - this.render(this.data); + + if (_.isFunction(this.handler.resize)) { + this._runOnHandler('resize'); + } else { + this.render(this.data); + } + }; + + Vis.prototype._runOnHandler = function (method) { + try { + this.handler[method](); + } catch (error) { + // If involving height and width of the container, log error to screen. + // Because we have to wait for the DOM element to initialize, we do not + // want to throw an error when the DOM `el` is zero + if (error instanceof errors.ContainerTooSmall) { + this.handler.error(error.message); + } else { + console.error(error.stack); + } + } }; /** @@ -89,9 +97,10 @@ define(function (require) { * @method destroy */ Vis.prototype.destroy = function () { - d3.select(this.el).selectAll('*').remove(); this.resizeChecker.off('resize', this.resize); this.resizeChecker.destroy(); + this._runOnHandler('destroy'); + d3.select(this.el).selectAll('*').remove(); }; /** From 8500441688dd6ebe3d6ac12a9ed53735613e5fe6 Mon Sep 17 00:00:00 2001 From: Spencer Alger Date: Thu, 6 Nov 2014 16:50:53 -0700 Subject: [PATCH 3/3] [vislib/tilemap] implement custom resize and destroy handling --- .../vislib/lib/handler/types/tile_map.js | 6 +++ .../vislib/visualizations/tile_map.js | 37 ++++++++++++++++--- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/kibana/components/vislib/lib/handler/types/tile_map.js b/src/kibana/components/vislib/lib/handler/types/tile_map.js index d413838b4fe7ce..141e29031a1a41 100644 --- a/src/kibana/components/vislib/lib/handler/types/tile_map.js +++ b/src/kibana/components/vislib/lib/handler/types/tile_map.js @@ -12,6 +12,12 @@ define(function (require) { data: data }); + MapHandler.resize = function () { + this.charts.forEach(function (chart) { + chart.resizeArea(); + }); + }; + return MapHandler; }; }; diff --git a/src/kibana/components/vislib/visualizations/tile_map.js b/src/kibana/components/vislib/visualizations/tile_map.js index 57e9aed3485460..dde21a72c505e2 100644 --- a/src/kibana/components/vislib/visualizations/tile_map.js +++ b/src/kibana/components/vislib/visualizations/tile_map.js @@ -35,10 +35,6 @@ define(function (require) { var mapDataExtents = handler.data.mapDataExtents(handler.data.data.raw); chartData.geoJSON.properties.allmin = mapDataExtents[0]; chartData.geoJSON.properties.allmax = mapDataExtents[1]; - - // turn off resizeChecker for tile maps - this.handler.vis.resizeChecker.off('resize', this.resize); - this.handler.vis.resizeChecker.destroy(); } /** @@ -53,7 +49,12 @@ define(function (require) { var $elem = $(this.chartEl); var div; var worldBounds = L.latLngBounds([-200, -220], [200, 220]); - + + // clean up old maps + _.invoke(self.maps, 'destroy'); + // create a new maps array + self.maps = []; + return function (selection) { selection.each(function (data) { div = $(this); @@ -92,6 +93,7 @@ define(function (require) { }; var map = L.map(div[0], mapOptions); + self.maps.push(map); // switch map types L.control.layers({ @@ -143,7 +145,7 @@ define(function (require) { var featureLayer = L.geoJson(mapData, { pointToLayer: function (feature, latlng) { var count = feature.properties.count; - + var rad = zoomScale * self.radiusScale(count, max, precision); return L.circleMarker(latlng, { radius: rad @@ -285,6 +287,20 @@ define(function (require) { legend.addTo(map); }; + /** + * Invalidate the size of the map, so that leaflet will resize to fit. + * then moves to center + * + * @return {undefined} + */ + TileMap.prototype.resizeArea = function () { + this.maps.forEach(function (map) { + map.invalidateSize({ + debounceMoveend: true + }); + }); + }; + /** * Redraws feature layer markers * @@ -496,6 +512,15 @@ define(function (require) { return darker; }; + /** + * tell leaflet that it's time to cleanup the map + */ + TileMap.prototype.destroy = function () { + this.maps.forEach(function (map) { + map.remove(); + }); + }; + return TileMap; };