diff --git a/packages/ripple-ui-core/src/components/icon/constants.ts b/packages/ripple-ui-core/src/components/icon/constants.ts index 24d59806e3..f7b85f73d3 100644 --- a/packages/ripple-ui-core/src/components/icon/constants.ts +++ b/packages/ripple-ui-core/src/components/icon/constants.ts @@ -85,7 +85,8 @@ export const RplIconGroups = { 'icon-view', 'icon-zoom-in', 'icon-zoom-out' - ] + ], + map: ['icon-enlarge', 'icon-map-zoom-in', 'icon-map-zoom-out', 'icon-home'] } as const export default { diff --git a/packages/ripple-ui-core/src/components/icon/custom.js b/packages/ripple-ui-core/src/components/icon/custom.js index 633457e169..ab2b99c8a5 100644 --- a/packages/ripple-ui-core/src/components/icon/custom.js +++ b/packages/ripple-ui-core/src/components/icon/custom.js @@ -56,5 +56,9 @@ export default { 'icon-wechat': () => import('./custom/icon-wechat.svg?component'), 'icon-youtube': () => import('./custom/icon-youtube.svg?component'), 'icon-zoom-in': () => import('./custom/icon-zoom-in.svg?component'), - 'icon-zoom-out': () => import('./custom/icon-zoom-out.svg?component') + 'icon-zoom-out': () => import('./custom/icon-zoom-out.svg?component'), + 'icon-map-zoom-in': () => import('./custom/icon-map-zoom-in.svg?component'), + 'icon-map-zoom-out': () => import('./custom/icon-map-zoom-out.svg?component'), + 'icon-enlarge': () => import('./custom/icon-enlarge.svg?component'), + 'icon-home': () => import('./custom/icon-home.svg?component') } diff --git a/packages/ripple-ui-core/src/components/icon/custom/Icon-map-zoom-out.svg b/packages/ripple-ui-core/src/components/icon/custom/Icon-map-zoom-out.svg new file mode 100644 index 0000000000..7fec07a021 --- /dev/null +++ b/packages/ripple-ui-core/src/components/icon/custom/Icon-map-zoom-out.svg @@ -0,0 +1 @@ + diff --git a/packages/ripple-ui-core/src/components/icon/custom/icon-enlarge.svg b/packages/ripple-ui-core/src/components/icon/custom/icon-enlarge.svg new file mode 100644 index 0000000000..192d6552f6 --- /dev/null +++ b/packages/ripple-ui-core/src/components/icon/custom/icon-enlarge.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/ripple-ui-core/src/components/icon/custom/icon-home.svg b/packages/ripple-ui-core/src/components/icon/custom/icon-home.svg new file mode 100644 index 0000000000..ab9a70bc03 --- /dev/null +++ b/packages/ripple-ui-core/src/components/icon/custom/icon-home.svg @@ -0,0 +1 @@ + diff --git a/packages/ripple-ui-core/src/components/icon/custom/icon-map-zoom-in.svg b/packages/ripple-ui-core/src/components/icon/custom/icon-map-zoom-in.svg new file mode 100644 index 0000000000..843dda137f --- /dev/null +++ b/packages/ripple-ui-core/src/components/icon/custom/icon-map-zoom-in.svg @@ -0,0 +1 @@ + diff --git a/packages/ripple-ui-maps/src/components/map/RplMap.css b/packages/ripple-ui-maps/src/components/map/RplMap.css index 419e8b8a4f..913bf340f2 100644 --- a/packages/ripple-ui-maps/src/components/map/RplMap.css +++ b/packages/ripple-ui-maps/src/components/map/RplMap.css @@ -17,7 +17,7 @@ .rpl-map__control { position: absolute; right: var(--rpl-sp-2); - + z-index: var(--rpl-layer-1); @media (--rpl-bp-l) { right: var(--rpl-sp-3); } @@ -86,12 +86,12 @@ bottom: var(--rpl-sp-3); } - .ol-zoom-in { + .rpl-map__control-zoom-in { border-bottom-left-radius: 0; border-bottom-right-radius: 0; } - .ol-zoom-out { + .rpl-map__control-zoom-out { border-top-left-radius: 0; border-top-right-radius: 0; border-top: none; diff --git a/packages/ripple-ui-maps/src/components/map/RplMap.vue b/packages/ripple-ui-maps/src/components/map/RplMap.vue index 38329d7561..1116a34769 100644 --- a/packages/ripple-ui-maps/src/components/map/RplMap.vue +++ b/packages/ripple-ui-maps/src/components/map/RplMap.vue @@ -1,5 +1,6 @@ diff --git a/packages/ripple-ui-maps/src/composables/useMapControlLabel.ts b/packages/ripple-ui-maps/src/composables/useMapControlLabel.ts deleted file mode 100644 index 8a140150d8..0000000000 --- a/packages/ripple-ui-maps/src/composables/useMapControlLabel.ts +++ /dev/null @@ -1,12 +0,0 @@ -export default () => { - function createHTMLElementFromString(text: string): HTMLOrSVGElement { - const div = document.createElement('div') - div.innerHTML = text.trim() - const svg = div.firstElementChild - svg.setAttribute('fill', 'currentColor') - return svg - } - return { - createHTMLElementFromString - } -} diff --git a/packages/ripple-ui-maps/src/composables/useMapControls.ts b/packages/ripple-ui-maps/src/composables/useMapControls.ts new file mode 100644 index 0000000000..dc2d9157a3 --- /dev/null +++ b/packages/ripple-ui-maps/src/composables/useMapControls.ts @@ -0,0 +1,135 @@ +import { easeOut } from 'ol/easing' +import { centerMap } from './../components/map/utils.ts' +import { ref } from 'vue' +export default (mapRef, center, initialZoom) => { + const isFullScreenRef = ref(false) + + /** + * @param {number} delta Zoom delta. + * @private + */ + function zoomByDelta(delta, duration = 250) { + const view = mapRef.value.map.getView() + if (!view) { + // the map does not have a view, so we can't act + // upon it + return + } + const currentZoom = view.getZoom() + if (currentZoom !== undefined) { + const newZoom = view.getConstrainedZoom(currentZoom + delta) + if (duration > 0) { + if (view.getAnimating()) { + view.cancelAnimations() + } + view.animate({ + zoom: newZoom, + duration: duration, + easing: easeOut + }) + } else { + view.setZoom(newZoom) + } + } + } + + /** + * @param {Document} doc The root document to check. + * @return {boolean} Fullscreen is supported by the current platform. + */ + function isFullScreenSupported(doc) { + const body = doc.body + return !!( + body['webkitRequestFullscreen'] || + (body.requestFullscreen && doc.fullscreenEnabled) + ) + } + + /** + * @param {Document} doc The root document to check. + * @return {boolean} Element is currently in fullscreen. + */ + function isFullScreen(doc) { + return !!(doc['webkitIsFullScreen'] || doc.fullscreenElement) + } + + /** + * Request to fullscreen an element. + * @param {HTMLElement} element Element to request fullscreen + */ + function requestFullScreen(element) { + if (element.requestFullscreen) { + element.requestFullscreen() + } else if (element['webkitRequestFullscreen']) { + element['webkitRequestFullscreen']() + } + } + + /** + * Request to fullscreen an element with keyboard input. + * @param {HTMLElement} element Element to request fullscreen + */ + function requestFullScreenWithKeys(element) { + if (element['webkitRequestFullscreen']) { + element['webkitRequestFullscreen']() + } else { + requestFullScreen(element) + } + } + + /** + * Exit fullscreen. + * @param {Document} doc The document to exit fullscren from + */ + function exitFullScreen(doc) { + if (doc.exitFullscreen) { + doc.exitFullscreen() + } else if (doc['webkitExitFullscreen']) { + doc['webkitExitFullscreen']() + } + } + + function handleFullScreen(withKeys = false) { + const map = mapRef.value.map + if (!map) { + return + } + const doc = map.getOwnerDocument() + if (!isFullScreenSupported(doc)) { + return + } + if (isFullScreen(doc)) { + exitFullScreen(doc) + isFullScreenRef.value = false + } else { + const element = map.getTargetElement() + if (withKeys) { + requestFullScreenWithKeys(element) + } else { + requestFullScreen(element) + } + isFullScreenRef.value = true + } + } + + function onHomeClick() { + centerMap(mapRef.value.map, center.value, { y: 0, x: 0 }, initialZoom) + } + function onZoomInClick() { + zoomByDelta(1) + } + function onZoomOutClick() { + zoomByDelta(-1) + } + function onFullScreenClick() { + handleFullScreen() + } + + return { + onHomeClick, + onZoomInClick, + onZoomOutClick, + onFullScreenClick, + isFullScreenRef + } +}