H5端API库,为Taro跨端开发框架提供Web/H5端的API实现
—
Geolocation API integration providing location access and monitoring capabilities for web environments using the browser's native Geolocation API with Mini Program compatibility.
Retrieve the device's current geographical location with configurable accuracy and coordinate system options.
/**
* Get current device location
* @param options - Location retrieval configuration
* @returns Promise resolving to current location coordinates
*/
function getLocation(options: LocationOption): Promise<LocationResult>;
interface LocationOption extends CallbackOptions {
/** Coordinate system type (default: 'wgs84') */
type?: 'wgs84' | 'gcj02';
/** Whether to include altitude information (default: false) */
altitude?: boolean;
/** Use high accuracy mode (default: false) */
isHighAccuracy?: boolean;
/** High accuracy timeout in milliseconds (default: 3000) */
highAccuracyExpireTime?: number;
/** Overall operation timeout in milliseconds (default: 5000) */
timeout?: number;
/** Cache valid time in milliseconds (default: 0, no cache) */
cacheTime?: number;
}
interface LocationResult {
/** Latitude coordinate */
latitude: number;
/** Longitude coordinate */
longitude: number;
/** Movement speed in m/s */
speed: number;
/** Location accuracy in meters */
accuracy: number;
/** Altitude in meters (if altitude: true) */
altitude: number;
/** Vertical accuracy in meters (if altitude: true) */
verticalAccuracy: number;
/** Horizontal accuracy in meters */
horizontalAccuracy: number;
/** Location acquisition timestamp */
timestamp?: number;
}Usage Examples:
import { getLocation } from "@tarojs/taro-h5";
// Basic location retrieval
async function getCurrentPosition() {
try {
const location = await getLocation({
type: 'wgs84',
isHighAccuracy: true
});
console.log(`Latitude: ${location.latitude}`);
console.log(`Longitude: ${location.longitude}`);
console.log(`Accuracy: ${location.accuracy}m`);
return location;
} catch (error) {
console.error('Failed to get location:', error);
throw error;
}
}
// High-precision location with altitude
const preciseLoc = await getLocation({
type: 'wgs84',
altitude: true,
isHighAccuracy: true,
highAccuracyExpireTime: 10000,
timeout: 15000
});
console.log(`Position: ${preciseLoc.latitude}, ${preciseLoc.longitude}`);
console.log(`Altitude: ${preciseLoc.altitude}m ±${preciseLoc.verticalAccuracy}m`);
console.log(`Speed: ${preciseLoc.speed} m/s`);
// Location with Chinese coordinate system (GCJ-02)
const chinaLocation = await getLocation({
type: 'gcj02', // Chinese coordinate system
isHighAccuracy: false,
timeout: 8000
});
// Location with callbacks
getLocation({
type: 'wgs84',
isHighAccuracy: true,
success: (location) => {
console.log('Location obtained:', location);
displayLocationOnMap(location);
},
fail: (error) => {
console.error('Location failed:', error);
showLocationError();
},
complete: () => {
console.log('Location request completed');
}
});Allow users to select a location from a map interface or location picker.
/**
* Open location picker for user selection
* @param options - Location picker configuration
* @returns Promise resolving to selected location
*/
function chooseLocation(options: ChooseLocationOption): Promise<LocationResult>;
interface ChooseLocationOption extends CallbackOptions {
/** Initial latitude for map center */
latitude?: number;
/** Initial longitude for map center */
longitude?: number;
/** Map zoom level (1-20, default: 15) */
scale?: number;
/** Location name search keyword */
keyword?: string;
}Usage Examples:
import { chooseLocation } from "@tarojs/taro-h5";
// Open location picker
async function selectLocation() {
try {
const selectedLocation = await chooseLocation({
latitude: 39.908823,
longitude: 116.39747,
scale: 15
});
console.log('Selected location:', selectedLocation);
return selectedLocation;
} catch (error) {
console.log('User cancelled location selection');
return null;
}
}
// Location picker with search
const searchLocation = await chooseLocation({
keyword: 'coffee shop',
scale: 16
});
// Location picker near current position
async function pickNearbyLocation() {
const currentLoc = await getLocation({ type: 'wgs84' });
const pickedLocation = await chooseLocation({
latitude: currentLoc.latitude,
longitude: currentLoc.longitude,
scale: 17
});
return pickedLocation;
}Open the selected location in an external map application for navigation or detailed viewing.
/**
* Open location in external map application
* @param options - External map configuration
* @returns Promise that resolves when map is opened
*/
function openLocation(options: OpenLocationOption): Promise<void>;
interface OpenLocationOption extends CallbackOptions {
/** Target latitude (required) */
latitude: number;
/** Target longitude (required) */
longitude: number;
/** Location name/title */
name?: string;
/** Detailed address description */
address?: string;
/** Map zoom level (1-20, default: 15) */
scale?: number;
}Usage Examples:
import { openLocation } from "@tarojs/taro-h5";
// Open specific location in external map
await openLocation({
latitude: 39.908823,
longitude: 116.39747,
name: 'Tiananmen Square',
address: 'Dongcheng District, Beijing',
scale: 16
});
// Open user's selected location
async function openSelectedLocation(location: LocationResult) {
await openLocation({
latitude: location.latitude,
longitude: location.longitude,
name: 'Selected Location',
scale: 15
});
}
// Open business location with full details
await openLocation({
latitude: 40.7589,
longitude: -73.9851,
name: 'Times Square',
address: 'Manhattan, New York, NY 10036, USA',
scale: 17
});Monitor location changes in real-time for navigation or tracking applications.
/**
* Add listener for location changes
* @param callback - Function called when location changes
*/
function onLocationChange(callback: LocationChangeCallback): void;
/**
* Remove listener for location changes
* @param callback - Previously registered callback function
*/
function offLocationChange(callback: LocationChangeCallback): void;
/**
* Add listener for location change errors
* @param callback - Function called when location errors occur
*/
function onLocationChangeError(callback: LocationErrorCallback): void;
/**
* Remove listener for location change errors
* @param callback - Previously registered error callback function
*/
function offLocationChangeError(callback: LocationErrorCallback): void;
/**
* Start location monitoring
* @param options - Location monitoring configuration
* @returns Promise that resolves when monitoring starts
*/
function startLocationUpdate(options?: LocationUpdateOption): Promise<void>;
/**
* Stop location monitoring
* @returns Promise that resolves when monitoring stops
*/
function stopLocationUpdate(): Promise<void>;
interface LocationUpdateOption {
/** Coordinate system type (default: 'wgs84') */
type?: 'wgs84' | 'gcj02';
/** Use high accuracy mode (default: false) */
isHighAccuracy?: boolean;
/** Update interval in milliseconds (default: 5000) */
interval?: number;
}
type LocationChangeCallback = (location: LocationResult) => void;
type LocationErrorCallback = (error: any) => void;Usage Examples:
import {
onLocationChange,
offLocationChange,
onLocationChangeError,
offLocationChangeError,
startLocationUpdate,
stopLocationUpdate
} from "@tarojs/taro-h5";
// Location tracking setup
class LocationTracker {
private isTracking = false;
private locationHistory: LocationResult[] = [];
async startTracking() {
if (this.isTracking) return;
// Set up event listeners
onLocationChange(this.handleLocationChange.bind(this));
onLocationChangeError(this.handleLocationError.bind(this));
try {
// Start location updates
await startLocationUpdate({
type: 'wgs84',
isHighAccuracy: true,
interval: 5000 // Update every 5 seconds
});
this.isTracking = true;
console.log('Location tracking started');
} catch (error) {
console.error('Failed to start location tracking:', error);
}
}
async stopTracking() {
if (!this.isTracking) return;
try {
await stopLocationUpdate();
// Remove event listeners
offLocationChange(this.handleLocationChange.bind(this));
offLocationChangeError(this.handleLocationError.bind(this));
this.isTracking = false;
console.log('Location tracking stopped');
} catch (error) {
console.error('Failed to stop location tracking:', error);
}
}
private handleLocationChange(location: LocationResult) {
console.log('Location updated:', location);
// Store location history
this.locationHistory.push({
...location,
timestamp: Date.now()
});
// Keep only last 100 locations
if (this.locationHistory.length > 100) {
this.locationHistory.shift();
}
// Trigger custom events
this.onLocationUpdate(location);
}
private handleLocationError(error: any) {
console.error('Location tracking error:', error);
this.onLocationError(error);
}
// Override these methods in implementation
protected onLocationUpdate(location: LocationResult) {
// Custom location update handling
}
protected onLocationError(error: any) {
// Custom error handling
}
getLocationHistory(): LocationResult[] {
return [...this.locationHistory];
}
getCurrentLocation(): LocationResult | null {
return this.locationHistory.length > 0
? this.locationHistory[this.locationHistory.length - 1]
: null;
}
}
// Usage
const tracker = new LocationTracker();
// Override event handlers
tracker.onLocationUpdate = (location) => {
updateMapMarker(location);
calculateDistance(location);
};
tracker.onLocationError = (error) => {
showToast({
title: 'Location tracking error',
icon: 'error'
});
};
// Start tracking
await tracker.startTracking();
// Stop tracking after 10 minutes
setTimeout(() => {
tracker.stopTracking();
}, 10 * 60 * 1000);Complex location scenarios and best practices for location-based applications.
// Distance calculation utility
function calculateDistance(lat1: number, lon1: number, lat2: number, lon2: number): number {
const R = 6371; // Earth's radius in kilometers
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLon = (lon2 - lon1) * Math.PI / 180;
const a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon/2) * Math.sin(dLon/2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c; // Distance in kilometers
}
// Geofencing implementation
class GeofenceManager {
private geofences: Map<string, Geofence> = new Map();
private tracker: LocationTracker;
constructor(tracker: LocationTracker) {
this.tracker = tracker;
this.tracker.onLocationUpdate = this.checkGeofences.bind(this);
}
addGeofence(id: string, geofence: Geofence) {
this.geofences.set(id, geofence);
}
removeGeofence(id: string) {
this.geofences.delete(id);
}
private checkGeofences(location: LocationResult) {
for (const [id, geofence] of this.geofences) {
const distance = calculateDistance(
location.latitude,
location.longitude,
geofence.latitude,
geofence.longitude
) * 1000; // Convert to meters
const isInside = distance <= geofence.radius;
const wasInside = geofence.isInside || false;
if (isInside && !wasInside) {
// Entered geofence
geofence.isInside = true;
geofence.onEnter?.(location, geofence);
} else if (!isInside && wasInside) {
// Exited geofence
geofence.isInside = false;
geofence.onExit?.(location, geofence);
} else if (isInside) {
// Still inside
geofence.onStay?.(location, geofence);
}
}
}
}
interface Geofence {
latitude: number;
longitude: number;
radius: number; // meters
name?: string;
isInside?: boolean;
onEnter?: (location: LocationResult, geofence: Geofence) => void;
onExit?: (location: LocationResult, geofence: Geofence) => void;
onStay?: (location: LocationResult, geofence: Geofence) => void;
}
// Location caching for performance
class LocationCache {
private cache: LocationResult | null = null;
private cacheTime: number = 0;
private readonly CACHE_DURATION = 30000; // 30 seconds
async getLocation(options?: LocationOption): Promise<LocationResult> {
const now = Date.now();
// Return cached location if still valid
if (this.cache && (now - this.cacheTime) < this.CACHE_DURATION) {
console.log('Returning cached location');
return this.cache;
}
try {
const location = await getLocation(options || { type: 'wgs84' });
// Update cache
this.cache = location;
this.cacheTime = now;
return location;
} catch (error) {
// Return cached location as fallback if available
if (this.cache) {
console.log('Using stale cached location due to error');
return this.cache;
}
throw error;
}
}
clearCache() {
this.cache = null;
this.cacheTime = 0;
}
}
// Permission handling utility
class LocationPermissionManager {
static async requestPermission(): Promise<boolean> {
if (!navigator.geolocation) {
console.error('Geolocation is not supported');
return false;
}
try {
// Test location access
await new Promise<GeolocationPosition>((resolve, reject) => {
navigator.geolocation.getCurrentPosition(resolve, reject, {
timeout: 10000,
maximumAge: 0
});
});
return true;
} catch (error: any) {
console.error('Location permission denied:', error);
if (error.code === 1) { // PERMISSION_DENIED
await showModal({
title: 'Location Permission Required',
content: 'This app needs location access to provide location-based features. Please enable location permissions in your browser settings.',
showCancel: false,
confirmText: 'OK'
});
}
return false;
}
}
static async checkPermissionStatus(): Promise<'granted' | 'denied' | 'prompt'> {
if (!navigator.permissions) {
return 'prompt'; // Assume permission is needed
}
try {
const permission = await navigator.permissions.query({ name: 'geolocation' });
return permission.state;
} catch {
return 'prompt';
}
}
}
// Usage examples
async function initializeLocationServices() {
// Check and request permissions
const hasPermission = await LocationPermissionManager.requestPermission();
if (!hasPermission) {
console.log('Location services unavailable');
return;
}
// Initialize location cache
const locationCache = new LocationCache();
// Initialize tracker and geofencing
const tracker = new LocationTracker();
const geofenceManager = new GeofenceManager(tracker);
// Add some geofences
geofenceManager.addGeofence('home', {
latitude: 40.7589,
longitude: -73.9851,
radius: 100,
name: 'Home',
onEnter: (location, fence) => {
showToast({ title: `Welcome home!`, icon: 'success' });
},
onExit: (location, fence) => {
showToast({ title: `Leaving home`, icon: 'none' });
}
});
geofenceManager.addGeofence('office', {
latitude: 40.7505,
longitude: -73.9934,
radius: 50,
name: 'Office',
onEnter: (location, fence) => {
showToast({ title: `Arrived at office`, icon: 'success' });
}
});
// Start tracking
await tracker.startTracking();
return { tracker, geofenceManager, locationCache };
}Location services can fail due to permissions, network issues, or device limitations.
// Comprehensive error handling
async function safeGetLocation(options?: LocationOption): Promise<LocationResult | null> {
try {
return await getLocation(options || { type: 'wgs84', timeout: 10000 });
} catch (error: any) {
console.error('Location error:', error);
// Handle specific error types
if (error.code === 1) { // PERMISSION_DENIED
await showModal({
title: 'Location Access Denied',
content: 'Location permission is required for this feature. Please enable location access in your browser settings.',
showCancel: false
});
} else if (error.code === 2) { // POSITION_UNAVAILABLE
await showToast({
title: 'Location unavailable',
icon: 'error'
});
} else if (error.code === 3) { // TIMEOUT
await showToast({
title: 'Location request timed out',
icon: 'error'
});
} else {
await showToast({
title: 'Failed to get location',
icon: 'error'
});
}
return null;
}
}interface CallbackOptions {
success?: (res: any) => void;
fail?: (err: any) => void;
complete?: (res: any) => void;
}
type CoordinateType = 'wgs84' | 'gcj02';
interface LocationError {
code: number;
message: string;
}
// Geolocation error codes
declare const LOCATION_ERROR_CODES: {
PERMISSION_DENIED: 1;
POSITION_UNAVAILABLE: 2;
TIMEOUT: 3;
};Install with Tessl CLI
npx tessl i tessl/npm-tarojs--taro-h5