diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index c90b00a6..78eee41a 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -4,6 +4,7 @@ on: push: branches: - 'master' + - 'terrain_3d' tags: - 'v*' diff --git a/package-lock.json b/package-lock.json index 5284cbed..059d8a2c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "dependencies": { "@mapbox/mapbox-gl-rtl-text": "^0.2.3", "@qwant/map-style-builder": "github:Qwant/map-style-builder#81eebb0", - "@qwant/qwant-basic-gl-style": "^1.5.2", + "@qwant/qwant-basic-gl-style": "1.6.5", "@qwant/qwant-ponents": "^0.2.8", "@turf/along": "^6.0.1", "@turf/bbox": "^6.0.1", @@ -4425,9 +4425,9 @@ "link": true }, "node_modules/@qwant/qwant-basic-gl-style": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@qwant/qwant-basic-gl-style/-/qwant-basic-gl-style-1.6.1.tgz", - "integrity": "sha512-TyEFuHbsoedFr3qrX1P1+CNnR4GSJLmYxBwOt0Xm+zTR0M30R5s+UCMFvUOmbjaE4fFFcPy5sMziOcUNPBxeNQ==" + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@qwant/qwant-basic-gl-style/-/qwant-basic-gl-style-1.6.5.tgz", + "integrity": "sha512-PEnkySZFHqhMjxmvq7Tokh/BpFbhzgFNON2GRShYCKSmFc2lbfJen0IkRqqbTMV3Jem6kwmGoceGtjwzJo1dGg==" }, "node_modules/@qwant/qwant-maps-common": { "resolved": "local_modules/qwant-maps-common", @@ -36083,9 +36083,9 @@ "version": "file:local_modules/po-js-loader" }, "@qwant/qwant-basic-gl-style": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@qwant/qwant-basic-gl-style/-/qwant-basic-gl-style-1.6.1.tgz", - "integrity": "sha512-TyEFuHbsoedFr3qrX1P1+CNnR4GSJLmYxBwOt0Xm+zTR0M30R5s+UCMFvUOmbjaE4fFFcPy5sMziOcUNPBxeNQ==" + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@qwant/qwant-basic-gl-style/-/qwant-basic-gl-style-1.6.5.tgz", + "integrity": "sha512-PEnkySZFHqhMjxmvq7Tokh/BpFbhzgFNON2GRShYCKSmFc2lbfJen0IkRqqbTMV3Jem6kwmGoceGtjwzJo1dGg==" }, "@qwant/qwant-maps-common": { "version": "file:local_modules/qwant-maps-common", diff --git a/package.json b/package.json index f7a0e297..37c39bc3 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "dependencies": { "@mapbox/mapbox-gl-rtl-text": "^0.2.3", "@qwant/map-style-builder": "github:Qwant/map-style-builder#81eebb0", - "@qwant/qwant-basic-gl-style": "^1.5.2", + "@qwant/qwant-basic-gl-style": "^1.6.5", "@qwant/qwant-ponents": "^0.2.8", "@turf/along": "^6.0.1", "@turf/bbox": "^6.0.1", diff --git a/src/adapters/scene.js b/src/adapters/scene.js index 16c17c42..4201ee48 100644 --- a/src/adapters/scene.js +++ b/src/adapters/scene.js @@ -319,8 +319,8 @@ Scene.prototype.initMapBox = function ({ locationHash, bbox }) { this.addMarkerMapillary(coord); }); - listen('change_camera_orientation', pov => { - this.updateCameraOrientation(pov); + listen('change_camera_orientation', bearing => { + this.updateCameraOrientation(bearing); }); listen('clean_marker', () => { @@ -598,9 +598,9 @@ function makeCamera(bearing, fov) { return container; } -Scene.prototype.updateCameraOrientation = function (pov) { +Scene.prototype.updateCameraOrientation = function (bearing) { const svg = this.camera.querySelector('svg'); - svg.style.transform = rotateArc(pov.bearing); + svg.style.transform = rotateArc(bearing); }; Scene.prototype.cleanMarker = async function () { diff --git a/src/components/TopBar/TopBar.jsx b/src/components/TopBar/TopBar.jsx index 6fc7936f..f5ee1f15 100644 --- a/src/components/TopBar/TopBar.jsx +++ b/src/components/TopBar/TopBar.jsx @@ -30,8 +30,8 @@ const TopBar = ({ value, setUserInputValue, inputRef, onSuggestToggle, backButto isMenuDrawerOpen, setMenuDrawerOpen, isMapillaryLayerVisible, - setMapillaryLayerVisible, isMapillaryViewerOpen, + setMapillaryLayerVisible, setMapillaryViewerOpen, isProductsDrawerOpen, setProductsDrawerOpen, @@ -208,7 +208,9 @@ const TopBar = ({ value, setUserInputValue, inputRef, onSuggestToggle, backButto })} onClick={() => { setMapillaryLayerVisible(!isMapillaryLayerVisible); - setMapillaryViewerOpen(!isMapillaryViewerOpen); + if (isMapillaryViewerOpen) { + setMapillaryViewerOpen(false); + } }} title={_('Mapillary')} > diff --git a/src/mapbox/extended_nav_control.js b/src/mapbox/extended_nav_control.js index 718c7718..af87c25b 100644 --- a/src/mapbox/extended_nav_control.js +++ b/src/mapbox/extended_nav_control.js @@ -2,6 +2,7 @@ import React from 'react'; import ExtendedScaleControl from './extended_scale_control'; import ExtendedAttributionControl from './extended_attribution_control'; import GeolocControl from './extended_geolocate_control'; +import ExtendedTerrainControl from './extended_terrain_control'; import Telemetry from 'src/libs/telemetry'; import { listen, unListen } from '../libs/customEvents'; import renderStaticReact from 'src/libs/renderStaticReact'; @@ -80,8 +81,17 @@ export default class ExtendedControl { this.bottomButtonGroup.appendChild(this._zoomOutButton); }); - this._map.addControl(geolocControl); + const terrainControl = new ExtendedTerrainControl( + { + source: 'terrainSource', + exaggeration: 1, + }, + this.bottomButtonGroup, + this._map + ); + this._map.addControl(geolocControl); + this._map.addControl(terrainControl); const _pitchAndRotateCompassArrow = this._pitchAndRotateCompassArrow.bind(this); _pitchAndRotateCompassArrow(); @@ -106,8 +116,8 @@ export default class ExtendedControl { ); this._container.appendChild(this.topButtonGroup); this._container.appendChild(this.bottomButtonGroup); - this._container.appendChild(this.scaleAttributionContainer); + this._map.addControl(extendedScaleControl, 'bottom-right'); this._map.addControl(extendedAttributionControl, 'bottom-right'); return this._container; diff --git a/src/mapbox/extended_terrain_control.js b/src/mapbox/extended_terrain_control.js new file mode 100644 index 00000000..4d100526 --- /dev/null +++ b/src/mapbox/extended_terrain_control.js @@ -0,0 +1,33 @@ +import { TerrainControl } from 'maplibre-gl'; + +/** + * Override default TerrainControl + */ + +export default class ExtendedTerrainControl extends TerrainControl { + constructor(options, container, map) { + super(options); + this.parentContainer = container; + this.visible = false; + this.map = map; + } + + onAdd(map) { + const container = super.onAdd(map); + if (container) { + this.parentContainer.appendChild(container); + } + return this.parentContainer; + } + + _toggleTerrain() { + if (this.visible) { + this.visible = false; + this.map.setLayoutProperty('hills', 'visibility', 'none'); + } else { + this.visible = true; + this.map.setLayoutProperty('hills', 'visibility', 'visible'); + } + super._toggleTerrain(); + } +} diff --git a/src/panel/Mapillary.tsx b/src/panel/Mapillary.tsx index 20285015..9f9df871 100644 --- a/src/panel/Mapillary.tsx +++ b/src/panel/Mapillary.tsx @@ -3,8 +3,7 @@ import ViewerComponent from 'src/panel/MapillaryViewer'; import { CloseButton } from 'src/components/ui'; import { Flex } from '@qwant/qwant-ponents'; import { useStore } from 'src/store'; -import { fire, listen, unListen } from 'src/libs/customEvents'; -import { Viewer } from 'mapillary-js'; +import { listen, unListen } from 'src/libs/customEvents'; let viewer; const Mapillary = () => { @@ -27,36 +26,6 @@ const Mapillary = () => { const mapillaryListener = listen('set_mapillary_viewer', setMapillaryViewer); - function init(opts) { - const { accessToken, container } = opts; - const viewerOptions = { - accessToken, - component: { - cover: false, - }, - container, - }; - viewer = new Viewer(viewerOptions); - viewer.moveTo(mapillaryImageId).catch(error => console.warn(error)); - const onPov = async () => { - const pov = await viewer.getPointOfView(); - fire('change_camera_orientation', pov); - }; - const onPosition = async () => { - const position = await viewer.getPosition(); - const pos = [position.lng, position.lat]; - fire('create_mapillary_marker', pos); - }; - viewer.on('position', onPosition); - viewer.on('pov', onPov); - } - - function dispose() { - if (viewer) { - viewer.remove(); - } - } - return (
{isMapillaryViewerOpen && ( @@ -68,11 +37,7 @@ const Mapillary = () => { className="menu-top-close-button" /> - +
)} diff --git a/src/panel/MapillaryViewer.jsx b/src/panel/MapillaryViewer.jsx index 3721ed4c..d4de383e 100644 --- a/src/panel/MapillaryViewer.jsx +++ b/src/panel/MapillaryViewer.jsx @@ -1,4 +1,6 @@ import React from 'react'; +import { Viewer } from 'mapillary-js'; +import { fire } from 'src/libs/customEvents'; class ViewerComponent extends React.Component { constructor(props) { @@ -7,16 +9,37 @@ class ViewerComponent extends React.Component { } componentDidMount() { - const { init } = this.props; - init({ + this.viewer = new Viewer({ accessToken: 'MLY|4100327730013843|5bb78b81720791946a9a7b956c57b7cf', container: this.containerRef.current, + component: { cover: false }, + imageId: this.props.imageId, }); } + componentDidUpdate(prevProps) { + if (prevProps.imageId !== this.props.imageId) { + if (this.viewer) { + this.viewer.moveTo(this.props.imageId); + } + } + const onBearing = async () => { + const bearing = await this.viewer.getBearing(); + fire('change_camera_orientation', bearing); + }; + const onPosition = async () => { + const position = await this.viewer.getPosition(); + const pos = [position.lng, position.lat]; + fire('create_mapillary_marker', pos); + }; + this.viewer.on('position', onPosition); + this.viewer.on('bearing', onBearing); + } + componentWillUnmount() { - const { dispose } = this.props; - dispose(); + if (this.viewer) { + this.viewer.remove(); + } } render() {