geosphere-maps/app/[locale]/layer-list.tsx

156 lines
4.5 KiB
TypeScript

import { useRef, useEffect, RefObject } from 'react';
import { useTranslation } from 'react-i18next';
import initI18n from './i18n';
import MapView from '@arcgis/core/views/MapView';
import LayerList from '@arcgis/core/widgets/LayerList';
import FeatureTable from '@arcgis/core/widgets/FeatureTable';
import ImageryTileLayer from '@arcgis/core/layers/ImageryTileLayer';
import MapImageLayer from '@arcgis/core/layers/MapImageLayer';
import Sublayer from '@arcgis/core/layers/support/Sublayer';
import ButtonMenuItem from '@arcgis/core/widgets/FeatureTable/Grid/support/ButtonMenuItem';
// load localized strings
const match = location.pathname.match(/\/(\w+)/);
if (match && match.length > 1) {
const locale = match[1];
initI18n(locale);
}
export default function Layers({ view, tableRoot }: { view: MapView; tableRoot: RefObject<HTMLDivElement> }) {
const htmlDiv = useRef<HTMLDivElement>(null);
const featureTable = useRef<FeatureTable | null>(null);
const rendered = useRef<boolean>(false);
const { t } = useTranslation();
useEffect(() => {
if (rendered.current) return;
rendered.current = true;
const createTable = async (layer: Sublayer, view: MapView) => {
const tableContainer = document.createElement('div');
tableContainer.className = 'h-full w-full';
if (tableRoot && tableRoot.current) {
tableRoot.current.classList.remove('hidden');
tableRoot.current.append(tableContainer);
}
const featureLayer = await layer.createFeatureLayer();
featureTable.current = new FeatureTable({
view: view,
layer: featureLayer,
container: tableContainer,
menuConfig: {
items: [
{
label: t('layers.table.close'),
iconClass: 'esri-icon-close',
clickFunction: function () {
featureTable.current?.destroy();
if (tableRoot && tableRoot.current) {
tableRoot.current.classList.add('hidden');
}
},
} as unknown as ButtonMenuItem,
],
},
});
};
if (htmlDiv.current) {
const arcGISAPIWidgetContainer = document.createElement('div');
htmlDiv.current.append(arcGISAPIWidgetContainer);
const layerList = new LayerList({
view,
container: htmlDiv.current,
selectionEnabled: true,
listItemCreatedFunction: async function (event) {
const item = event.item;
const type = item.layer.type;
if (type === 'imagery-tile' || type === 'map-image') {
item.actionsSections = [
[
{
title: 'Info',
className: 'esri-icon-description',
id: 'info',
},
],
[
{
title: t('layers.increaseOpacity'),
className: 'esri-icon-up',
id: 'increase-opacity',
},
{
title: t('layers.decreaseOpacity'),
className: 'esri-icon-down',
id: 'decrease-opacity',
},
],
];
}
if (item.layer.declaredClass === 'esri.layers.support.Sublayer') {
item.actionsSections = [
[
{
title: 'Table',
className: 'esri-icon-table',
id: 'table',
},
],
];
}
},
});
layerList.on('trigger-action', async (event) => {
const id = event.action.id;
const item = event.item;
const layer = item.layer;
const type = layer.type;
if (id === 'info') {
if (type === 'imagery-tile') {
window.open((layer as ImageryTileLayer).portalItem?.itemPageUrl);
}
if (type === 'map-image') {
window.open((layer as MapImageLayer).portalItem?.itemPageUrl);
}
}
if (id === 'increase-opacity') {
if (layer.opacity < 1) {
layer.opacity += 0.25;
}
}
if (id === 'decrease-opacity') {
if (layer.opacity > 0) {
layer.opacity -= 0.25;
}
}
if (id === 'table') {
featureTable.current?.destroy();
try {
createTable(layer as unknown as Sublayer, view);
} catch (error) {}
}
});
}
return () => {};
});
return <div ref={htmlDiv}></div>;
}