or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

canvas.mdcore-framework.mddevice.mddom-query.mdindex.mdlocation.mdmedia.mdnavigation.mdnetwork.mdstorage.mdsystem-info.mdui-interactions.md

location.mddocs/

0

# Location Services

1

2

Geolocation API integration providing location access and monitoring capabilities for web environments using the browser's native Geolocation API with Mini Program compatibility.

3

4

## Capabilities

5

6

### Get Current Location

7

8

Retrieve the device's current geographical location with configurable accuracy and coordinate system options.

9

10

```typescript { .api }

11

/**

12

* Get current device location

13

* @param options - Location retrieval configuration

14

* @returns Promise resolving to current location coordinates

15

*/

16

function getLocation(options: LocationOption): Promise<LocationResult>;

17

18

interface LocationOption extends CallbackOptions {

19

/** Coordinate system type (default: 'wgs84') */

20

type?: 'wgs84' | 'gcj02';

21

/** Whether to include altitude information (default: false) */

22

altitude?: boolean;

23

/** Use high accuracy mode (default: false) */

24

isHighAccuracy?: boolean;

25

/** High accuracy timeout in milliseconds (default: 3000) */

26

highAccuracyExpireTime?: number;

27

/** Overall operation timeout in milliseconds (default: 5000) */

28

timeout?: number;

29

/** Cache valid time in milliseconds (default: 0, no cache) */

30

cacheTime?: number;

31

}

32

33

interface LocationResult {

34

/** Latitude coordinate */

35

latitude: number;

36

/** Longitude coordinate */

37

longitude: number;

38

/** Movement speed in m/s */

39

speed: number;

40

/** Location accuracy in meters */

41

accuracy: number;

42

/** Altitude in meters (if altitude: true) */

43

altitude: number;

44

/** Vertical accuracy in meters (if altitude: true) */

45

verticalAccuracy: number;

46

/** Horizontal accuracy in meters */

47

horizontalAccuracy: number;

48

/** Location acquisition timestamp */

49

timestamp?: number;

50

}

51

```

52

53

**Usage Examples:**

54

55

```typescript

56

import { getLocation } from "@tarojs/taro-h5";

57

58

// Basic location retrieval

59

async function getCurrentPosition() {

60

try {

61

const location = await getLocation({

62

type: 'wgs84',

63

isHighAccuracy: true

64

});

65

66

console.log(`Latitude: ${location.latitude}`);

67

console.log(`Longitude: ${location.longitude}`);

68

console.log(`Accuracy: ${location.accuracy}m`);

69

70

return location;

71

} catch (error) {

72

console.error('Failed to get location:', error);

73

throw error;

74

}

75

}

76

77

// High-precision location with altitude

78

const preciseLoc = await getLocation({

79

type: 'wgs84',

80

altitude: true,

81

isHighAccuracy: true,

82

highAccuracyExpireTime: 10000,

83

timeout: 15000

84

});

85

86

console.log(`Position: ${preciseLoc.latitude}, ${preciseLoc.longitude}`);

87

console.log(`Altitude: ${preciseLoc.altitude}m ±${preciseLoc.verticalAccuracy}m`);

88

console.log(`Speed: ${preciseLoc.speed} m/s`);

89

90

// Location with Chinese coordinate system (GCJ-02)

91

const chinaLocation = await getLocation({

92

type: 'gcj02', // Chinese coordinate system

93

isHighAccuracy: false,

94

timeout: 8000

95

});

96

97

// Location with callbacks

98

getLocation({

99

type: 'wgs84',

100

isHighAccuracy: true,

101

success: (location) => {

102

console.log('Location obtained:', location);

103

displayLocationOnMap(location);

104

},

105

fail: (error) => {

106

console.error('Location failed:', error);

107

showLocationError();

108

},

109

complete: () => {

110

console.log('Location request completed');

111

}

112

});

113

```

114

115

### Location Picker

116

117

Allow users to select a location from a map interface or location picker.

118

119

```typescript { .api }

120

/**

121

* Open location picker for user selection

122

* @param options - Location picker configuration

123

* @returns Promise resolving to selected location

124

*/

125

function chooseLocation(options: ChooseLocationOption): Promise<LocationResult>;

126

127

interface ChooseLocationOption extends CallbackOptions {

128

/** Initial latitude for map center */

129

latitude?: number;

130

/** Initial longitude for map center */

131

longitude?: number;

132

/** Map zoom level (1-20, default: 15) */

133

scale?: number;

134

/** Location name search keyword */

135

keyword?: string;

136

}

137

```

138

139

**Usage Examples:**

140

141

```typescript

142

import { chooseLocation } from "@tarojs/taro-h5";

143

144

// Open location picker

145

async function selectLocation() {

146

try {

147

const selectedLocation = await chooseLocation({

148

latitude: 39.908823,

149

longitude: 116.39747,

150

scale: 15

151

});

152

153

console.log('Selected location:', selectedLocation);

154

return selectedLocation;

155

} catch (error) {

156

console.log('User cancelled location selection');

157

return null;

158

}

159

}

160

161

// Location picker with search

162

const searchLocation = await chooseLocation({

163

keyword: 'coffee shop',

164

scale: 16

165

});

166

167

// Location picker near current position

168

async function pickNearbyLocation() {

169

const currentLoc = await getLocation({ type: 'wgs84' });

170

171

const pickedLocation = await chooseLocation({

172

latitude: currentLoc.latitude,

173

longitude: currentLoc.longitude,

174

scale: 17

175

});

176

177

return pickedLocation;

178

}

179

```

180

181

### Open External Map

182

183

Open the selected location in an external map application for navigation or detailed viewing.

184

185

```typescript { .api }

186

/**

187

* Open location in external map application

188

* @param options - External map configuration

189

* @returns Promise that resolves when map is opened

190

*/

191

function openLocation(options: OpenLocationOption): Promise<void>;

192

193

interface OpenLocationOption extends CallbackOptions {

194

/** Target latitude (required) */

195

latitude: number;

196

/** Target longitude (required) */

197

longitude: number;

198

/** Location name/title */

199

name?: string;

200

/** Detailed address description */

201

address?: string;

202

/** Map zoom level (1-20, default: 15) */

203

scale?: number;

204

}

205

```

206

207

**Usage Examples:**

208

209

```typescript

210

import { openLocation } from "@tarojs/taro-h5";

211

212

// Open specific location in external map

213

await openLocation({

214

latitude: 39.908823,

215

longitude: 116.39747,

216

name: 'Tiananmen Square',

217

address: 'Dongcheng District, Beijing',

218

scale: 16

219

});

220

221

// Open user's selected location

222

async function openSelectedLocation(location: LocationResult) {

223

await openLocation({

224

latitude: location.latitude,

225

longitude: location.longitude,

226

name: 'Selected Location',

227

scale: 15

228

});

229

}

230

231

// Open business location with full details

232

await openLocation({

233

latitude: 40.7589,

234

longitude: -73.9851,

235

name: 'Times Square',

236

address: 'Manhattan, New York, NY 10036, USA',

237

scale: 17

238

});

239

```

240

241

### Location Monitoring

242

243

Monitor location changes in real-time for navigation or tracking applications.

244

245

```typescript { .api }

246

/**

247

* Add listener for location changes

248

* @param callback - Function called when location changes

249

*/

250

function onLocationChange(callback: LocationChangeCallback): void;

251

252

/**

253

* Remove listener for location changes

254

* @param callback - Previously registered callback function

255

*/

256

function offLocationChange(callback: LocationChangeCallback): void;

257

258

/**

259

* Add listener for location change errors

260

* @param callback - Function called when location errors occur

261

*/

262

function onLocationChangeError(callback: LocationErrorCallback): void;

263

264

/**

265

* Remove listener for location change errors

266

* @param callback - Previously registered error callback function

267

*/

268

function offLocationChangeError(callback: LocationErrorCallback): void;

269

270

/**

271

* Start location monitoring

272

* @param options - Location monitoring configuration

273

* @returns Promise that resolves when monitoring starts

274

*/

275

function startLocationUpdate(options?: LocationUpdateOption): Promise<void>;

276

277

/**

278

* Stop location monitoring

279

* @returns Promise that resolves when monitoring stops

280

*/

281

function stopLocationUpdate(): Promise<void>;

282

283

interface LocationUpdateOption {

284

/** Coordinate system type (default: 'wgs84') */

285

type?: 'wgs84' | 'gcj02';

286

/** Use high accuracy mode (default: false) */

287

isHighAccuracy?: boolean;

288

/** Update interval in milliseconds (default: 5000) */

289

interval?: number;

290

}

291

292

type LocationChangeCallback = (location: LocationResult) => void;

293

type LocationErrorCallback = (error: any) => void;

294

```

295

296

**Usage Examples:**

297

298

```typescript

299

import {

300

onLocationChange,

301

offLocationChange,

302

onLocationChangeError,

303

offLocationChangeError,

304

startLocationUpdate,

305

stopLocationUpdate

306

} from "@tarojs/taro-h5";

307

308

// Location tracking setup

309

class LocationTracker {

310

private isTracking = false;

311

private locationHistory: LocationResult[] = [];

312

313

async startTracking() {

314

if (this.isTracking) return;

315

316

// Set up event listeners

317

onLocationChange(this.handleLocationChange.bind(this));

318

onLocationChangeError(this.handleLocationError.bind(this));

319

320

try {

321

// Start location updates

322

await startLocationUpdate({

323

type: 'wgs84',

324

isHighAccuracy: true,

325

interval: 5000 // Update every 5 seconds

326

});

327

328

this.isTracking = true;

329

console.log('Location tracking started');

330

} catch (error) {

331

console.error('Failed to start location tracking:', error);

332

}

333

}

334

335

async stopTracking() {

336

if (!this.isTracking) return;

337

338

try {

339

await stopLocationUpdate();

340

341

// Remove event listeners

342

offLocationChange(this.handleLocationChange.bind(this));

343

offLocationChangeError(this.handleLocationError.bind(this));

344

345

this.isTracking = false;

346

console.log('Location tracking stopped');

347

} catch (error) {

348

console.error('Failed to stop location tracking:', error);

349

}

350

}

351

352

private handleLocationChange(location: LocationResult) {

353

console.log('Location updated:', location);

354

355

// Store location history

356

this.locationHistory.push({

357

...location,

358

timestamp: Date.now()

359

});

360

361

// Keep only last 100 locations

362

if (this.locationHistory.length > 100) {

363

this.locationHistory.shift();

364

}

365

366

// Trigger custom events

367

this.onLocationUpdate(location);

368

}

369

370

private handleLocationError(error: any) {

371

console.error('Location tracking error:', error);

372

this.onLocationError(error);

373

}

374

375

// Override these methods in implementation

376

protected onLocationUpdate(location: LocationResult) {

377

// Custom location update handling

378

}

379

380

protected onLocationError(error: any) {

381

// Custom error handling

382

}

383

384

getLocationHistory(): LocationResult[] {

385

return [...this.locationHistory];

386

}

387

388

getCurrentLocation(): LocationResult | null {

389

return this.locationHistory.length > 0

390

? this.locationHistory[this.locationHistory.length - 1]

391

: null;

392

}

393

}

394

395

// Usage

396

const tracker = new LocationTracker();

397

398

// Override event handlers

399

tracker.onLocationUpdate = (location) => {

400

updateMapMarker(location);

401

calculateDistance(location);

402

};

403

404

tracker.onLocationError = (error) => {

405

showToast({

406

title: 'Location tracking error',

407

icon: 'error'

408

});

409

};

410

411

// Start tracking

412

await tracker.startTracking();

413

414

// Stop tracking after 10 minutes

415

setTimeout(() => {

416

tracker.stopTracking();

417

}, 10 * 60 * 1000);

418

```

419

420

### Advanced Location Patterns

421

422

Complex location scenarios and best practices for location-based applications.

423

424

```typescript

425

// Distance calculation utility

426

function calculateDistance(lat1: number, lon1: number, lat2: number, lon2: number): number {

427

const R = 6371; // Earth's radius in kilometers

428

const dLat = (lat2 - lat1) * Math.PI / 180;

429

const dLon = (lon2 - lon1) * Math.PI / 180;

430

const a =

431

Math.sin(dLat/2) * Math.sin(dLat/2) +

432

Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *

433

Math.sin(dLon/2) * Math.sin(dLon/2);

434

const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

435

return R * c; // Distance in kilometers

436

}

437

438

// Geofencing implementation

439

class GeofenceManager {

440

private geofences: Map<string, Geofence> = new Map();

441

private tracker: LocationTracker;

442

443

constructor(tracker: LocationTracker) {

444

this.tracker = tracker;

445

this.tracker.onLocationUpdate = this.checkGeofences.bind(this);

446

}

447

448

addGeofence(id: string, geofence: Geofence) {

449

this.geofences.set(id, geofence);

450

}

451

452

removeGeofence(id: string) {

453

this.geofences.delete(id);

454

}

455

456

private checkGeofences(location: LocationResult) {

457

for (const [id, geofence] of this.geofences) {

458

const distance = calculateDistance(

459

location.latitude,

460

location.longitude,

461

geofence.latitude,

462

geofence.longitude

463

) * 1000; // Convert to meters

464

465

const isInside = distance <= geofence.radius;

466

const wasInside = geofence.isInside || false;

467

468

if (isInside && !wasInside) {

469

// Entered geofence

470

geofence.isInside = true;

471

geofence.onEnter?.(location, geofence);

472

} else if (!isInside && wasInside) {

473

// Exited geofence

474

geofence.isInside = false;

475

geofence.onExit?.(location, geofence);

476

} else if (isInside) {

477

// Still inside

478

geofence.onStay?.(location, geofence);

479

}

480

}

481

}

482

}

483

484

interface Geofence {

485

latitude: number;

486

longitude: number;

487

radius: number; // meters

488

name?: string;

489

isInside?: boolean;

490

onEnter?: (location: LocationResult, geofence: Geofence) => void;

491

onExit?: (location: LocationResult, geofence: Geofence) => void;

492

onStay?: (location: LocationResult, geofence: Geofence) => void;

493

}

494

495

// Location caching for performance

496

class LocationCache {

497

private cache: LocationResult | null = null;

498

private cacheTime: number = 0;

499

private readonly CACHE_DURATION = 30000; // 30 seconds

500

501

async getLocation(options?: LocationOption): Promise<LocationResult> {

502

const now = Date.now();

503

504

// Return cached location if still valid

505

if (this.cache && (now - this.cacheTime) < this.CACHE_DURATION) {

506

console.log('Returning cached location');

507

return this.cache;

508

}

509

510

try {

511

const location = await getLocation(options || { type: 'wgs84' });

512

513

// Update cache

514

this.cache = location;

515

this.cacheTime = now;

516

517

return location;

518

} catch (error) {

519

// Return cached location as fallback if available

520

if (this.cache) {

521

console.log('Using stale cached location due to error');

522

return this.cache;

523

}

524

throw error;

525

}

526

}

527

528

clearCache() {

529

this.cache = null;

530

this.cacheTime = 0;

531

}

532

}

533

534

// Permission handling utility

535

class LocationPermissionManager {

536

static async requestPermission(): Promise<boolean> {

537

if (!navigator.geolocation) {

538

console.error('Geolocation is not supported');

539

return false;

540

}

541

542

try {

543

// Test location access

544

await new Promise<GeolocationPosition>((resolve, reject) => {

545

navigator.geolocation.getCurrentPosition(resolve, reject, {

546

timeout: 10000,

547

maximumAge: 0

548

});

549

});

550

551

return true;

552

} catch (error: any) {

553

console.error('Location permission denied:', error);

554

555

if (error.code === 1) { // PERMISSION_DENIED

556

await showModal({

557

title: 'Location Permission Required',

558

content: 'This app needs location access to provide location-based features. Please enable location permissions in your browser settings.',

559

showCancel: false,

560

confirmText: 'OK'

561

});

562

}

563

564

return false;

565

}

566

}

567

568

static async checkPermissionStatus(): Promise<'granted' | 'denied' | 'prompt'> {

569

if (!navigator.permissions) {

570

return 'prompt'; // Assume permission is needed

571

}

572

573

try {

574

const permission = await navigator.permissions.query({ name: 'geolocation' });

575

return permission.state;

576

} catch {

577

return 'prompt';

578

}

579

}

580

}

581

582

// Usage examples

583

async function initializeLocationServices() {

584

// Check and request permissions

585

const hasPermission = await LocationPermissionManager.requestPermission();

586

if (!hasPermission) {

587

console.log('Location services unavailable');

588

return;

589

}

590

591

// Initialize location cache

592

const locationCache = new LocationCache();

593

594

// Initialize tracker and geofencing

595

const tracker = new LocationTracker();

596

const geofenceManager = new GeofenceManager(tracker);

597

598

// Add some geofences

599

geofenceManager.addGeofence('home', {

600

latitude: 40.7589,

601

longitude: -73.9851,

602

radius: 100,

603

name: 'Home',

604

onEnter: (location, fence) => {

605

showToast({ title: `Welcome home!`, icon: 'success' });

606

},

607

onExit: (location, fence) => {

608

showToast({ title: `Leaving home`, icon: 'none' });

609

}

610

});

611

612

geofenceManager.addGeofence('office', {

613

latitude: 40.7505,

614

longitude: -73.9934,

615

radius: 50,

616

name: 'Office',

617

onEnter: (location, fence) => {

618

showToast({ title: `Arrived at office`, icon: 'success' });

619

}

620

});

621

622

// Start tracking

623

await tracker.startTracking();

624

625

return { tracker, geofenceManager, locationCache };

626

}

627

```

628

629

## Error Handling

630

631

Location services can fail due to permissions, network issues, or device limitations.

632

633

```typescript

634

// Comprehensive error handling

635

async function safeGetLocation(options?: LocationOption): Promise<LocationResult | null> {

636

try {

637

return await getLocation(options || { type: 'wgs84', timeout: 10000 });

638

} catch (error: any) {

639

console.error('Location error:', error);

640

641

// Handle specific error types

642

if (error.code === 1) { // PERMISSION_DENIED

643

await showModal({

644

title: 'Location Access Denied',

645

content: 'Location permission is required for this feature. Please enable location access in your browser settings.',

646

showCancel: false

647

});

648

} else if (error.code === 2) { // POSITION_UNAVAILABLE

649

await showToast({

650

title: 'Location unavailable',

651

icon: 'error'

652

});

653

} else if (error.code === 3) { // TIMEOUT

654

await showToast({

655

title: 'Location request timed out',

656

icon: 'error'

657

});

658

} else {

659

await showToast({

660

title: 'Failed to get location',

661

icon: 'error'

662

});

663

}

664

665

return null;

666

}

667

}

668

```

669

670

## Types

671

672

```typescript { .api }

673

interface CallbackOptions {

674

success?: (res: any) => void;

675

fail?: (err: any) => void;

676

complete?: (res: any) => void;

677

}

678

679

type CoordinateType = 'wgs84' | 'gcj02';

680

681

interface LocationError {

682

code: number;

683

message: string;

684

}

685

686

// Geolocation error codes

687

declare const LOCATION_ERROR_CODES: {

688

PERMISSION_DENIED: 1;

689

POSITION_UNAVAILABLE: 2;

690

TIMEOUT: 3;

691

};

692

```