Skip to content

Commit

Permalink
Merge pull request #150 from Geoportail-Luxembourg/GSLUX-736-fit-draw…
Browse files Browse the repository at this point in the history
…-feat

GSLUX-736: Fit view on feature
  • Loading branch information
AlitaBernachot authored Sep 30, 2024
2 parents f223b44 + c687256 commit 9341d8c
Show file tree
Hide file tree
Showing 13 changed files with 126 additions and 12 deletions.
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ VITE_OFFLINE_GUTTER=96

# View
VITE_DEFAULT_VIEW_ZOOM=8
VITE_DEFAULT_VIEW_ZOOM_MAX=19
VITE_DEFAULT_VIEW_ZOOM_MIN=8
VITE_DEFAULT_MAX_EXTENT=[2.6, 47.7, 8.6, 51]

# Mode lib in v3
Expand Down
2 changes: 2 additions & 0 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ VITE_OFFLINE_GUTTER=96

# View
VITE_DEFAULT_VIEW_ZOOM=8
VITE_DEFAULT_VIEW_ZOOM_MAX=19
VITE_DEFAULT_VIEW_ZOOM_MIN=8
VITE_DEFAULT_MAX_EXTENT=[2.6, 47.7, 8.6, 51]

# Mode lib in v3
Expand Down
2 changes: 2 additions & 0 deletions .env.e2e
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ VITE_OFFLINE_GUTTER=96

# View
VITE_DEFAULT_VIEW_ZOOM=8
VITE_DEFAULT_VIEW_ZOOM_MAX=19
VITE_DEFAULT_VIEW_ZOOM_MIN=8
VITE_DEFAULT_MAX_EXTENT=[2.6, 47.7, 8.6, 51]

# Mode lib in v3
Expand Down
2 changes: 2 additions & 0 deletions .env.staging
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ VITE_OFFLINE_GUTTER=96

# View
VITE_DEFAULT_VIEW_ZOOM=8
VITE_DEFAULT_VIEW_ZOOM_MAX=19
VITE_DEFAULT_VIEW_ZOOM_MIN=8
VITE_DEFAULT_MAX_EXTENT=[2.6, 47.7, 8.6, 51]

# Mode lib in v3
Expand Down
6 changes: 1 addition & 5 deletions src/components/draw/feature-sub-content.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ function onClickValidate() {
}
currentEditCompKey.value = undefined
}
function onClickSearch() {
alert('TODO: Draw feature click onClickSearch()')
}
</script>

<template>
Expand Down Expand Up @@ -101,7 +97,7 @@ function onClickSearch() {
<button
data-cy="featItemActionSearch"
class="hover:text-tertiary"
@click="onClickSearch"
@click="() => feature?.fit()"
>
<i class="fa fa-search"></i>
</button>
Expand Down
4 changes: 2 additions & 2 deletions src/composables/layers/layers.composable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import { useAlertNotificationsStore } from '@/stores/alert-notifications.store'
import useThemes from '@/composables/themes/themes.composable'
import { AlertNotificationType } from '@/stores/alert-notifications.store.model'

const themes = useThemes()

export default function useLayers() {
const themes = useThemes()

function hasIntersect(exclusionA: string, exclusionB: string) {
try {
const concat = JSON.parse(exclusionA).concat(JSON.parse(exclusionB))
Expand Down
9 changes: 9 additions & 0 deletions src/composables/map/map.model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import MapLibreLayer from '@/lib/ol-mapbox-layer'

export const DEFAULT_VIEW_ZOOM_MAX = parseInt(
import.meta.env.VITE_DEFAULT_VIEW_ZOOM_MAX,
10
)
export const DEFAULT_VIEW_ZOOM_MIN = parseInt(
import.meta.env.VITE_DEFAULT_VIEW_ZOOM_MIN,
10
)

export declare type MapLibreLayerType = typeof MapLibreLayer

export enum MutationTypeValue {
Expand Down
5 changes: 5 additions & 0 deletions src/composables/map/ol-view.synchronizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import { watch } from 'vue'
import type OlMap from 'ol/Map'

import { useMapStore } from '@/stores/map.store'
import { DEFAULT_VIEW_ZOOM_MAX, DEFAULT_VIEW_ZOOM_MIN } from './map.model'

export class OlViewSynchronizer {
constructor(map: OlMap) {
const view = map.getView()
const mapStore = useMapStore()

view.setMaxZoom(DEFAULT_VIEW_ZOOM_MAX)
view.setMinZoom(DEFAULT_VIEW_ZOOM_MIN)
view.setConstrainResolution(true) // No intermediate zooms

watch(
() => mapStore.minZoom,
zoom => zoom !== undefined && view.setMinZoom(zoom)
Expand Down
24 changes: 23 additions & 1 deletion src/composables/themes/themes.composable.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { ThemeNodeModel } from './themes.model'
import type { Metadata, ThemeNodeModel } from './themes.model'
import { useThemeStore } from '@/stores/config.store'
import { useMapStore } from '@/stores/map.store'
import { LayerId } from '@/stores/map.store.model'
import { storeToRefs } from 'pinia'
import { DEFAULT_VIEW_ZOOM_MAX } from '@/composables/map/map.model'

export default function useThemes() {
function findById(
Expand Down Expand Up @@ -54,10 +57,29 @@ export default function useThemes() {
return bgLayers.find(l => l.name === name)
}

/**
* Switch theme and set max zoom
* @param name The theme's name eg. "main"
*/
function setTheme(name: string) {
const { setTheme } = useThemeStore()

setTheme(name)
setThemeZooms(name)
}

/**
* Set the max zoom according to the theme's metadata resolutions (if any).
* Only the max zoom is set, min zoom is by default always 8.
* @param name The theme's name eg. "main"
*/
function setThemeZooms(name: string) {
// TODO: deactivate setThemeZooms in v3 and use this one instead
const { maxZoom } = storeToRefs(useMapStore())
const theme = findByName(name)
const { resolutions } = <Metadata>theme?.metadata || {}

maxZoom.value = resolutions ? resolutions.length + 7 : DEFAULT_VIEW_ZOOM_MAX
}

return {
Expand Down
46 changes: 46 additions & 0 deletions src/services/draw/drawn-feature.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Map, View } from 'ol'
import { Extent } from 'ol/extent'
import { Geometry } from 'ol/geom'

import { DrawnFeature } from './drawn-feature'
import useMap from '@/composables/map/map.composable'

const mockViewSize = [99, 100]

vi.mock('@/composables/map/map.composable', () => ({
default: () => ({
getOlMap: vi.fn(() => ({
getSize: vi.fn(() => mockViewSize),
getView: vi.fn(() => {}),
})),
}),
}))

describe('DrawnFeature', () => {
let drawnFeature: DrawnFeature
let mockMap: Map

beforeEach(() => {
drawnFeature = new DrawnFeature()
mockMap = useMap().getOlMap()
drawnFeature.map = mockMap
})

it('should call map.getView().fit with correct extent and size', () => {
const mockExtent: Extent = [0, 0, 10, 10]
const mockGeometry = {
getExtent: vi.fn(() => mockExtent),
} as unknown as Geometry

vi.spyOn(drawnFeature, 'getGeometry').mockReturnValue(mockGeometry)
vi.spyOn(drawnFeature.map, 'getView').mockReturnValue({
fit: vi.fn(() => {}),
} as unknown as View)

drawnFeature.fit()

expect(mockMap.getView().fit).toHaveBeenCalledWith(mockExtent, {
size: mockViewSize,
})
})
})
15 changes: 11 additions & 4 deletions src/services/draw/drawn-feature.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { Feature } from 'ol'
import { DrawnFeatureType, DrawnFeatureStyle } from '@/stores/draw.store.model'
import useMap from '@/composables/map/map.composable'

import { Point, LineString, MultiPoint, Polygon } from 'ol/geom'

import StyleStyle, { StyleLike, StyleFunction } from 'ol/style/Style'
import StyleRegularShape, {
Options as RegularShapeOptions,
Expand All @@ -13,6 +9,10 @@ import StyleFill from 'ol/style/Fill'
import StyleStroke from 'ol/style/Stroke'
import StyleIcon from 'ol/style/Icon'
import StyleText from 'ol/style/Text'
import { Extent } from 'ol/extent'

import { DrawnFeatureType, DrawnFeatureStyle } from '@/stores/draw.store.model'
import useMap from '@/composables/map/map.composable'

const MYMAPS_URL = import.meta.env.VITE_MYMAPS_URL
const MYMAPS_SYMBOL_URL = MYMAPS_URL + '/symbol/'
Expand All @@ -31,6 +31,13 @@ export class DrawnFeature extends Feature {
featureStyle: DrawnFeatureStyle
map = useMap().getOlMap()

fit() {
const size = this.map.getSize()
const extent = <Extent>this.getGeometry()?.getExtent()

this.map.getView().fit(extent, { size })
}

toProperties() {
return {
angle: this.featureStyle.angle,
Expand Down
20 changes: 20 additions & 0 deletions src/services/state-persistor/state-persistor-map.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import useMap, {
} from '@/composables/map/map.composable'
import {
SP_KEY_ZOOM,
SP_KEY_ROTATION,
SP_KEY_X,
SP_KEY_Y,
SP_KEY_SRS,
Expand Down Expand Up @@ -44,6 +45,22 @@ class StatePersistorMapService implements StatePersistorService {
)
}

persistRotation() {
const view = useMap().getOlMap().getView()
const fnStorageSetValueRotation = () => {
const rotation = view.getRotation()
storageHelper.setValue(SP_KEY_ROTATION, rotation || 0)
}

fnStorageSetValueRotation()

olEvents.listen(
view,
'change:rotation',
debounce(fnStorageSetValueRotation, 300)
)
}

persistXY() {
const view = useMap().getOlMap().getView()
const fnStorageSetValueXY = () => {
Expand All @@ -64,6 +81,7 @@ class StatePersistorMapService implements StatePersistorService {
persist() {
this.persistXY()
this.persistZoom()
this.persistRotation()
}

/**
Expand All @@ -75,6 +93,7 @@ class StatePersistorMapService implements StatePersistorService {
restore() {
const view = useMap().getOlMap().getView()
const zoom = storageHelper.getValue(SP_KEY_ZOOM, stringToNumber)
const rotation = storageHelper.getValue(SP_KEY_ROTATION, stringToNumber)
const version = storageHelper.getInitialVersion()
const x = storageHelper.getValue(SP_KEY_X, stringToNumber)
const y = storageHelper.getValue(SP_KEY_Y, stringToNumber)
Expand Down Expand Up @@ -117,6 +136,7 @@ class StatePersistorMapService implements StatePersistorService {

view.setCenter(viewCenter)
view.setZoom(viewZoom)
view.setRotation(rotation || 0)
}
}

Expand Down
1 change: 1 addition & 0 deletions src/services/state-persistor/state-persistor.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const SP_KEY_OPACITIES = 'opacities'
export const SP_KEY_THEME = 'theme'
export const SP_KEY_TIME_SELECTIONS = 'time' // !!! Separator is "--"?
export const SP_KEY_ZOOM = 'zoom'
export const SP_KEY_ROTATION = 'rotation'
export const SP_KEY_SRS = 'SRS' // TODO:
export const SP_KEY_X = 'X'
export const SP_KEY_Y = 'Y'
Expand Down

0 comments on commit 9341d8c

Please sign in to comment.