feat: Add deck.gl Heatmap Visualization (#23551)
This commit is contained in:
parent
febc07aec3
commit
fc8c537118
|
|
@ -23180,7 +23180,8 @@
|
|||
"version": "8.8.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz",
|
||||
"integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==",
|
||||
"devOptional": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
|
|
@ -23196,7 +23197,8 @@
|
|||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"devOptional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/ajv-keywords": {
|
||||
"version": "3.5.2",
|
||||
|
|
@ -23764,6 +23766,7 @@
|
|||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/aphrodite/-/aphrodite-1.2.5.tgz",
|
||||
"integrity": "sha1-g1jDbIC7A67puXFlqqcBhiJbSYM=",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"asap": "^2.0.3",
|
||||
"inline-style-prefixer": "^3.0.1",
|
||||
|
|
@ -25363,7 +25366,8 @@
|
|||
"node_modules/bowser": {
|
||||
"version": "1.9.4",
|
||||
"resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz",
|
||||
"integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ=="
|
||||
"integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/boxen": {
|
||||
"version": "5.1.2",
|
||||
|
|
@ -28259,6 +28263,7 @@
|
|||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz",
|
||||
"integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"hyphenate-style-name": "^1.0.2",
|
||||
"isobject": "^3.0.1"
|
||||
|
|
@ -36631,7 +36636,8 @@
|
|||
"node_modules/hyphenate-style-name": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
|
||||
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
|
||||
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
|
|
@ -37065,6 +37071,7 @@
|
|||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-3.0.8.tgz",
|
||||
"integrity": "sha1-hVG45bTVcyROZqNLBPfTIHaitTQ=",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"bowser": "^1.7.3",
|
||||
"css-in-js-utils": "^2.0.0"
|
||||
|
|
@ -54252,7 +54259,8 @@
|
|||
"node_modules/string-hash": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz",
|
||||
"integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs="
|
||||
"integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/string-length": {
|
||||
"version": "4.0.1",
|
||||
|
|
@ -64788,7 +64796,6 @@
|
|||
"@vx/scale": "0.0.140",
|
||||
"@vx/shape": "0.0.140",
|
||||
"@vx/tooltip": "0.0.140",
|
||||
"aphrodite": "^1.2.0",
|
||||
"d3-array": "^1.2.0",
|
||||
"d3-format": "^1.2.0",
|
||||
"d3-selection": "^1.1.0",
|
||||
|
|
@ -80581,15 +80588,13 @@
|
|||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
|
||||
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
|
||||
"devOptional": true,
|
||||
"requires": {
|
||||
"ajv": "^8.0.0"
|
||||
},
|
||||
"requires": {},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "8.8.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz",
|
||||
"version": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz",
|
||||
"integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==",
|
||||
"devOptional": true,
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
|
|
@ -80601,7 +80606,8 @@
|
|||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"devOptional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -81032,6 +81038,7 @@
|
|||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/aphrodite/-/aphrodite-1.2.5.tgz",
|
||||
"integrity": "sha1-g1jDbIC7A67puXFlqqcBhiJbSYM=",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"asap": "^2.0.3",
|
||||
"inline-style-prefixer": "^3.0.1",
|
||||
|
|
@ -82267,7 +82274,8 @@
|
|||
"bowser": {
|
||||
"version": "1.9.4",
|
||||
"resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz",
|
||||
"integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ=="
|
||||
"integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==",
|
||||
"peer": true
|
||||
},
|
||||
"boxen": {
|
||||
"version": "5.1.2",
|
||||
|
|
@ -84567,6 +84575,7 @@
|
|||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz",
|
||||
"integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"hyphenate-style-name": "^1.0.2",
|
||||
"isobject": "^3.0.1"
|
||||
|
|
@ -90958,7 +90967,8 @@
|
|||
"hyphenate-style-name": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
|
||||
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
|
||||
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==",
|
||||
"peer": true
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
|
|
@ -91276,6 +91286,7 @@
|
|||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-3.0.8.tgz",
|
||||
"integrity": "sha1-hVG45bTVcyROZqNLBPfTIHaitTQ=",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"bowser": "^1.7.3",
|
||||
"css-in-js-utils": "^2.0.0"
|
||||
|
|
@ -101671,8 +101682,7 @@
|
|||
"integrity": "sha512-JZUw7hBsAHXK7PTyErJyI7SopSBFRcFHDjWW5SWjcugY0i6iH7f+eJkY8cJmGMlZ1C9xz1J3Vjz0plFpavVeRg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.2.0",
|
||||
"invariant": "^2.2.4",
|
||||
"prop-types": "^15.5.7"
|
||||
"invariant": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"react-split": {
|
||||
|
|
@ -104476,7 +104486,8 @@
|
|||
"string-hash": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz",
|
||||
"integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs="
|
||||
"integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=",
|
||||
"peer": true
|
||||
},
|
||||
"string-length": {
|
||||
"version": "4.0.1",
|
||||
|
|
@ -108266,8 +108277,6 @@
|
|||
"is-scoped": "^2.1.0",
|
||||
"lodash": "^4.17.10",
|
||||
"log-symbols": "^4.0.0",
|
||||
"mem-fs": "^1.2.0 || ^2.0.0",
|
||||
"mem-fs-editor": "^8.1.2 || ^9.0.0",
|
||||
"minimatch": "^3.0.4",
|
||||
"npmlog": "^5.0.1",
|
||||
"p-queue": "^6.6.2",
|
||||
|
|
|
|||
|
|
@ -218,6 +218,11 @@ const schemes = [
|
|||
isDiverging: false,
|
||||
colors: ['#f6EFA6', '#D88273', '#BF444C'],
|
||||
},
|
||||
{
|
||||
id: 'deck_gl_heatmap_gradient',
|
||||
label: 'Deck.gl Heatmap Default',
|
||||
colors: ['#bd0026', '#f03b20', '#fd8d3c', '#feb24c', '#fed976', '#ffffb2'],
|
||||
},
|
||||
].map(s => new SequentialScheme(s));
|
||||
|
||||
export default schemes;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ type deckGLComponentProps = {
|
|||
viewport: Viewport;
|
||||
width: number;
|
||||
};
|
||||
interface getLayerType<T> {
|
||||
export interface getLayerType<T> {
|
||||
(
|
||||
formData: QueryFormData,
|
||||
payload: JsonObject,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { HeatmapLayer } from 'deck.gl';
|
||||
import React from 'react';
|
||||
import { t, getSequentialSchemeRegistry } from '@superset-ui/core';
|
||||
import { commonLayerProps } from '../common';
|
||||
import sandboxedEval from '../../utils/sandbox';
|
||||
import { hexToRGB } from '../../utils/colors';
|
||||
import { createDeckGLComponent, getLayerType } from '../../factory';
|
||||
import TooltipRow from '../../TooltipRow';
|
||||
|
||||
function setTooltipContent(o: any) {
|
||||
return (
|
||||
<div className="deckgl-tooltip">
|
||||
<TooltipRow
|
||||
label={t('Centroid (Longitude and Latitude): ')}
|
||||
value={`(${o.coordinate[0]}, ${o.coordinate[1]})`}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export const getLayer: getLayerType<unknown> = (
|
||||
formData,
|
||||
payload,
|
||||
onAddFilter,
|
||||
setTooltip,
|
||||
) => {
|
||||
const fd = formData;
|
||||
const {
|
||||
intensity = 1,
|
||||
radius_pixels: radiusPixels = 30,
|
||||
aggregation = 'SUM',
|
||||
js_data_mutator: jsFnMutator,
|
||||
linear_color_scheme: colorScheme,
|
||||
} = fd;
|
||||
let data = payload.data.features;
|
||||
|
||||
if (jsFnMutator) {
|
||||
// Applying user defined data mutator if defined
|
||||
const jsFnMutatorFunction = sandboxedEval(fd.js_data_mutator);
|
||||
data = jsFnMutatorFunction(data);
|
||||
}
|
||||
|
||||
const colorScale = getSequentialSchemeRegistry()
|
||||
?.get(colorScheme)
|
||||
?.createLinearScale([0, 6]);
|
||||
const colorRange = colorScale
|
||||
?.range()
|
||||
?.map(color => hexToRGB(color))
|
||||
?.reverse();
|
||||
|
||||
return new HeatmapLayer({
|
||||
id: `heatmp-layer-${fd.slice_id}`,
|
||||
data,
|
||||
intensity,
|
||||
radiusPixels,
|
||||
colorRange,
|
||||
aggregation: aggregation.toUpperCase(),
|
||||
getPosition: (d: { position: number[]; weight: number }) => d.position,
|
||||
getWeight: (d: { position: number[]; weight: number }) =>
|
||||
d.weight ? d.weight : 1,
|
||||
...commonLayerProps(fd, setTooltip, setTooltipContent),
|
||||
});
|
||||
};
|
||||
|
||||
function getPoints(data: any[]) {
|
||||
return data.map(d => d.position);
|
||||
}
|
||||
|
||||
export default createDeckGLComponent(getLayer, getPoints);
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
ControlPanelConfig,
|
||||
sections,
|
||||
formatSelectOptions,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import {
|
||||
t,
|
||||
validateNonEmpty,
|
||||
legacyValidateNumber,
|
||||
legacyValidateInteger,
|
||||
} from '@superset-ui/core';
|
||||
import {
|
||||
autozoom,
|
||||
filterNulls,
|
||||
jsColumns,
|
||||
jsDataMutator,
|
||||
jsOnclickHref,
|
||||
jsTooltip,
|
||||
mapboxStyle,
|
||||
spatial,
|
||||
viewport,
|
||||
} from '../../utilities/Shared_DeckGL';
|
||||
|
||||
const INTENSITY_OPTIONS = Array.from(
|
||||
{ length: 10 },
|
||||
(_, index) => (index + 1) / 10,
|
||||
);
|
||||
const RADIUS_PIXEL_OPTIONS = Array.from(
|
||||
{ length: 14 },
|
||||
(_, index) => index * 5 + 5,
|
||||
);
|
||||
|
||||
const config: ControlPanelConfig = {
|
||||
controlPanelSections: [
|
||||
sections.legacyRegularTime,
|
||||
{
|
||||
label: t('Query'),
|
||||
expanded: true,
|
||||
controlSetRows: [
|
||||
[spatial],
|
||||
['size'],
|
||||
['row_limit'],
|
||||
[filterNulls],
|
||||
['adhoc_filters'],
|
||||
[
|
||||
{
|
||||
name: 'intensity',
|
||||
config: {
|
||||
type: 'SelectControl',
|
||||
label: t('Intesity'),
|
||||
description: t(
|
||||
'Intensity is the value multiplied by the weight to obtain the final weight',
|
||||
),
|
||||
freeForm: true,
|
||||
clearable: false,
|
||||
validators: [legacyValidateNumber],
|
||||
default: 1,
|
||||
choices: formatSelectOptions(INTENSITY_OPTIONS),
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
name: 'radius_pixels',
|
||||
config: {
|
||||
type: 'SelectControl',
|
||||
label: t('Intensity Radius'),
|
||||
description: t(
|
||||
'Intensity Radius is the radius at which the weight is distributed',
|
||||
),
|
||||
freeForm: true,
|
||||
clearable: false,
|
||||
validators: [legacyValidateInteger],
|
||||
default: 30,
|
||||
choices: formatSelectOptions(RADIUS_PIXEL_OPTIONS),
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
label: t('Map'),
|
||||
controlSetRows: [
|
||||
[mapboxStyle, viewport],
|
||||
['linear_color_scheme'],
|
||||
[autozoom],
|
||||
[
|
||||
{
|
||||
name: 'aggregation',
|
||||
config: {
|
||||
type: 'SelectControl',
|
||||
label: t('Aggregation'),
|
||||
description: t(
|
||||
'The function to use when aggregating points into groups',
|
||||
),
|
||||
default: 'sum',
|
||||
clearable: false,
|
||||
renderTrigger: true,
|
||||
choices: [
|
||||
['sum', t('sum')],
|
||||
['mean', t('mean')],
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
label: t('Advanced'),
|
||||
controlSetRows: [
|
||||
[jsColumns],
|
||||
[jsDataMutator],
|
||||
[jsTooltip],
|
||||
[jsOnclickHref],
|
||||
],
|
||||
},
|
||||
],
|
||||
controlOverrides: {
|
||||
size: {
|
||||
label: t('Weight'),
|
||||
description: t("Metric used as a weight for the grid's coloring"),
|
||||
validators: [validateNonEmpty],
|
||||
},
|
||||
},
|
||||
formDataOverrides: formData => ({
|
||||
...formData,
|
||||
}),
|
||||
};
|
||||
|
||||
export default config;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 658 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 658 KiB |
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { t, ChartMetadata, ChartPlugin } from '@superset-ui/core';
|
||||
import transformProps from '../../transformProps';
|
||||
import controlPanel from './controlPanel';
|
||||
import thumbnail from './images/thumbnail.png';
|
||||
|
||||
const metadata = new ChartMetadata({
|
||||
category: t('Map'),
|
||||
credits: ['https://uber.github.io/deck.gl'],
|
||||
description: t(
|
||||
'Uses Gaussian Kernel Density Estimation to visualize spatial distribution of data',
|
||||
),
|
||||
name: t('deck.gl Heatmap'),
|
||||
thumbnail,
|
||||
useLegacyApi: true,
|
||||
tags: [t('deckGL'), t('Spatial'), t('Comparison'), t('Experimental')],
|
||||
});
|
||||
|
||||
export default class HeatmapChartPlugin extends ChartPlugin {
|
||||
constructor() {
|
||||
super({
|
||||
loadChart: () => import('./Heatmap'),
|
||||
controlPanel,
|
||||
metadata,
|
||||
transformProps,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ import ArcChartPlugin from './layers/Arc';
|
|||
import GeoJsonChartPlugin from './layers/Geojson';
|
||||
import GridChartPlugin from './layers/Grid';
|
||||
import HexChartPlugin from './layers/Hex';
|
||||
import HeatmapChartPlugin from './layers/Heatmap';
|
||||
import MultiChartPlugin from './Multi';
|
||||
import PathChartPlugin from './layers/Path';
|
||||
import PolygonChartPlugin from './layers/Polygon';
|
||||
|
|
@ -36,6 +37,7 @@ export default class DeckGLChartPreset extends Preset {
|
|||
new GeoJsonChartPlugin().configure({ key: 'deck_geojson' }),
|
||||
new GridChartPlugin().configure({ key: 'deck_grid' }),
|
||||
new HexChartPlugin().configure({ key: 'deck_hex' }),
|
||||
new HeatmapChartPlugin().configure({ key: 'deck_heatmap' }),
|
||||
new MultiChartPlugin().configure({ key: 'deck_multi' }),
|
||||
new PathChartPlugin().configure({ key: 'deck_path' }),
|
||||
new PolygonChartPlugin().configure({ key: 'deck_polygon' }),
|
||||
|
|
|
|||
|
|
@ -17,3 +17,31 @@
|
|||
* under the License.
|
||||
*/
|
||||
declare module '@math.gl/web-mercator';
|
||||
|
||||
declare module 'deck.gl' {
|
||||
import { Layer, LayerProps } from '@deck.gl/core';
|
||||
|
||||
interface HeatmapLayerProps<T extends object = any> extends LayerProps<T> {
|
||||
id?: string;
|
||||
data?: T[];
|
||||
getPosition?: (d: T) => number[] | null | undefined;
|
||||
getWeight?: (d: T) => number | null | undefined;
|
||||
radiusPixels?: number;
|
||||
colorRange?: number[][];
|
||||
threshold?: number;
|
||||
intensity?: number;
|
||||
aggregation?: string;
|
||||
}
|
||||
|
||||
export class HeatmapLayer<T extends object = any> extends Layer<
|
||||
T,
|
||||
HeatmapLayerProps<T>
|
||||
> {
|
||||
constructor(props: HeatmapLayerProps<T>);
|
||||
}
|
||||
}
|
||||
|
||||
declare module '*.png' {
|
||||
const value: any;
|
||||
export default value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2988,6 +2988,27 @@ class DeckHex(BaseDeckGLViz):
|
|||
return super().get_data(df)
|
||||
|
||||
|
||||
class DeckHeatmap(BaseDeckGLViz):
|
||||
|
||||
"""deck.gl's HeatmapLayer"""
|
||||
|
||||
viz_type = "deck_heatmap"
|
||||
verbose_name = _("Deck.gl - Heatmap")
|
||||
spatial_control_keys = ["spatial"]
|
||||
|
||||
def get_properties(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
return {
|
||||
"position": data.get("spatial"),
|
||||
"weight": (data.get(self.metric_label) if self.metric_label else None) or 1,
|
||||
}
|
||||
|
||||
def get_data(self, df: pd.DataFrame) -> VizData:
|
||||
self.metric_label = ( # pylint: disable=attribute-defined-outside-init
|
||||
utils.get_metric_name(self.metric) if self.metric else None
|
||||
)
|
||||
return super().get_data(df)
|
||||
|
||||
|
||||
class DeckGeoJson(BaseDeckGLViz):
|
||||
|
||||
"""deck.gl's GeoJSONLayer"""
|
||||
|
|
|
|||
Loading…
Reference in New Issue