Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map: add 3D terrain control when user tilts #184

Merged
merged 2 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"js-cookie": "^2.2.1",
"jss": "^10.6.0",
"lodash": "^4.17.21",
"maplibre-gl": "^1.14.0",
"maplibre-gl": "^3.3.1",
"next": "^13.4.3",
"next-cookies": "^2.0.3",
"next-pwa": "^5.2.21",
Expand Down
4 changes: 2 additions & 2 deletions src/components/FeaturePanel/Coordinates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ const LinkItem = ({ href, label }) => (

// Our map uses 512 tiles, so our zoom is "one less"
// https://wiki.openstreetmap.org/wiki/Zoom_levels#Mapbox_GL
const MAPBOXGL_ZOOM_DIFFERENCE = 1;
const MAPLIBREGL_ZOOM_DIFFERENCE = 1;

const useGetItems = ([lon, lat]: PositionBoth) => {
const { feature } = useFeatureContext();
const { view } = useMapStateContext();
const [ourZoom] = view;

const zoom = parseFloat(ourZoom) + MAPBOXGL_ZOOM_DIFFERENCE;
const zoom = parseFloat(ourZoom) + MAPLIBREGL_ZOOM_DIFFERENCE;
const zoomInt = Math.round(zoom);
const osmQuery = feature?.osmMeta?.id
? `${feature.osmMeta.type}/${feature.osmMeta.id}`
Expand Down
6 changes: 4 additions & 2 deletions src/components/Map/BrowserMap.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react';
import 'maplibre-gl/dist/maplibre-gl.css';
import maplibregl from 'maplibre-gl';
import { useAddMapEvent, useMapEffect, useMobileMode } from '../helpers';
import { useMapStateContext } from '../utils/MapStateContext';
import { useFeatureContext } from '../utils/FeatureContext';
Expand All @@ -10,6 +9,8 @@ import { useUpdateViewOnMove } from './behaviour/useUpdateViewOnMove';
import { useUpdateStyle } from './behaviour/useUpdateStyle';
import { useInitMap } from './behaviour/useInitMap';
import { Translation } from '../../services/intl';
import { useToggleTerrainControl } from './behaviour/useToggleTerrainControl';
import { isWebglSupported } from './helpers';

const useOnMapLoaded = useAddMapEvent((map, onMapLoaded) => ({
eventType: 'load',
Expand All @@ -32,7 +33,7 @@ const NotSupportedMessage = () => (
// TODO https://cdn.klokantech.com/openmaptiles-language/v1.0/openmaptiles-language.js + use localized name in FeaturePanel

const BrowserMap = ({ onMapLoaded }) => {
if (!maplibregl.supported()) {
if (!isWebglSupported()) {
onMapLoaded();
return <NotSupportedMessage />;
}
Expand All @@ -46,6 +47,7 @@ const BrowserMap = ({ onMapLoaded }) => {
const { viewForMap, setViewFromMap, setBbox, activeLayers } =
useMapStateContext();
useUpdateViewOnMove(map, setViewFromMap, setBbox);
useToggleTerrainControl(map);
useUpdateMap(map, viewForMap);
useUpdateStyle(map, activeLayers);

Expand Down
38 changes: 38 additions & 0 deletions src/components/Map/behaviour/useToggleTerrainControl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* eslint-disable no-underscore-dangle */
import maplibregl from 'maplibre-gl';
import { useAddMapEvent } from '../../helpers';

class OsmappTerrainControl extends maplibregl.TerrainControl {
_toggleTerrain = () => {
if (this._map.getTerrain()) {
this._map.setTerrain(null);
this._map.setMaxPitch(60);
} else {
this._map.setTerrain(this.options);
this._map.setMaxPitch(85);
}
this._updateTerrainIcon();
};
}

const terrainControl = new OsmappTerrainControl({
source: 'terrain',
exaggeration: 1,
});

let added = false;

export const useToggleTerrainControl = useAddMapEvent((map) => ({
eventType: 'move',
eventHandler: () => {
if (map.getPitch() > 0) {
if (!added) {
map.addControl(terrainControl);
added = true;
}
} else if (added) {
map.removeControl(terrainControl);
added = false;
}
},
}));
6 changes: 6 additions & 0 deletions src/components/Map/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ export const OSMAPP_SOURCES = {
'terrain-rgb': {
url: `https://api.maptiler.com/tiles/terrain-rgb/tiles.json?key=${apiKey}`,
type: 'raster-dem' as const,
tileSize: 256,
},
terrain: {
url: `https://api.maptiler.com/tiles/terrain-rgb/tiles.json?key=${apiKey}`,
type: 'raster-dem' as const,
tileSize: 256,
},
outdoor: {
url: `https://api.maptiler.com/tiles/outdoor/tiles.json?key=${apiKey}`,
Expand Down
23 changes: 23 additions & 0 deletions src/components/Map/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,26 @@ export const convertOsmIdToMapId = (apiId: OsmApiId) => {
const osmToMapType = { node: 0, way: 1, relation: 4 };
return parseInt(`${apiId.id}${osmToMapType[apiId.type]}`, 10);
};

// maplibregl.supported() no longer exists
// copied from https://maplibre.org/maplibre-gl-js/docs/examples/check-for-support/
export const isWebglSupported = () => {
if (window.WebGLRenderingContext) {
const canvas = document.createElement('canvas');
try {
// Note that { failIfMajorPerformanceCaveat: true } can be passed as a second argument
// to canvas.getContext(), causing the check to fail if hardware rendering is not available. See
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext
// for more details.
const context = canvas.getContext('webgl2') || canvas.getContext('webgl');
if (context && typeof context.getParameter === 'function') {
return true;
}
} catch (e) {
// WebGL is supported, but disabled
}
return false;
}
// WebGL not supported
return false;
};
4 changes: 2 additions & 2 deletions src/components/Map/styles/rasterStyle.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import maplibregl from 'maplibre-gl';
import type { StyleSpecification } from '@maplibre/maplibre-gl-style-spec';
import { GLYPHS, OSMAPP_SOURCES, OSMAPP_SPRITE } from '../consts';

const getSource = (url) => {
Expand All @@ -21,7 +21,7 @@ const getSource = (url) => {
};
};

export const rasterStyle = (id, url): maplibregl.Style => {
export const rasterStyle = (id, url): StyleSpecification => {
const source = getSource(url);
return {
version: 8,
Expand Down
8 changes: 4 additions & 4 deletions src/helpers/GlobalStyle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,25 @@ export const GlobalStyle = createGlobalStyle`
margin-top: 0;
}

.mapboxgl-ctrl-group {
.maplibregl-ctrl-group {
background: ${({ theme }) => theme.palette.background.default} !important;
.mapboxgl-ctrl-icon {
.maplibregl-ctrl-icon {
filter: ${({ theme }) => theme.palette.invertFilter};
}
button+button {
border-top: 1px solid ${({ theme }) => theme.palette.divider};
}
}

.mapboxgl-ctrl-top-right {
.maplibregl-ctrl-top-right {
top: ${83 + 72}px !important;

@media ${isDesktop} {
top: 83px !important;
}
}

.mapboxgl-canvas:not(:focus) {
.maplibregl-canvas:not(:focus) {
outline: 0;
}

Expand Down
2 changes: 1 addition & 1 deletion src/services/__tests__/osmApi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jest.mock('next/config', () => () => ({
describe('fetchFeature', () => {
beforeEach(() => {
jest.clearAllMocks();
jest.spyOn(tagging, 'fetchSchemaTranslations').mockResolvedValue(true);
jest.spyOn(tagging, 'fetchSchemaTranslations').mockResolvedValue(undefined);
jest
.spyOn(idTaggingScheme, 'getSchemaForFeature')
.mockReturnValue(undefined); // this is covered in idTaggingScheme.test.ts
Expand Down
Loading