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

Control for useGeolocation() #2372

Closed
4 tasks done
lugrinder opened this issue Oct 28, 2022 · 1 comment · Fixed by #2376
Closed
4 tasks done

Control for useGeolocation() #2372

lugrinder opened this issue Oct 28, 2022 · 1 comment · Fixed by #2376
Labels
enhancement New feature or request

Comments

@lugrinder
Copy link

Clear and concise description of the problem

Once used useGeolocation(), it is not possible to stop (and continue) the geolocation update. The only way is unmounting the component that uses it.
There are scenarios where you need to temporally pause the position update, or simply capture the current position by taking multiple positions until accuracy is as desired.

Suggested solution

Add pause() and resume() functions to control the watcher.

Alternative

Export watcher and leave user to control it.

Additional context

No response

Validations

@lugrinder lugrinder added the enhancement New feature or request label Oct 28, 2022
@lugrinder
Copy link
Author

This could be a solution:

/* this implementation is original ported from https://github.com/logaretm/vue-use-web by Abdelrahman Awad */

import type { Ref } from 'vue-demi'
import { ref } from 'vue-demi'
import { tryOnScopeDispose } from '@vueuse/shared'
import { ConfigurableNavigator, defaultNavigator, useSupported } from '@vueuse/core'

export interface UseGeolocationOptions extends Partial<PositionOptions>, ConfigurableNavigator {
  immediate?: boolean
}

/**
 * Reactive Geolocation API.
 *
 * @see https://vueuse.org/useGeolocation
 * @param options
 */
export function useGeolocation(options: UseGeolocationOptions = {}) {
  const {
    enableHighAccuracy = true,
    maximumAge = 30000,
    timeout = 27000,
    navigator = defaultNavigator,
    immediate = true
  } = options

  const isSupported = useSupported(() => navigator && 'geolocation' in navigator)

  const locatedAt: Ref<number | null> = ref(null)
  const error = ref<GeolocationPositionError | null>(null)
  const coords: Ref<GeolocationPosition['coords']> = ref({
    accuracy: 0,
    latitude: Infinity,
    longitude: Infinity,
    altitude: null,
    altitudeAccuracy: null,
    heading: null,
    speed: null,
  })

  function updatePosition(position: GeolocationPosition) {
    locatedAt.value = position.timestamp
    coords.value = position.coords
    error.value = null
  }

  let watcher: number

  function resume() {
    if (isSupported.value) {
      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
      watcher = navigator!.geolocation.watchPosition (
        updatePosition,
        err => error.value = err,
        {
          enableHighAccuracy,
          maximumAge,
          timeout
        }
      )
    }
  }

  function pause() {
    if (watcher && navigator) {
      navigator.geolocation.clearWatch (watcher)
      watcher = 0
    }
  }

  tryOnScopeDispose(() => {
    pause()
  })

  if (immediate)
    resume()

  return {
    isSupported,
    coords,
    locatedAt,
    error,
    pause,
    resume
  }
}

export type UseGeolocationReturn = ReturnType<typeof useGeolocation>

antfu pushed a commit that referenced this issue Nov 8, 2022
Co-authored-by: egstartsev <egstartsev@ozon.ru>
Co-authored-by: BenaXskope <78896684+BenaXskope@users.noreply.github.com>
closes #2372
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant