kepler.gl.geoiq
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
799 lines (696 loc) • 92.2 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.pointVisConfigs = exports.pointPosResolver = exports.pointPosAccessor = exports.pointLabelResolver = exports.pointLabelAccessor = exports.pointHeightPosResolver = exports.pointHeightPosAccessor = exports.geojsonVisConfigs = exports["default"] = exports.boundaryRequiredColumns = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _baseLayer = _interopRequireDefault(require("../base-layer"));
var _deck = require("deck.gl");
var _lodash = _interopRequireDefault(require("lodash.memoize"));
var _aggregateUtils = require("../../utils/aggregate-utils");
var _colorUtils = require("../../utils/color-utils");
var _geoHashLayerIcon = _interopRequireDefault(require("./geo-hash-layer-icon"));
var _axios = _interopRequireDefault(require("axios"));
var _collect = _interopRequireDefault(require("@turf/collect"));
var _helpers = require("@turf/helpers");
var _d3Array = require("d3-array");
var _geoHashLayerUtils = require("./geo-hash-layer-utils");
var _defaultSettings = require("../../constants/default-settings");
var _dataUtils = require("../../utils/data-utils");
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function saveText(text, filename) {
var a = document.createElement('a');
a.setAttribute('href', "data:text/plain;charset=utf-u,".concat(encodeURIComponent(text)));
a.setAttribute('download', filename);
a.click();
}
var pointPosAccessor = exports.pointPosAccessor = function pointPosAccessor(_ref) {
var columns = _ref.columns,
colorField = _ref.colorField;
return function (d) {
var lat = columns.lat,
lng = columns.lng,
altitude = columns.altitude;
var data;
if (colorField) {
data = d.data[colorField.tableFieldIndex - 1];
} else {
data = 1;
}
if (d.data[lng.fieldIdx] && d.data[lat.fieldIdx] // &&
// !is.NaN(d.data[lat.fieldIdx]) &&
// !is.NaN(d.data[lat.fieldIdx])
) {
return [(0, _helpers.point)([d.data[lng.fieldIdx], d.data[lat.fieldIdx]], {
aggregationData: data
})];
}
};
};
var pointPosResolver = exports.pointPosResolver = function pointPosResolver(_ref2) {
var columns = _ref2.columns,
colorField = _ref2.colorField;
return "".concat(columns.lat.fieldIdx, "-").concat(columns.lng.fieldIdx, "-").concat(columns.altitude ? columns.altitude.fieldIdx : 'z', "-").concat(colorField ? colorField.tableFieldIndex : null);
};
var pointHeightPosAccessor = exports.pointHeightPosAccessor = function pointHeightPosAccessor(_ref3) {
var columns = _ref3.columns,
heightField = _ref3.heightField;
return function (d) {
var lat = columns.lat,
lng = columns.lng,
altitude = columns.altitude;
var data;
if (heightField) {
data = d.data[heightField.tableFieldIndex - 1];
} else {
data = 1;
}
if (d.data[lng.fieldIdx] && d.data[lat.fieldIdx] // &&
// !is.NaN(d.data[lat.fieldIdx]) &&
// !is.NaN(d.data[lat.fieldIdx])
) {
return [(0, _helpers.point)([d.data[lng.fieldIdx], d.data[lat.fieldIdx]], {
heightAggregationData: data
})];
}
};
};
var pointHeightPosResolver = exports.pointHeightPosResolver = function pointHeightPosResolver(_ref4) {
var columns = _ref4.columns,
heightField = _ref4.heightField;
return "".concat(columns.lat.fieldIdx, "-").concat(columns.lng.fieldIdx, "-").concat(columns.altitude ? columns.altitude.fieldIdx : 'z', "-").concat(heightField ? heightField.tableFieldIndex : null);
};
var getLayerColorRange = function getLayerColorRange(colorRange) {
return colorRange.colors.map(_colorUtils.hexToRgb);
};
var pointLabelAccessor = exports.pointLabelAccessor = function pointLabelAccessor(textLabel) {
return function (d) {
return String(d.data[textLabel.field.tableFieldIndex - 1]);
};
};
var pointLabelResolver = exports.pointLabelResolver = function pointLabelResolver(textLabel) {
return textLabel.field && textLabel.field.tableFieldIndex;
};
var boundaryRequiredColumns = exports.boundaryRequiredColumns = ['lat', 'lng']; // export const pointOptionalColumns = ['altitude'];
var pointVisConfigs = exports.pointVisConfigs = {
radius: 'radius',
fixedRadius: 'fixedRadius',
opacity: 'opacity',
outline: 'outline',
thickness: 'thickness',
colorRange: 'colorRange',
radiusRange: 'radiusRange',
'hi-precision': 'hi-precision'
};
var geojsonVisConfigs = exports.geojsonVisConfigs = {
opacity: 'opacity',
thickness: {
type: 'number',
defaultValue: 0.5,
label: 'Stroke Width',
isRanged: false,
range: [0, 100],
step: 0.1,
group: 'stroke',
property: 'thickness'
},
colorRange: 'colorRange',
radius: 'radius',
colorAggregation: 'aggregation',
heightAggregation: 'heightAggregation',
sizeRange: 'strokeWidthRange',
radiusRange: 'radiusRange',
heightRange: 'elevationRange',
elevationScale: 'elevationScale',
'hi-precision': 'hi-precision',
stroked: 'stroked',
filled: 'filled',
enable3d: 'enable3d',
wireframe: 'wireframe'
};
var GeoHashLayer = exports["default"] = /*#__PURE__*/function (_Layer) {
(0, _inherits2["default"])(GeoHashLayer, _Layer);
var _super = _createSuper(GeoHashLayer);
function GeoHashLayer(props) {
var _this;
(0, _classCallCheck2["default"])(this, GeoHashLayer);
_this = _super.call(this, props);
_this.registerVisConfig(geojsonVisConfigs);
_this.getPosition = (0, _lodash["default"])(pointPosAccessor, pointPosResolver);
_this.getHeightPosition = (0, _lodash["default"])(pointHeightPosAccessor, pointHeightPosResolver);
_this.getText = (0, _lodash["default"])(pointLabelAccessor, pointLabelResolver); // this.getColorValue = memoize(getValueAggr, aggrResolver);
_this.getColorRange = (0, _lodash["default"])(getLayerColorRange);
return _this;
}
(0, _createClass2["default"])(GeoHashLayer, [{
key: "type",
get: function get() {
return 'geoHash';
}
}, {
key: "isAggregated",
get: function get() {
return true;
}
}, {
key: "showLoader",
get: function get() {
return true;
}
}, {
key: "layerIcon",
get: function get() {
return _geoHashLayerIcon["default"];
}
}, {
key: "requiredLayerColumns",
get: function get() {
return boundaryRequiredColumns;
}
}, {
key: "columnPairs",
get: function get() {
return this.defaultPointColumnPairs;
}
}, {
key: "noneLayerDataAffectingProps",
get: function get() {
return [].concat((0, _toConsumableArray2["default"])((0, _get2["default"])((0, _getPrototypeOf2["default"])(GeoHashLayer.prototype), "noneLayerDataAffectingProps", this)), ['radius']);
}
}, {
key: "visualChannels",
get: function get() {
var _objectSpread2;
return _objectSpread(_objectSpread({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(GeoHashLayer.prototype), "visualChannels", this)), {}, {
color: _objectSpread(_objectSpread({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(GeoHashLayer.prototype), "visualChannels", this).color), {}, {
aggregation: 'colorAggregation',
channelScaleType: _defaultSettings.CHANNEL_SCALES.colorAggr,
defaultMeasure: 'Point Count',
domain: 'colorDomain',
field: 'colorField',
key: 'color',
property: 'color',
range: 'colorRange',
scale: 'colorScale'
}),
size: _objectSpread(_objectSpread({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(GeoHashLayer.prototype), "visualChannels", this).size), {}, (_objectSpread2 = {
property: 'stroke',
aggregation: 'sizeAggregation',
channelScaleType: _defaultSettings.CHANNEL_SCALES.sizeAggr,
condition: function condition(config) {
return config.visConfig.enable3d;
},
defaultMeasure: 'Point Count',
domain: 'sizeDomain',
field: 'sizeField',
key: 'size'
}, (0, _defineProperty2["default"])(_objectSpread2, "property", 'stroke'), (0, _defineProperty2["default"])(_objectSpread2, "range", 'sizeRange'), (0, _defineProperty2["default"])(_objectSpread2, "scale", 'sizeScale'), _objectSpread2))
});
}
}, {
key: "shouldRenderColumnConfig",
value: function shouldRenderColumnConfig() {
return false;
}
/**
* Get the description of a visualChannel config
* @param key
* @returns {{label: string, measure: (string|string)}}
*/
}, {
key: "getVisualChannelDescription",
value: function getVisualChannelDescription(key) {
// e.g. label: Color, measure: Average of ETA
var _this$visualChannels$ = this.visualChannels[key],
range = _this$visualChannels$.range,
field = _this$visualChannels$.field,
defaultMeasure = _this$visualChannels$.defaultMeasure,
aggregation = _this$visualChannels$.aggregation;
return {
label: this.visConfigSettings[range].label,
measure: this.config[field] ? "".concat(this.config.visConfig[aggregation], " of ").concat(this.config[field].name) : defaultMeasure
};
}
}, {
key: "getHoverData",
value: function getHoverData(object, allData) {
// index of allData is saved to feature.properties
return object;
}
}, {
key: "getDefaultLayerConfig",
value: function getDefaultLayerConfig() {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return _objectSpread(_objectSpread({}, (0, _get2["default"])((0, _getPrototypeOf2["default"])(GeoHashLayer.prototype), "getDefaultLayerConfig", this).call(this, props)), {}, {
apiCallRequest: true,
// add height visual channel
heightField: null,
heightDomain: [0, 1],
heightScale: 'linear'
});
}
/**
* Aggregation layer handles visual channel aggregation inside deck.gl layer
*/
}, {
key: "updateLayerVisualChannel",
value: function updateLayerVisualChannel(_ref5, channel) {
var data = _ref5.data,
allData = _ref5.allData;
this.validateVisualChannel(channel);
} // /**
// * Validate aggregation type on top of basic layer visual channel validation
// * @param channel
// */
}, {
key: "validateVisualChannel",
value: function validateVisualChannel(channel) {
// field type decides aggregation type decides scale type
this.validateFieldType(channel);
this.validateAggregationType(channel);
this.validateScale(channel);
}
/**
* Validate aggregation type based on selected field
*/
}, {
key: "validateAggregationType",
value: function validateAggregationType(channel) {
var visualChannel = this.visualChannels[channel];
var field = visualChannel.field,
aggregation = visualChannel.aggregation;
var aggregationOptions = this.getAggregationOptions(channel);
if (!aggregation) {
return;
}
if (!aggregationOptions.length) {
// if field cannot be aggregated, set field to null
this.updateLayerConfig((0, _defineProperty2["default"])({}, field, null));
} else if (!aggregationOptions.includes(this.config.visConfig[aggregation])) {
// current aggregation type is not supported by this field
// set aggregation to the first supported option
this.updateLayerVisConfig((0, _defineProperty2["default"])({}, aggregation, aggregationOptions[0]));
}
}
}, {
key: "getAggregationOptions",
value: function getAggregationOptions(channel) {
var visualChannel = this.visualChannels[channel];
var field = visualChannel.field,
channelScaleType = visualChannel.channelScaleType;
return Object.keys(this.config[field] ? _defaultSettings.FIELD_OPTS[this.config[field].type].scale[channelScaleType] : _defaultSettings.DEFAULT_AGGREGATION[channelScaleType]);
}
/**
* Get scale options based on current field and aggregation type
* @param {string} channel
* @returns {string[]}
*/
}, {
key: "getScaleOptions",
value: function getScaleOptions(channel) {
var visualChannel = this.visualChannels[channel];
var field = visualChannel.field,
aggregation = visualChannel.aggregation,
channelScaleType = visualChannel.channelScaleType,
scale = visualChannel.scale;
var aggregationType = this.config.visConfig[aggregation];
return this.config[field] ? // scale options based on aggregation
_defaultSettings.FIELD_OPTS[this.config[field].type].scale[channelScaleType][aggregationType] : // default scale options for point count
_defaultSettings.DEFAULT_AGGREGATION[channelScaleType][aggregationType];
}
}, {
key: "axiosApiCall",
value: function axiosApiCall(datasets, viewport, zoom, filters, auth, project) {
var _this$config = this.config,
colorField = _this$config.colorField,
dataId = _this$config.dataId,
visConfig = _this$config.visConfig;
var colorAggregation = visConfig.colorAggregation;
var indexName = datasets[dataId].indexName;
var isEdit = project.isEdit;
var uid = auth.uid;
filters = filters.filter(function (f) {
return f.dataId.includes(dataId);
});
var config = {
headers: {
'Content-Type': 'application/json'
}
}; // aggregation type
// filters
// viewport
// zoom
var data = {
colorField: colorField ? colorField.name : null,
colorAggregation: colorField ? colorAggregation : 'count',
colorFieldType: colorField ? colorField.type : null,
filters: JSON.stringify(filters),
indexName: indexName,
userId: uid,
viewport: JSON.stringify(viewport),
zoom: zoom,
permissionType: isEdit
}; // const url = 'https://app.geoiq.io/boundary/v1.0/boundary_query';
var response = _axios["default"].post("".concat(_defaultSettings.ON_PREMESIS_URL, "/geoiqlayers/hashlayer/v1.0/fetch"), data, config).then(function (response) {
return response.data.data;
})["catch"](); // const response = geoHashData;
return response;
}
/**
* helper function to update one layer domain when state.data changed
* if state.data change is due ot update filter, newFiler will be passed
* called by updateAllLayerDomainData
* @param {Object} dataset
* @param {Object} newFilter
* @returns {object} layer
* @returns {object} widget
*/
}, {
key: "updateLayerDomain",
value: function updateLayerDomain(dataset, layerData, newFilter) {
var _this2 = this;
Object.values(this.visualChannels).forEach(function (channel) {
var scale = channel.scale;
var scaleType = _this2.config[scale]; // ordinal domain is based on allData, if only filter changed
// no need to update ordinal domain
if (!newFilter || scaleType !== _defaultSettings.SCALE_TYPES.ordinal) {
var domain = channel.domain;
var updatedDomain = _this2.calculateLayerDomain(dataset, layerData, channel);
_this2.updateLayerConfig((0, _defineProperty2["default"])({}, domain, updatedDomain));
}
});
return this;
}
}, {
key: "calculateLayerDomain",
value: function calculateLayerDomain(dataset, layerData, visualChannel) {
var allData = dataset.allData,
filteredIndexForDomain = dataset.filteredIndexForDomain;
var colorField = this.config.colorField; // const defaultDomain = [0, 1];
var defaultDomain;
var values;
if (layerData && colorField && layerData.collected) {
values = layerData.collected.map(function (c) {
return c.properties.aggregatedData;
});
return (0, _dataUtils.unique)(values).filter(_dataUtils.notNullorUndefined).sort();
} else if (layerData && layerData.collected) {
values = layerData.collected.map(function (c) {
return c.properties.totalCount;
});
return (0, _dataUtils.unique)(values).filter(_dataUtils.notNullorUndefined).sort();
}
defaultDomain = [0, 1];
var scale = visualChannel.scale;
var scaleType = this.config[scale];
var field = this.config[visualChannel.field];
if (!field) {
// if colorField or sizeField were set back to null
return defaultDomain;
}
if (!_defaultSettings.SCALE_TYPES[scaleType]) {
Console.error("scale type ".concat(scaleType, " not supported"));
return defaultDomain;
} // TODO: refactor to add valueAccessor to field
var fieldIdx = field.tableFieldIndex - 1;
var isTime = field.type === _defaultSettings.ALL_FIELD_TYPES.timestamp;
var valueAccessor = _dataUtils.maybeToDate.bind(null, isTime, fieldIdx, field.format);
var indexValueAccessor = function indexValueAccessor(i) {
return valueAccessor(allData[i]);
};
var sortFunction = (0, _dataUtils.getSortingFunction)(field.type);
if (!values) {
return defaultDomain;
}
switch (scaleType) {
case _defaultSettings.SCALE_TYPES.ordinal:
case _defaultSettings.SCALE_TYPES.point:
// do not recalculate ordinal domain based on filtered data
// don't need to update ordinal domain every time
return defaultDomain;
case _defaultSettings.SCALE_TYPES.quantile:
return values.filter(_dataUtils.notNullorUndefined).sort(sortFunction);
case _defaultSettings.SCALE_TYPES.quantize:
case _defaultSettings.SCALE_TYPES.linear:
case _defaultSettings.SCALE_TYPES.sqrt:
default:
return (0, _d3Array.extent)(values).map(function (d, i) {
return d === undefined ? i : d;
});
}
}
}, {
key: "getEncodedChannelValue",
value: function getEncodedChannelValue(scale, data, field) {
var defaultValue = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : _defaultSettings.NO_VALUE_COLOR;
var type = field.type;
var value = data;
var attributeValue;
if (type === _defaultSettings.ALL_FIELD_TYPES.timestamp) {
// shouldn't need to convert here
// scale Function should take care of it
attributeValue = scale(new Date(value));
} else {
attributeValue = scale(value);
}
if (!attributeValue) {
attributeValue = defaultValue;
}
return attributeValue;
}
}, {
key: "calculateHeightDomain",
value: function calculateHeightDomain(value, minMax) {
if (!minMax.length) {
return [value, value];
}
var min = (0, _aggregateUtils.aggregate)([value, minMax[0]], 'minimum');
var max = (0, _aggregateUtils.aggregate)([value, minMax[1]], 'maximum');
return [min, max];
}
}, {
key: "calculateBoundaryAggregatedData",
value: function calculateBoundaryAggregatedData(collected, colorField, colorAggregation) {
var colorDomain = [];
if (colorField && collected) {
collected.map(function (c) {
colorDomain.push(c.properties.aggregatedData);
});
} else if (collected) {
collected.map(function (c) {
return colorDomain.push(c.properties.totalCount);
});
}
return {
collected: collected,
colorDomain: colorDomain
};
} // TODO: fix complexity
/* eslint-disable complexity */
}, {
key: "formatLayerData",
value: function formatLayerData(_, allData, filteredIndex, oldLayerData, response, opt) {
var _this3 = this;
var _this$config2 = this.config,
colorScale = _this$config2.colorScale,
colorField = _this$config2.colorField,
sizeScale = _this$config2.sizeScale,
sizeDomain = _this$config2.sizeDomain,
sizeField = _this$config2.sizeField,
heightField = _this$config2.heightField,
heightScale = _this$config2.heightScale,
visConfig = _this$config2.visConfig;
var _this$config3 = this.config,
heightDomain = _this$config3.heightDomain,
colorDomain = _this$config3.colorDomain;
var stroked = visConfig.stroked,
colorAggregation = visConfig.colorAggregation,
colorRange = visConfig.colorRange,
heightRange = visConfig.heightRange,
sizeRange = visConfig.sizeRange; // if (!oldLayerData || oldLayerData.getHeightPosition !== getHeightPosition) {
// this.updateLayerMeta(allData, getHeightPositon);
// }
if (!oldLayerData) {
this.updateLayerMeta();
}
if (oldLayerData && oldLayerData.collected) {
var collected = oldLayerData.collected;
}
colorDomain = [];
if (response) {
collected = (0, _geoHashLayerUtils.geoHashToPolygon)(response.geohashes, colorField, colorAggregation);
}
var _this$calculateBounda = this.calculateBoundaryAggregatedData(collected, colorField, colorAggregation),
collected = _this$calculateBounda.collected,
colorDomain = _this$calculateBounda.colorDomain;
Object.values(this.visualChannels).forEach(function (channel) {
var scale = channel.scale,
domain = channel.domain; // ordinal domain is based on allData, if only filter changed
// no need to update ordinal domain
if (collected) {
var updatedDomain = _this3.calculateLayerDomain({}, {
collected: collected
}, channel);
_this3.updateLayerConfig((0, _defineProperty2["default"])({}, domain, updatedDomain));
}
}); // used for saving geoJson
// if (collected) {
// saveText(JSON.stringify(featureCollection(collected)), 'filename.json');
// }
// }
var cScale = this.getVisChannelScale(colorScale, colorDomain, colorRange.colors.map(_colorUtils.hexToRgb)); // calculate stroke scale - if stroked = true
var sScale = sizeField && stroked && this.getVisChannelScale(sizeScale, sizeDomain, sizeRange); // calculate elevation scale - if extruded = true
var eScale = this.getVisChannelScale(heightScale, heightDomain, heightRange);
return {
collected: collected,
getFillColor: function getFillColor(d) {
return colorField ? _this3.getEncodedChannelValue(cScale, d.properties.aggregatedData, colorField) : _this3.getEncodedChannelValue(cScale, d.properties.totalCount, {
type: 'real'
});
},
getLineColor: function getLineColor(d) {
return colorField ? _this3.getEncodedChannelValue(cScale, d.properties.aggregatedData, colorField) : _this3.getEncodedChannelValue(cScale, d.properties.totalCount, {
type: 'real'
});
},
getLineWidth: function getLineWidth(d) {
return sScale ? _this3.getEncodedChannelValue(sScale, allData[d.properties.index], sizeField, 0) : d.properties.lineWidth || 1;
},
getElevation: function getElevation(d) {
return heightField ? _this3.getEncodedChannelValue(eScale, d.properties.heightAggregatedData, heightField, 0) : _this3.getEncodedChannelValue(eScale, d.properties.totalCount, {
type: 'real'
}, 0);
}
};
}
/* eslint-enable complexity */
}, {
key: "updateLayerMeta",
value: function updateLayerMeta() {
// const bounds = this.getPointsBounds(allData, d => getPosition({data: d}));
// get bounds from features
// const bounds = getGeojsonBounds(allFeatures);
// get lightSettings from points
// const lightSettings = this.getLightSettingsFromBounds(bounds);
// if any of the feature has properties.hi-precision set to be true
var fp64 = false;
var fixedRadius = false; // keep a record of what type of geometry the collection has
var featureTypes = {
polygon: true
};
this.updateMeta({
fp64: fp64,
fixedRadius: fixedRadius,
featureTypes: featureTypes
});
}
}, {
key: "renderLayer",
value: function renderLayer(_ref6) {
var data = _ref6.data,
idx = _ref6.idx,
objectHovered = _ref6.objectHovered,
mapState = _ref6.mapState,
interactionConfig = _ref6.interactionConfig;
var _this$meta = this.meta,
fp64 = _this$meta.fp64,
lightSettings = _this$meta.lightSettings,
fixedRadius = _this$meta.fixedRadius;
var radiusScale = this.getRadiusScaleByZoom(mapState, fixedRadius);
var zoomFactor = this.getZoomFactor(mapState);
var visConfig = this.config.visConfig;
var layerProps = {
// multiplier applied just so it being consistent with previously saved maps
lineWidthScale: visConfig.thickness * zoomFactor * 8,
lineWidthMinPixels: 1,
elevationScale: visConfig.elevationScale,
pointRadiusScale: radiusScale,
fp64: fp64 || visConfig['hi-precision'],
lineMiterLimit: 4
};
var updateTriggers = {
getElevation: {
heightField: this.config.heightField,
heightScale: this.config.heightScale,
aggregationType: visConfig.heightAggregation,
heightDomain: this.config.heightDomain,
heightRange: visConfig.heightRange
},
getFillColor: {
color: this.config.color,
colorField: this.config.colorField,
colorRange: visConfig.colorRange,
colorScale: this.config.colorScale,
aggregationType: visConfig.colorAggregation,
colorDomain: this.config.colorDomain,
apiCall: this.config.apiCallRequest,
boundary: this.config.boundaryAggregation
},
getLineColor: {
color: this.config.color,
colorField: this.config.colorField,
colorRange: visConfig.colorRange,
colorScale: this.config.colorScale,
aggregationType: visConfig.colorAggregation,
colorDomain: this.config.colorDomain,
apiCallComplete: this.config.apiCallComplete,
apiCall: this.config.apiCallRequest,
boundary: this.config.boundaryAggregation
},
getLineWidth: {
sizeField: this.config.sizeField,
sizeRange: visConfig.sizeRange
}
}; // this.config.apiCallComplete = false;
// this.config.apiCallRequest = false;
return [new _deck.GeoJsonLayer(_objectSpread(_objectSpread({}, layerProps), {}, {
id: this.id,
idx: idx,
data: data.collected,
getFillColor: data.getFillColor,
getLineColor: data.getLineColor,
getLineWidth: data.getLineWidth,
getElevation: data.getElevation,
// highlight
pickable: true,
// highlightColor: this.config.highlightColor,
autoHighlight: visConfig.enable3d,
// parameters
parameters: {
depthTest: Boolean(visConfig.enable3d || mapState.dragRotate)
},
opacity: visConfig.opacity,
stroked: visConfig.stroked,
filled: visConfig.filled,
extruded: visConfig.enable3d,
wireframe: visConfig.wireframe,
lightSettings: lightSettings,
updateTriggers: updateTriggers
}))].concat((0, _toConsumableArray2["default"])(this.isLayerHovered(objectHovered) && !visConfig.enable3d ? [new _deck.GeoJsonLayer(_objectSpread(_objectSpread({}, layerProps), {}, {
id: "".concat(this.id, "-hovered"),
data: [objectHovered.object],
getLineWidth: data.getLineWidth,
getElevation: data.getElevation,
getLineColor: this.config.highlightColor,
getFillColor: this.config.highlightColor,
updateTriggers: updateTriggers,
stroked: true,
pickable: false,
filled: false
}))] : []));
}
}]);
return GeoHashLayer;
}(_baseLayer["default"]);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYXllcnMvZ2VvLWhhc2gtbGF5ZXIvZ2VvLWhhc2gtbGF5ZXIuanMiXSwibmFtZXMiOlsic2F2ZVRleHQiLCJ0ZXh0IiwiZmlsZW5hbWUiLCJhIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50Iiwic2V0QXR0cmlidXRlIiwiZW5jb2RlVVJJQ29tcG9uZW50IiwiY2xpY2siLCJwb2ludFBvc0FjY2Vzc29yIiwiY29sdW1ucyIsImNvbG9yRmllbGQiLCJkIiwibGF0IiwibG5nIiwiYWx0aXR1ZGUiLCJkYXRhIiwidGFibGVGaWVsZEluZGV4IiwiZmllbGRJZHgiLCJhZ2dyZWdhdGlvbkRhdGEiLCJwb2ludFBvc1Jlc29sdmVyIiwicG9pbnRIZWlnaHRQb3NBY2Nlc3NvciIsImhlaWdodEZpZWxkIiwiaGVpZ2h0QWdncmVnYXRpb25EYXRhIiwicG9pbnRIZWlnaHRQb3NSZXNvbHZlciIsImdldExheWVyQ29sb3JSYW5nZSIsImNvbG9yUmFuZ2UiLCJjb2xvcnMiLCJtYXAiLCJoZXhUb1JnYiIsInBvaW50TGFiZWxBY2Nlc3NvciIsInRleHRMYWJlbCIsIlN0cmluZyIsImZpZWxkIiwicG9pbnRMYWJlbFJlc29sdmVyIiwiYm91bmRhcnlSZXF1aXJlZENvbHVtbnMiLCJwb2ludFZpc0NvbmZpZ3MiLCJyYWRpdXMiLCJmaXhlZFJhZGl1cyIsIm9wYWNpdHkiLCJvdXRsaW5lIiwidGhpY2tuZXNzIiwicmFkaXVzUmFuZ2UiLCJnZW9qc29uVmlzQ29uZmlncyIsInR5cGUiLCJkZWZhdWx0VmFsdWUiLCJsYWJlbCIsImlzUmFuZ2VkIiwicmFuZ2UiLCJzdGVwIiwiZ3JvdXAiLCJwcm9wZXJ0eSIsImNvbG9yQWdncmVnYXRpb24iLCJoZWlnaHRBZ2dyZWdhdGlvbiIsInNpemVSYW5nZSIsImhlaWdodFJhbmdlIiwiZWxldmF0aW9uU2NhbGUiLCJzdHJva2VkIiwiZmlsbGVkIiwiZW5hYmxlM2QiLCJ3aXJlZnJhbWUiLCJHZW9IYXNoTGF5ZXIiLCJwcm9wcyIsInJlZ2lzdGVyVmlzQ29uZmlnIiwiZ2V0UG9zaXRpb24iLCJnZXRIZWlnaHRQb3NpdGlvbiIsImdldFRleHQiLCJnZXRDb2xvclJhbmdlIiwiQm91bmRhcnlMYXllckljb24iLCJkZWZhdWx0UG9pbnRDb2x1bW5QYWlycyIsImNvbG9yIiwiYWdncmVnYXRpb24iLCJjaGFubmVsU2NhbGVUeXBlIiwiQ0hBTk5FTF9TQ0FMRVMiLCJjb2xvckFnZ3IiLCJkZWZhdWx0TWVhc3VyZSIsImRvbWFpbiIsImtleSIsInNjYWxlIiwic2l6ZSIsInNpemVBZ2dyIiwiY29uZGl0aW9uIiwiY29uZmlnIiwidmlzQ29uZmlnIiwidmlzdWFsQ2hhbm5lbHMiLCJ2aXNDb25maWdTZXR0aW5ncyIsIm1lYXN1cmUiLCJuYW1lIiwib2JqZWN0IiwiYWxsRGF0YSIsImFwaUNhbGxSZXF1ZXN0IiwiaGVpZ2h0RG9tYWluIiwiaGVpZ2h0U2NhbGUiLCJjaGFubmVsIiwidmFsaWRhdGVWaXN1YWxDaGFubmVsIiwidmFsaWRhdGVGaWVsZFR5cGUiLCJ2YWxpZGF0ZUFnZ3JlZ2F0aW9uVHlwZSIsInZhbGlkYXRlU2NhbGUiLCJ2aXN1YWxDaGFubmVsIiwiYWdncmVnYXRpb25PcHRpb25zIiwiZ2V0QWdncmVnYXRpb25PcHRpb25zIiwibGVuZ3RoIiwidXBkYXRlTGF5ZXJDb25maWciLCJpbmNsdWRlcyIsInVwZGF0ZUxheWVyVmlzQ29uZmlnIiwiT2JqZWN0Iiwia2V5cyIsIkZJRUxEX09QVFMiLCJERUZBVUxUX0FHR1JFR0FUSU9OIiwiYWdncmVnYXRpb25UeXBlIiwiZGF0YXNldHMiLCJ2aWV3cG9ydCIsInpvb20iLCJmaWx0ZXJzIiwiYXV0aCIsInByb2plY3QiLCJkYXRhSWQiLCJpbmRleE5hbWUiLCJpc0VkaXQiLCJ1aWQiLCJmaWx0ZXIiLCJmIiwiaGVhZGVycyIsImNvbG9yRmllbGRUeXBlIiwiSlNPTiIsInN0cmluZ2lmeSIsInVzZXJJZCIsInBlcm1pc3Npb25UeXBlIiwicmVzcG9uc2UiLCJheGlvcyIsInBvc3QiLCJPTl9QUkVNRVNJU19VUkwiLCJ0aGVuIiwiZGF0YXNldCIsImxheWVyRGF0YSIsIm5ld0ZpbHRlciIsInZhbHVlcyIsImZvckVhY2giLCJzY2FsZVR5cGUiLCJTQ0FMRV9UWVBFUyIsIm9yZGluYWwiLCJ1cGRhdGVkRG9tYWluIiwiY2FsY3VsYXRlTGF5ZXJEb21haW4iLCJmaWx0ZXJlZEluZGV4Rm9yRG9tYWluIiwiZGVmYXVsdERvbWFpbiIsImNvbGxlY3RlZCIsImMiLCJwcm9wZXJ0aWVzIiwiYWdncmVnYXRlZERhdGEiLCJub3ROdWxsb3JVbmRlZmluZWQiLCJzb3J0IiwidG90YWxDb3VudCIsIkNvbnNvbGUiLCJlcnJvciIsImlzVGltZSIsIkFMTF9GSUVMRF9UWVBFUyIsInRpbWVzdGFtcCIsInZhbHVlQWNjZXNzb3IiLCJtYXliZVRvRGF0ZSIsImJpbmQiLCJmb3JtYXQiLCJpbmRleFZhbHVlQWNjZXNzb3IiLCJpIiwic29ydEZ1bmN0aW9uIiwicG9pbnQiLCJxdWFudGlsZSIsInF1YW50aXplIiwibGluZWFyIiwic3FydCIsInVuZGVmaW5lZCIsIk5PX1ZBTFVFX0NPTE9SIiwidmFsdWUiLCJhdHRyaWJ1dGVWYWx1ZSIsIkRhdGUiLCJtaW5NYXgiLCJtaW4iLCJtYXgiLCJjb2xvckRvbWFpbiIsInB1c2giLCJfIiwiZmlsdGVyZWRJbmRleCIsIm9sZExheWVyRGF0YSIsIm9wdCIsImNvbG9yU2NhbGUiLCJzaXplU2NhbGUiLCJzaXplRG9tYWluIiwic2l6ZUZpZWxkIiwidXBkYXRlTGF5ZXJNZXRhIiwiZ2VvaGFzaGVzIiwiY2FsY3VsYXRlQm91bmRhcnlBZ2dyZWdhdGVkRGF0YSIsImNTY2FsZSIsImdldFZpc0NoYW5uZWxTY2FsZSIsInNTY2FsZSIsImVTY2FsZSIsImdldEZpbGxDb2xvciIsImdldEVuY29kZWRDaGFubmVsVmFsdWUiLCJnZXRMaW5lQ29sb3IiLCJnZXRMaW5lV2lkdGgiLCJpbmRleCIsImxpbmVXaWR0aCIsImdldEVsZXZhdGlvbiIsImhlaWdodEFnZ3JlZ2F0ZWREYXRhIiwiZnA2NCIsImZlYXR1cmVUeXBlcyIsInBvbHlnb24iLCJ1cGRhdGVNZXRhIiwiaWR4Iiwib2JqZWN0SG92ZXJlZCIsIm1hcFN0YXRlIiwiaW50ZXJhY3Rpb25Db25maWciLCJtZXRhIiwibGlnaHRTZXR0aW5ncyIsInJhZGl1c1NjYWxlIiwiZ2V0UmFkaXVzU2NhbGVCeVpvb20iLCJ6b29tRmFjdG9yIiwiZ2V0Wm9vbUZhY3RvciIsImxheWVyUHJvcHMiLCJsaW5lV2lkdGhTY2FsZSIsImxpbmVXaWR0aE1pblBpeGVscyIsInBvaW50UmFkaXVzU2NhbGUiLCJsaW5lTWl0ZXJMaW1pdCIsInVwZGF0ZVRyaWdnZXJzIiwiYXBpQ2FsbCIsImJvdW5kYXJ5IiwiYm91bmRhcnlBZ2dyZWdhdGlvbiIsImFwaUNhbGxDb21wbGV0ZSIsIkdlb0pzb25MYXllciIsImlkIiwicGlja2FibGUiLCJhdXRvSGlnaGxpZ2h0IiwicGFyYW1ldGVycyIsImRlcHRoVGVzdCIsIkJvb2xlYW4iLCJkcmFnUm90YXRlIiwiZXh0cnVkZWQiLCJpc0xheWVySG92ZXJlZCIsImhpZ2hsaWdodENvbG9yIiwiTGF5ZXIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFvQkE7O0FBQ0E7O0FBQ0E7O0FBR0E7O0FBRUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBRUE7O0FBU0E7Ozs7Ozs7Ozs7QUFTQSxTQUFTQSxRQUFULENBQWtCQyxJQUFsQixFQUF3QkMsUUFBeEIsRUFBa0M7QUFDaEMsTUFBSUMsQ0FBQyxHQUFHQyxRQUFRLENBQUNDLGFBQVQsQ0FBdUIsR0FBdkIsQ0FBUjtBQUNBRixFQUFBQSxDQUFDLENBQUNHLFlBQUYsQ0FDRSxNQURGLDBDQUVtQ0Msa0JBQWtCLENBQUNOLElBQUQsQ0FGckQ7QUFJQUUsRUFBQUEsQ0FBQyxDQUFDRyxZQUFGLENBQWUsVUFBZixFQUEyQkosUUFBM0I7QUFDQUMsRUFBQUEsQ0FBQyxDQUFDSyxLQUFGO0FBQ0Q7O0FBRU0s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