Interaction Components

Interaction components handle user input and enable functionality like feature selection, drawing, and editing. They provide a reactive interface to OpenLayers’ interaction system with automatic reactivity for seamless bidirectional updates.

Interaction.Select

Allows users to select features by clicking or other methods.

Basic Usage

<script>
	import { View, Map, Layer, Feature, Interaction } from 'svelte-openlayers';

	let selectedFeatures: ReactiveCollection | null = $state(null);

	const selectedStyle = createCircleStyle({
		radius: 12,
		fill: { color: '#ef4444' },
		stroke: { color: '#ffffff', width: 3 }
	});
</script>

<View center={[0, 0]} zoom={2}>
	<Map class="h-96 w-full">
		<Layer.Tile source="osm" />
		<Layer.Vector>
			<Feature.Point coordinates={[-74.0, 40.7]} properties={{ name: 'New York' }} />
			<Feature.Point coordinates={[-118.2, 34.0]} properties={{ name: 'Los Angeles' }} />
		</Layer.Vector>

		<Interaction.Select bind:selectedFeatures style={selectedStyle} />
	</Map>
</View>

Props

PropTypeDefaultDescription
styleStyleLikeundefinedStyle for selected features
layersLayer[]undefinedLayers to select from
filteranyundefinedFeature filter function
multibooleanfalseAllow multiple selection
hitTolerancenumberundefinedHit detection tolerance in pixels
addConditionanyundefinedCondition for adding to selection
removeConditionanyundefinedCondition for removing from selection
toggleConditionanyundefinedCondition for toggling selection
onSelect(features: Feature[]) => voidundefinedSelection callback
interactionanyundefinedBindable interaction instance (read-only)
selectedFeaturesReactiveCollection<Feature>undefinedBindable reactive selected features collection
reactivebooleantrueEnable automatic reactivity (set to false for performance)

Interaction.Hover

Detects when the pointer hovers over features and provides callbacks for hover events.

Basic Usage

<script>
	import { View, Map, Layer, Feature, Interaction } from 'svelte-openlayers';

	let hoveredFeature = null;

	const handleHover = (feature, coordinate) => {
		hoveredFeature = feature;
	};

	const handleHoverEnd = () => {
		hoveredFeature = null;
	};
</script>

<View center={[0, 0]} zoom={2}>
	<Map class="h-96 w-full">
		<Layer.Tile source="osm" />
		<Layer.Vector>
			<Feature.Point coordinates={[-74.0, 40.7]} properties={{ name: 'New York' }} />
			<Feature.Point coordinates={[-118.2, 34.0]} properties={{ name: 'Los Angeles' }} />
		</Layer.Vector>

		<Interaction.Hover onHover={handleHover} onHoverEnd={handleHoverEnd} />
	</Map>
</View>

Props

PropTypeDefaultDescription
onHover(feature: Feature | null, coordinate?: Coordinate) => voidundefinedHover event callback
onHoverEnd() => voidundefinedHover end callback
layersLayer[]undefinedLayers to detect hover on
hitTolerancenumberundefinedHit detection tolerance in pixels
interactionany | nullnullBindable interaction instance (read-only)

Interaction.Draw

Enables drawing of vector features (points, lines, polygons, and circles) on the map. The interaction automatically handles user input and provides callbacks for drawing lifecycle events.

Basic Usage

<script>
	import { Map, Layer, Interaction } from 'svelte-openlayers';
	import { createStyle, createCircleStyle } from 'svelte-openlayers/utils';
	import VectorSource from 'ol/source/Vector.js';

	let drawType = $state('Point');
	let drawnFeatures = $state([]);

	// Create a vector source to store drawn features
	const vectorSource = new VectorSource();

	// Style for drawn features
	const drawStyle = createStyle({
		fill: { color: 'rgba(59, 130, 246, 0.3)' },
		stroke: { color: '#2563eb', width: 2 },
		image: createCircleStyle({
			radius: 6,
			fill: { color: '#2563eb' },
			stroke: { color: '#ffffff', width: 2 }
		})
	});

	// Style for drawing preview
	const sketchStyle = createStyle({
		fill: { color: 'rgba(16, 185, 129, 0.2)' },
		stroke: { color: '#10b981', width: 2, lineDash: [10, 10] },
		image: createCircleStyle({
			radius: 6,
			fill: { color: '#10b981' },
			stroke: { color: '#ffffff', width: 2 }
		})
	});

	function handleDrawEnd(evt) {
		drawnFeatures = [...drawnFeatures, evt.feature];
	}
</script>

<View center={[-74.006, 40.7128]} zoom={10}>
	<Map class="h-96 w-full">
		<Layer.Tile source="osm" />

		<Layer.Vector bind:source={vectorSource} style={drawStyle}>
			<Interaction.Draw bind:type={drawType} style={sketchStyle} onDrawEnd={handleDrawEnd} />
		</Layer.Vector>
	</Map>
</View>

Drawing Types

  • Point: Click to place a single point
  • LineString: Click to start, continue clicking to add points, double-click to finish
  • Polygon: Click to start, continue clicking to add vertices, double-click to close
  • Circle: Click and drag to create a circle

Props

PropTypeDefaultDescription
type'Point' \| 'LineString' \| 'Polygon' \| 'Circle''Point'Geometry type to draw (bindable)
sourceVectorSourcenullVector source for drawn features (bindable)
styleStyleLike \| FlatStyleLikeundefinedStyle for drawing preview/sketch features
featuresCollection<Feature>undefinedFeature collection for drawn features (bindable)
clickTolerancenumber6Click tolerance in pixels
snapTolerancenumber12Snap tolerance for finishing drawing
stopClickbooleanfalseStop click events during drawing
maxPointsnumberundefinedMaximum number of points before auto-finish
minPointsnumberundefinedMinimum points required (default: 3 for polygons, 2 for lines)
finishConditionConditionundefinedCustom condition for finishing drawing
geometryFunctionGeometryFunctionundefinedCustom geometry creation function
geometryNamestringundefinedGeometry property name for features
conditionConditionundefinedCondition for handling events
freehandbooleanfalseEnable freehand drawing mode
freehandConditionConditionundefinedCondition for freehand mode
traceboolean \| ConditionfalseEnable tracing along existing geometries
traceSourceVectorSourceundefinedSource for features to trace
wrapXbooleanfalseWrap drawing horizontally
geometryLayout'XY' \| 'XYZ' \| 'XYM' \| 'XYZM''XY'Coordinate layout for geometries
interactionDrawnullBindable interaction instance (read-only)

Events

EventTypeDescription
onDrawStart(evt: DrawEvent) => voidFired when drawing starts
onDrawEnd(evt: DrawEvent) => voidFired when drawing is finished
onDrawAbort(evt: DrawEvent) => voidFired when drawing is aborted

Note: The Draw interaction automatically creates its own overlay layer for displaying sketch features while drawing. You only need to provide a vector source for storing the final drawn features.

Interaction.Modify Beta

Beta Feature: This component is functional but may have API changes in future releases.

Enables modification of existing vector features by dragging vertices and segments. Users can move vertices, add new points by dragging segments, and delete vertices (typically with Alt+Click).

Basic Usage

<script>
	import { Map, Layer, Feature, Interaction } from 'svelte-openlayers';
	import Collection from 'ol/Collection.js';

	let selectedFeatures = new Collection();
</script>

<View center={[0, 0]} zoom={2}>
	<Map class="h-96 w-full">
		<Layer.Tile source="osm" />
		<Layer.Vector>
			<Feature.Point coordinates={[-74.0, 40.7]} />
			<Feature.LineString coordinates={[[-74.0, 40.7], [-118.2, 34.0]]} />

			<!-- Select features first -->
			<Interaction.Select bind:selectedFeatures multi />

			<!-- Then modify selected features -->
			<Interaction.Modify features={selectedFeatures} />
		</Layer.Vector>
	</Map>
</View>

Modify by Source

You can modify all features in a layer source without requiring selection:

<script>
	import VectorSource from 'ol/source/Vector.js';

	const vectorSource = new VectorSource();
</script>

<Layer.Vector bind:source={vectorSource}>
	<!-- Features added to the source -->
	<Feature.Polygon coordinates={[/* ... */]} />

	<!-- Modify all features in the source -->
	<Interaction.Modify source={vectorSource} />
</Layer.Vector>

Props

PropTypeDefaultDescription
featuresCollection<Feature> | Feature[]nullFeatures to modify (bindable)
sourceVectorSourcenullSource of features to modify (bindable)
styleStyleLikeundefinedStyle for modified features while editing
pixelTolerancenumber10Pixel tolerance for selecting vertices
conditionConditionundefinedCondition for modification
deleteConditionConditionundefinedCondition for deleting vertices (default: Alt+Click)
insertVertexConditionConditionundefinedCondition for inserting vertices
hitDetectionboolean \| Layer[]undefinedEnable hit detection on layers
onModifyStart(evt: ModifyEvent) => voidundefinedFired when modification starts
onModifyEnd(evt: ModifyEvent) => voidundefinedFired when modification ends
interactionModify | nullnullBindable interaction instance (read-only)

Modification Controls

  • Move vertex: Click and drag a vertex
  • Delete vertex: Alt+Click on a vertex (or custom deleteCondition)
  • Add vertex: Click and drag a line segment between vertices
  • Undo: Press Ctrl+Z while modifying

Events

EventTypeDescription
onModifyStart(evt: ModifyEvent) => voidFired when modification starts
onModifyEnd(evt: ModifyEvent) => voidFired when modification finishes

Combined with Select

The most common pattern is to combine Modify with Select for better UX:

<script>
	import { createCircleStyle, createStyle } from 'svelte-openlayers/utils';
	import Collection from 'ol/Collection.js';

	let selectedFeatures = new Collection();

	const selectedStyle = createStyle({
		stroke: { color: '#2563eb', width: 3 },
		fill: { color: 'rgba(37, 99, 235, 0.2)' },
		image: { radius: 8, fill: { color: '#2563eb' }, stroke: { color: '#fff', width: 2 } }
	});

	const modifyStyle = createStyle({
		stroke: { color: '#10b981', width: 3 },
		fill: { color: 'rgba(16, 185, 129, 0.2)' },
		image: { radius: 6, fill: { color: '#10b981' } }
	});
</script>

<Layer.Vector>
	<!-- Your features -->
	<Feature.Polygon coordinates={[/* ... */]} />

	<!-- Select interaction with custom style -->
	<Interaction.Select bind:selectedFeatures multi style={selectedStyle} />

	<!-- Modify interaction on selected features -->
	<Interaction.Modify
		features={selectedFeatures}
		style={modifyStyle}
		onModifyStart={() => console.log('Started modifying')}
		onModifyEnd={(evt) => console.log('Modified:', evt.features)}
	/>
</Layer.Vector>

Coming Soon: Additional interaction types including Interaction.Translate are planned for future releases.