Search with Distance & Proximity Filter

When building location-aware applications, you often need to restrict or bias search results to a specific area. This example demonstrates how to use interactive map selection to configure locationBias (soft preference) or locationRestriction (hard boundary) with visual feedback, perfect for "near me" searches, delivery zones, or service area restrictions.

Live Demo

Use the interactive map selectors to set your origin point, choose between location bias (soft preference) or location restriction (hard boundary), and adjust the search radius. Click on the maps to visually select center points and see the search area with circle or rectangle overlays.

Lat: 51.520454

Lng: -0.127983

The origin point from which to calculate geodesic distance to the destination place.

1 km 50 km

Centre point: (51.5205° N, 0.1280° W)

Bias: Prefers results within radius but allows others

Lat: 51.518233

Lng: -0.099195

Bias results to a specified location.

Try it out:

powered by
powered by Google

How It Works

This example demonstrates an interactive map-based approach to configuring proximity search with visual feedback for both location bias and restriction modes.

  1. Separate Location Points: Uses three distinct locations: locOrigin for distance calculations, locBias for the bias center, and locRestriction bounds for restriction mode. This allows independent configuration of each aspect.
  2. Interactive Map Selection: Users click on Google Maps to visually select points. Location Bias shows a circle overlay (radius-based), whilst Location Restriction shows a rectangle overlay (bounds-based) for immediate visual feedback.
  3. Mode Switching: Toggle buttons let users switch between locationBias (soft preference) and locationRestriction (hard boundary). The UI conditionally renders the appropriate controls for each mode.
  4. Reactive Updates: Uses $effect to automatically update requestParams when the mode, radius, or location points change. A {#key} block ensures the component re-initialises with new parameters.
  5. Visual Overlays: The maps display Circle and Rectangle shapes using Google Maps API to show the exact search area, helping users understand the effective range of their configuration before making selections.
  6. Distance Calculation: Implements the Haversine formula to calculate geodesic distance from the origin point, displayed with each selected place.

Location Restriction vs Location Bias

  • locationRestriction: Hard limit. Results must be within the specified area. Use for strict service area boundaries.
  • locationBias: Soft preference. Results are preferred from the area but can come from elsewhere. Use for better UX when strict boundaries aren't required.
  • You can use both together to combine strict limits with smart ranking.

Full Code Example

Here's a complete implementation of proximity filtering. Adapt the centre point to your application's needs (e.g., user's geolocation, business location, selected city).

<script lang="ts">
	import { PlaceAutocomplete } from 'places-autocomplete-svelte';
	import type { PlaceResult } from 'places-autocomplete-svelte/interfaces';

	let radiusKm = $state(2);
	let locationType = $state<'locationBias' | 'locationRestriction'>('locationBias');
	
	// Separate points for origin, bias center, and restriction bounds
	let locOrigin = $state({ lat: 51.5074, lng: -0.1278 });
	let locBias = $state({ lat: 51.5074, lng: -0.1278 });
	let locRestriction = $state({
		north: 51.522577,
		east: -0.122372,
		south: 51.51745,
		west: -0.133701
	});

	// Reactive request parameters based on selected mode
	let requestParams = $state({
		language: 'en-gb',
		region: 'GB',
		origin: locOrigin
	});

	const options = {
		placeholder: `Search within ${radiusKm}km...`,
		distance: true,
		distance_units: 'km'
	};

	// Update request params when mode or values change
	$effect(() => {
		const { locationRestriction, locationBias, ...rest } = requestParams;
		requestParams = {
			...rest,
			origin: locOrigin
		};

		if (locationType === 'locationBias') {
			requestParams.locationBias = {
				circle: {
					center: locBias,
					radius: radiusKm * 1000
				}
			};
		} else {
			requestParams.locationRestriction = locRestriction;
		}
	});

	const onResponse = (response: PlaceResult) => {
		console.log('Selected place:', response);
	};
</script>

<!-- Mode Toggle -->
<div>
	<button onclick={() => locationType = 'locationBias'}>
		Location Bias
	</button>
	<button onclick={() => locationType = 'locationRestriction'}>
		Location Restriction
	</button>
</div>

<!-- Radius Slider -->
<label>
	Search radius: {radiusKm} km
	<input 
		type="range" 
		bind:value={radiusKm} 
		min="1" 
		max="50"
	/>
</label>

<!-- Autocomplete Component -->
{#key requestParams}
	<PlaceAutocomplete
		{onResponse}
		{requestParams}
		{options}
	/>
{/key}