Skip to content

Commit

Permalink
[Maps] Use mapbox feature-state for dynamic properties and upgrade ma…
Browse files Browse the repository at this point in the history
…pbox-gl to 0.54 (#36466) (#36945)
  • Loading branch information
nreese committed May 23, 2019
1 parent a60d91b commit 013235b
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 89 deletions.
2 changes: 1 addition & 1 deletion x-pack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@
"lodash.topath": "^4.5.2",
"lodash.uniqby": "^4.7.0",
"lz-string": "^1.4.4",
"mapbox-gl": "0.52.0",
"mapbox-gl": "0.54.0",
"mapbox-gl-draw-rectangle-mode": "^1.0.4",
"markdown-it": "^8.4.1",
"mime": "^2.2.2",
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/maps/common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const SOURCE_DATA_ID_ORIGIN = 'source';

export const DECIMAL_DEGREES_PRECISION = 5; // meters precision
export const ZOOM_PRECISION = 2;
export const DEFAULT_ES_DOC_LIMIT = 2048;

export const FEATURE_ID_PROPERTY_NAME = '__kbn__feature_id__';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/

export const DEFAULT_ES_DOC_LIMIT = 2048;

export const DEFAULT_FILTER_BY_MAP_BOUNDS = true;
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import { NoIndexPatternCallout } from '../../../components/no_index_pattern_call
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { kfetch } from 'ui/kfetch';
import { ES_GEO_FIELD_TYPE, GIS_API_PATH } from '../../../../../common/constants';
import { DEFAULT_ES_DOC_LIMIT, DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants';
import { ES_GEO_FIELD_TYPE, GIS_API_PATH, DEFAULT_ES_DOC_LIMIT } from '../../../../../common/constants';
import { DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants';

function filterGeoField(field) {
return [ES_GEO_FIELD_TYPE.GEO_POINT, ES_GEO_FIELD_TYPE.GEO_SHAPE].includes(field.type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import { SearchSource } from '../../../../kibana_services';
import { hitsToGeoJson } from '../../../../elasticsearch_geo_utils';
import { CreateSourceEditor } from './create_source_editor';
import { UpdateSourceEditor } from './update_source_editor';
import { ES_SEARCH, ES_GEO_FIELD_TYPE } from '../../../../../common/constants';
import { ES_SEARCH, ES_GEO_FIELD_TYPE, DEFAULT_ES_DOC_LIMIT } from '../../../../../common/constants';
import { i18n } from '@kbn/i18n';
import { getDataSourceLabel } from '../../../../../common/i18n_getters';
import { ESTooltipProperty } from '../../tooltips/es_tooltip_property';
import { getTermsFields } from '../../../utils/get_terms_fields';

import { DEFAULT_ES_DOC_LIMIT, DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants';
import { DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants';

export class ESSearchSource extends AbstractESSource {

Expand Down Expand Up @@ -54,7 +54,6 @@ export class ESSearchSource extends AbstractESSource {
type: ESSearchSource.type,
indexPatternId: descriptor.indexPatternId,
geoField: descriptor.geoField,
limit: _.get(descriptor, 'limit', DEFAULT_ES_DOC_LIMIT),
filterByMapBounds: _.get(descriptor, 'filterByMapBounds', DEFAULT_FILTER_BY_MAP_BOUNDS),
tooltipProperties: _.get(descriptor, 'tooltipProperties', []),
}, inspectorAdapters);
Expand Down Expand Up @@ -129,7 +128,7 @@ export class ESSearchSource extends AbstractESSource {
}

async getGeoJsonWithMeta(layerName, searchFilters) {
const searchSource = await this._makeSearchSource(searchFilters, this._descriptor.limit);
const searchSource = await this._makeSearchSource(searchFilters, DEFAULT_ES_DOC_LIMIT);
// Setting "fields" instead of "source: { includes: []}"
// because SearchSource automatically adds the following by default
// 1) all scripted fields
Expand Down
61 changes: 44 additions & 17 deletions x-pack/plugins/maps/public/shared/layers/styles/vector_style.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,8 @@ export class VectorStyle extends AbstractStyle {
return (<VectorStyleLegend styleProperties={styleProperties}/>);
}

addScaledPropertiesBasedOnStyle(featureCollection) {
if (!featureCollection || featureCollection.length === 0) {
return false;
}

const scaledFields = this.getDynamicPropertiesArray()
_getScaledFields() {
return this.getDynamicPropertiesArray()
.map(({ options }) => {
const name = options.field.name;
return {
Expand All @@ -318,16 +314,46 @@ export class VectorStyle extends AbstractStyle {
};
})
.filter(({ range }) => {
return range;
return !!range;
});

}

clearFeatureState(featureCollection, mbMap, sourceId) {
const tmpFeatureIdentifier = {
source: null,
id: null
};
for (let i = 0; i < featureCollection.features.length; i++) {
const feature = featureCollection.features[i];
tmpFeatureIdentifier.source = sourceId;
tmpFeatureIdentifier.id = feature.id;
mbMap.removeFeatureState(tmpFeatureIdentifier);
}
}

setFeatureState(featureCollection, mbMap, sourceId) {

if (!featureCollection) {
return;
}

const scaledFields = this._getScaledFields();
if (scaledFields.length === 0) {
return false;
return;
}

const tmpFeatureIdentifier = {
source: null,
id: null
};
const tmpFeatureState = {};

//scale to [0,1] domain
featureCollection.features.forEach(feature => {
scaledFields.forEach(({ name, range, computedName }) => {
for (let i = 0; i < featureCollection.features.length; i++) {
const feature = featureCollection.features[i];
for (let j = 0; j < scaledFields.length; j++) {
const { name, range, computedName } = scaledFields[j];
const unscaledValue = parseFloat(feature.properties[name]);
let scaledValue;
if (isNaN(unscaledValue)) {//cannot scale
Expand All @@ -337,11 +363,12 @@ export class VectorStyle extends AbstractStyle {
} else {
scaledValue = (feature.properties[name] - range.min) / range.delta;
}
feature.properties[computedName] = scaledValue;
});
});

return true;
tmpFeatureState[computedName] = scaledValue;
}
tmpFeatureIdentifier.source = sourceId;
tmpFeatureIdentifier.id = feature.id;
mbMap.setFeatureState(tmpFeatureIdentifier, tmpFeatureState);
}
}

_getMBDataDrivenColor({ fieldName, color }) {
Expand All @@ -354,7 +381,7 @@ export class VectorStyle extends AbstractStyle {
return [
'interpolate',
['linear'],
['coalesce', ['get', targetName], -1],
['coalesce', ['feature-state', targetName], -1],
-1, 'rgba(0,0,0,0)',
...colorRange
];
Expand All @@ -364,7 +391,7 @@ export class VectorStyle extends AbstractStyle {
const targetName = VectorStyle.getComputedFieldName(fieldName);
return ['interpolate',
['linear'],
['get', targetName],
['feature-state', targetName],
0, minSize,
1, maxSize
];
Expand Down
31 changes: 20 additions & 11 deletions x-pack/plugins/maps/public/shared/layers/vector_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ const EMPTY_FEATURE_COLLECTION = {
features: []
};


const CLOSED_SHAPE_MB_FILTER = [
'any',
['==', ['geometry-type'], GEO_JSON_TYPE.POLYGON],
Expand All @@ -36,6 +35,15 @@ const ALL_SHAPE_MB_FILTER = [
['==', ['geometry-type'], GEO_JSON_TYPE.MULTI_LINE_STRING]
];


let idCounter = 0;
function generateNumericalId() {
const newId = idCounter < Number.MAX_SAFE_INTEGER ? idCounter : 0;
idCounter = newId + 1;
return newId;
}


export class VectorLayer extends AbstractLayer {

static type = 'VECTOR';
Expand Down Expand Up @@ -364,11 +372,12 @@ export class VectorLayer extends AbstractLayer {
}
}


_assignIdsToFeatures(featureCollection) {
for (let i = 0; i < featureCollection.features.length; i++) {
const feature = featureCollection.features[i];
feature.properties[FEATURE_ID_PROPERTY_NAME] = (typeof feature.id === 'string' || typeof feature.id === 'number') ? feature.id : i;
const id = generateNumericalId();
feature.properties[FEATURE_ID_PROPERTY_NAME] = id;
feature.id = id;
}
}

Expand Down Expand Up @@ -406,23 +415,23 @@ export class VectorLayer extends AbstractLayer {
}

_syncFeatureCollectionWithMb(mbMap) {
const mbGeoJSONSource = mbMap.getSource(this.getId());

const mbGeoJSONSource = mbMap.getSource(this.getId());
const featureCollection = this._getSourceFeatureCollection();
const featureCollectionOnMap = AbstractLayer.getBoundDataForSource(mbMap, this.getId());

if (!featureCollection) {
if (featureCollectionOnMap) {
this._style.clearFeatureState(featureCollectionOnMap, mbMap, this.getId());
}
mbGeoJSONSource.setData(EMPTY_FEATURE_COLLECTION);
return;
}

const dataBoundToMap = AbstractLayer.getBoundDataForSource(mbMap, this.getId());
if (featureCollection !== dataBoundToMap) {
mbGeoJSONSource.setData(featureCollection);
}

const shouldRefresh = this._style.addScaledPropertiesBasedOnStyle(featureCollection);
if (shouldRefresh) {
if (featureCollection !== featureCollectionOnMap) {
mbGeoJSONSource.setData(featureCollection);
}
this._style.setFeatureState(featureCollection, mbMap, this.getId());
}

_setMbPointsProperties(mbMap) {
Expand Down
6 changes: 3 additions & 3 deletions x-pack/test/functional/apps/maps/joins.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,16 @@ export default function ({ getPageObjects, getService }) {

//circle layer for points
// eslint-disable-next-line max-len
expect(layersForVectorSource[0]).to.eql({ 'id': 'n1t6f_circle', 'type': 'circle', 'source': 'n1t6f', 'minzoom': 0, 'maxzoom': 24, 'filter': ['any', ['==', ['geometry-type'], 'Point'], ['==', ['geometry-type'], 'MultiPoint']], 'paint': { 'circle-color': ['interpolate', ['linear'], ['coalesce', ['get', '__kbn__scaled(__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name)'], -1], -1, 'rgba(0,0,0,0)', 0, '#f7faff', 0.125, '#ddeaf7', 0.25, '#c5daee', 0.375, '#9dc9e0', 0.5, '#6aadd5', 0.625, '#4191c5', 0.75, '#2070b4', 0.875, '#072f6b'], 'circle-opacity': 0.75, 'circle-stroke-color': '#FFFFFF', 'circle-stroke-opacity': 0.75, 'circle-stroke-width': 1, 'circle-radius': 10 } });
expect(layersForVectorSource[0]).to.eql({ 'id': 'n1t6f_circle', 'type': 'circle', 'source': 'n1t6f', 'minzoom': 0, 'maxzoom': 24, 'filter': ['any', ['==', ['geometry-type'], 'Point'], ['==', ['geometry-type'], 'MultiPoint']], 'layout': { 'visibility': 'visible' }, 'paint': { 'circle-color': ['interpolate', ['linear'], ['coalesce', ['feature-state', '__kbn__scaled(__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name)'], -1], -1, 'rgba(0,0,0,0)', 0, '#f7faff', 0.125, '#ddeaf7', 0.25, '#c5daee', 0.375, '#9dc9e0', 0.5, '#6aadd5', 0.625, '#4191c5', 0.75, '#2070b4', 0.875, '#072f6b'], 'circle-opacity': 0.75, 'circle-stroke-color': '#FFFFFF', 'circle-stroke-opacity': 0.75, 'circle-stroke-width': 1, 'circle-radius': 10 } });

//fill layer
// eslint-disable-next-line max-len
expect(layersForVectorSource[1]).to.eql({ 'id': 'n1t6f_fill', 'type': 'fill', 'source': 'n1t6f', 'minzoom': 0, 'maxzoom': 24, 'filter': ['any', ['==', ['geometry-type'], 'Polygon'], ['==', ['geometry-type'], 'MultiPolygon']], 'paint': { 'fill-color': ['interpolate', ['linear'], ['coalesce', ['get', '__kbn__scaled(__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name)'], -1], -1, 'rgba(0,0,0,0)', 0, '#f7faff', 0.125, '#ddeaf7', 0.25, '#c5daee', 0.375, '#9dc9e0', 0.5, '#6aadd5', 0.625, '#4191c5', 0.75, '#2070b4', 0.875, '#072f6b'], 'fill-opacity': 0.75 } }
expect(layersForVectorSource[1]).to.eql({ 'id': 'n1t6f_fill', 'type': 'fill', 'source': 'n1t6f', 'minzoom': 0, 'maxzoom': 24, 'filter': ['any', ['==', ['geometry-type'], 'Polygon'], ['==', ['geometry-type'], 'MultiPolygon']], 'layout': { 'visibility': 'visible' }, 'paint': { 'fill-color': ['interpolate', ['linear'], ['coalesce', ['feature-state', '__kbn__scaled(__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name)'], -1], -1, 'rgba(0,0,0,0)', 0, '#f7faff', 0.125, '#ddeaf7', 0.25, '#c5daee', 0.375, '#9dc9e0', 0.5, '#6aadd5', 0.625, '#4191c5', 0.75, '#2070b4', 0.875, '#072f6b'], 'fill-opacity': 0.75 } }
);

//line layer for borders
// eslint-disable-next-line max-len
expect(layersForVectorSource[2]).to.eql({ 'id': 'n1t6f_line', 'type': 'line', 'source': 'n1t6f', 'minzoom': 0, 'maxzoom': 24, 'filter': ['any', ['==', ['geometry-type'], 'Polygon'], ['==', ['geometry-type'], 'MultiPolygon'], ['==', ['geometry-type'], 'LineString'], ['==', ['geometry-type'], 'MultiLineString']], 'paint': { 'line-color': '#FFFFFF', 'line-opacity': 0.75, 'line-width': 1 } });
expect(layersForVectorSource[2]).to.eql({ 'id': 'n1t6f_line', 'type': 'line', 'source': 'n1t6f', 'minzoom': 0, 'maxzoom': 24, 'filter': ['any', ['==', ['geometry-type'], 'Polygon'], ['==', ['geometry-type'], 'MultiPolygon'], ['==', ['geometry-type'], 'LineString'], ['==', ['geometry-type'], 'MultiLineString']], 'layout': { 'visibility': 'visible' }, 'paint': { 'line-color': '#FFFFFF', 'line-opacity': 0.75, 'line-width': 1 } });

});

Expand Down
Loading

0 comments on commit 013235b

Please sign in to comment.