Skip to main content

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.

info

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​

  1. Starts the map watching with locate(), unless autoLocate is off.
  2. When the location is first found: shows the marker, puts the control on the map, and moves the map if centerOnFirstFind is set.
  3. 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.
  4. On an error: nothing appears. With the default showWhenLocated the 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:

OptionTypeDescription
attributesobjectAttributes to set on the element, such as a tooltip attribute your CSS reads.
classNamestringClass name(s) for the element. Nothing is styled for you.
contentstring | HTMLElement | FunctionThe contents — usually an icon.
elementHTMLElement | stringAn existing element, or a selector for one, to use instead of building one.
indexnumberThe order among the controls at the same position.
onClickFunctionCalled when the control is clicked, in addition to moving the map.
positionControlPositionWhere the control goes on the map.
statesButtonStatesWhat each state looks like, if you want the control to reflect one.
tagstringThe element to build. Defaults to button.

See ButtonOptions for the rest.

The control's own behaviour, and the marker​

OptionTypeDefaultDescription
action'pan' | 'center'panWhat clicking does with the map.
buttonbooleantruefalse for the marker on its own, with no control on the map.
autoLocatebooleantrueWhether the control calls locate() itself. Set it to false if something else on the page already does.
centerOnFirstFindbooleanfalseWhether to move the map to the user the first time a location is found.
locateOptionsLocateOptionsPassed through to locate().
markerboolean | Marker | MarkerOptionsfalse for no marker, a Marker to use as it is, or options merged over the default.
showWhenLocatedbooleantrueWhether the control is only put on the map once a location has been found.
zoomnumberThe 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​

PropertyTypeDescription
isLocatedbooleanWhether a location has been found yet. Read only.
locationLocationPosition | undefinedThe last position that was found. Read only.
markerMarker | undefinedThe marker showing where the user is. Read only.

Plus everything from Button and Control.

Events​

EventDescription
locatedA 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​

MethodDescription
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.