LocationControl
Shows the user's position on the map as a marker that keeps up with them, and gives them a control that takes the map back to it.
The location control is in its own entry point. Import it from @aptuitiv/gmaps/location-control, or use G.locationControl() with the standalone browser script, which contains everything. See installation.
import { locationControl } from '@aptuitiv/gmaps/location-control';
locationControl({
className: 'MapBtn MapBtn-geo',
content: '<svg class="Icon"><use xlink:href="#icon-location" /></svg>',
map: map,
position: ControlPosition.LEFT_BOTTOM,
});
That's the whole feature. The map starts watching, a marker appears where the user is and follows them, the control appears once there's somewhere to go, and clicking it pans the map there.
map.locate() does the locating on its own if all you want is the position data. This control is the part that shows it.
What it does, in order
- Starts the map watching with locate(), unless
autoLocateis off. - When the location is first found: shows the marker, puts the control on the map, and moves the map if
centerOnFirstFindis set. - On later location updates: moves the marker only. The map is deliberately left alone, so it doesn't yank itself back while the user is panning.
- On an error: nothing appears. With the default
showWhenLocatedthe control was never added, so a denied permission leaves no dead button on the map.
Location control options
Type LocationControlOptions.
The control is a button — it extends Button — and it has
a marker. That's why its own button appearance is configured at the top level, the same way you'd configure
any button, while the marker it puts on the map is configured under marker:
locationControl({
// The control's own appearance. It is the button.
className: 'MapBtn MapBtn-geo',
content: '<svg class="Icon"><use xlink:href="#icon-location" /></svg>',
position: ControlPosition.LEFT_BOTTOM,
// The marker it puts on the map, which is a separate object
marker: { svgIcon: { fillColor: '#c0392b' } },
// The control's own behaviour
action: 'center',
zoom: 15,
});
Marker works the same way: its own options are top-level and the tooltip it
attaches is nested under tooltip.
The control's own options
These come from Button and Control. The ones you'll usually want include:
| Option | Type | Description |
|---|---|---|
| attributes | object | Attributes to set on the element, such as a tooltip attribute your CSS reads. |
| className | string | Class name(s) for the element. Nothing is styled for you. |
| content | string | HTMLElement | Function | The contents — usually an icon. |
| element | HTMLElement | string | An existing element, or a selector for one, to use instead of building one. |
| index | number | The order among the controls at the same position. |
| onClick | Function | Called when the control is clicked, in addition to moving the map. |
| position | ControlPosition | Where the control goes on the map. |
| states | ButtonStates | What each state looks like, if you want the control to reflect one. |
| tag | string | The element to build. Defaults to button. |
See ButtonOptions for the rest.
The control's own behaviour, and the marker
| Option | Type | Default | Description |
|---|---|---|---|
| action | 'pan' | 'center' | pan | What clicking does with the map. |
| button | boolean | true | false for the marker on its own, with no control on the map. |
| autoLocate | boolean | true | Whether the control calls locate() itself. Set it to false if something else on the page already does. |
| centerOnFirstFind | boolean | false | Whether to move the map to the user the first time a location is found. |
| locateOptions | LocateOptions | Passed through to locate(). | |
| marker | boolean | Marker | MarkerOptions | false for no marker, a Marker to use as it is, or options merged over the default. | |
| showWhenLocated | boolean | true | Whether the control is only put on the map once a location has been found. |
| zoom | number | The zoom level to set when the control is clicked. Left alone if not set. |
The marker
The default is a blue dot for the user's position. It's a Marker with an SvgSymbol, so anything you can do to a marker you can do to it.
Pass marker options to change part of it — they're merged over the default, so you can change just the colour:
locationControl({ map: map, marker: { svgIcon: { fillColor: '#c0392b' } } });
svgIcon is merged a level deeper than the other options, so the rest of the icon — the path that draws the dot, the white outline — is kept. Pass a whole SVG string or an SvgSymbol instead and it's used as it is, with nothing merged into it.
The dot has no hover tooltip unless you ask for one. A marker's title shows as a tooltip when it's hovered. Add one if you want it, in whatever language your site is in:
locationControl({ map: map, marker: { title: 'My location' } });
Pass marker: false for a control with no marker, or your own Marker to use instead. A marker you pass in is yours: the control hides it when it's removed rather than destroying it.
Just the marker, with no control
Pass button: false when you want the user's position shown but nothing to click — the page has its own UI, or the dot is all you wanted:
locationControl({ map: map, button: false });
The location is still watched and the marker still follows it. Nothing is added to the map, so the options describing the control's appearance — className, content, position and the rest — are unused.
panToLocation() still works, so your own UI can move the map:
const location = locationControl({ map: map, button: false });
document.querySelector('.js-findMe').addEventListener('click', () => {
location.panToLocation();
});
Styling
No CSS ships with the library and no class names are chosen for you. A control with no className renders as an unstyled button. Something like this is a reasonable starting point:
.MapBtn {
background-color: #fff;
border: none;
border-radius: 2px;
box-shadow: 0 1px 4px -1px rgb(0 0 0 / 30%);
cursor: pointer;
margin: 10px;
padding: 8px;
}
Properties
| Property | Type | Description |
|---|---|---|
| isLocated | boolean | Whether a location has been found yet. Read only. |
| location | LocationPosition | undefined | The last position that was found. Read only. |
| marker | Marker | undefined | The marker showing where the user is. Read only. |
Plus everything from Button and Control.
Events
| Event | Description |
|---|---|
| located | A location was found. Fires on every fix, not just the first. The event includes the position. |
Plus click and change from Button, and add and remove from Control.
For the raw position data, listen to locationfound on the map instead — that's the right place for anything that isn't about this control, like filling in a "search near me" field.
map.onLocationFound((position) => {
document.querySelector('#lat').value = position.latitude;
document.querySelector('#lng').value = position.longitude;
});
Methods
| Method | Description |
|---|---|
| panToLocation() | Move the map to the last known location. This is what clicking does, exposed so the same behaviour can go on your own UI. |
| setMap(map) | Start listening to a map and show the control on it. It also starts the watch, unless autoLocate is off. The map option does this for you. |
| stop() | Stop watching, leaving the control and marker where they are. |
| remove() | Take the control off the map, hide the marker and stop watching. |
Stopping
stop() and remove() only stop the watch if this control started it. If something else on the page called locate() first, its updates keep coming.
remove() also stops the control listening to the map, so a location found afterwards does nothing. Call setMap() again to attach it to a map afterwards.
That restarts the watch as well, unless autoLocate is off — with it off the control listens but never asks for a location, so call map.locate() yourself:
control.setMap(map);
map.locate();
Using it with something else that locates
If the page already calls locate() — often to get the position before the map is even shown — turn autoLocate off. The control still reacts to every fix:
map.locate();
locationControl({ autoLocate: false, className: 'MapBtn', map: map });
Calling locate() more than once is safe either way: the map only ever keeps one watch.