Saturday, April 20, 2024
HomeJavaScriptUtilizing Google Maps with Alpine.js

Utilizing Google Maps with Alpine.js


It has been a short time since I’ve blogged about Alpine.js, and I believed an instance of integrating Google Maps with it could be a great way to proceed my path to turning into comfy with the framework. I imagined it could be pretty easy, however in constructing a couple of demos I bumped into some fascinating points that helped me study a bit extra about Alpine. Let’s have a look.

My Information

All of my examples are going to make use of the identical set of knowledge – a couple of Spirit Halloween shops near my location. I went to their web site, opened up dev instruments, and copied the situation of seven shops. I tweaked the info on one which was tremendous shut to a different location and added a worth that represents if a retailer is open twenty-four hours a day. Spirit shops do not try this, however I had a plan for it later.

[
    {
        "lat": 30.175776,
        "lng": -92.077008,
        "allday":true
    },
    {
        "lat": 30.173529,
        "lng": -92.078997,
        "allday":true
    },
    {
        "lat": 30.394324,
        "lng": -91.086551,
        "allday":false
    },
    {
        "lat": 30.176162,
        "lng": -93.219241,
        "allday":false
    },
    {
        "lat": 31.269887,
        "lng": -92.46034,
        "allday":false
    },
    {
        "lat": 29.61629,
        "lng": -90.757389,
        "allday":false
    },
    {
        "lat": 30.486217,
        "lng": -90.45677,
        "allday":false
    }
]

Beginning Easy – Static

For my first instance, I made a decision to make use of the Google Maps Static Map API. This has been a favourite API of mine for years because it’s much less an API and only a URL. For cases the place you do not want a dynamic map, the Static Map API is straightforward as hell and simply requires you to craft a URL with location data in it. I started by constructing a brand new Alpine software that may render the situation of every retailer together with a map. I am displaying the latitude and longitude values which you’d most likely by no means do as ‘common’ folks do not actually care. As an alternative, I would show a road tackle.

<div x-data="app">
    <template x-for="retailer in shops">
        <p>
            Retailer location: <span x-text="retailer.lat"></span>,<span x-text="retailer.lng"></span><br/>
            <img :src="getImageUrl(retailer.lat,retailer.lng)">
        </p>
    </template>
</div>

For every retailer, I am calling out to a technique, getImageUrl, that may return the Static Map API URL I want for my pictures. Here is my Alpine software in its entirety, besides with the JSON trimmed a bit for dimension.

const MAP_KEY = 'AIzaSyC3hC35ehz1oAfUll7q7qzUlPa27Gz5g5g';

doc.addEventListener('alpine:init', () => {
  Alpine.knowledge('app', () => ({
        shops:getStores(),
        getImageUrl(lat,lng) {
            return `https://maps.googleapis.com/maps/api/staticmap?middle=${lat},${lng}&zoom=15&dimension=400x400&maptype=roadmap&markers=colour:bluepercent7C${lat},${lng}&key=${MAP_KEY}`
        }
  }))
});

/* 
think about this was an API name..
*/
operate getStores() {
    return [
        // list of stores here
    ]
}

For instance, the URL for the primary retailer is:

https://maps.googleapis.com/maps/api/staticmap? 
middle=30.175776,-92.077008&zoom=15&dimension=400x400&maptype=roadmap
&markers=colour:bluepercent7C30.175776,-92.077008
&key=AIzaSyC3hC35ehz1oAfUll7q7qzUlPa27Gz5g5g

You may see that blow:

Static Map image

Discover that I middle my map on the location and add a marker so it is actually apparent what I am mentioning. Markers can have completely different colours and labels, however I am retaining it easy for now. Here is a CodePen displaying the entire software.

See the Pen Alpine + Google Maps 1 by Raymond Camden (@cfjedimaster) on CodePen.

A Dynamic Map

For my second instance, I wished to do a correct dynamic Google Map, however simply that, and nothing extra. Usually I’d not use Alpine.js if my solely purpose was to render a map and nothing else. The Google Map JavaScript library is not arduous to make use of and if I do not want Alpine, then there isn’t any cause to load it.

However in engaged on this demo, I bumped into some fascinating points. First off, each Google Maps and Alpine load asynchronously. If in my subsequent model I need to add Alpine performance that’s built-in with the map, I would want a approach to deal with that. I did some Googling and got here throughout this useful useful resource: Calling Alpine.js strategies from third-party scripts. The weblog entry describes a technique by which you hearth off a customized occasion out of your Google Maps code that Alpine will take heed to. Their code did not work for me immediately, I needed to tweak it a bit, however let’s have a look.

First, here is the way you add the Google Maps JavaScript SDK (with some extra line breaks for readability):

<script
src="https://maps.googleapis.com/maps/api/js? 
key=AIzaSyC3hC35ehz1oAfUll7q7qzUlPa27Gz5g5g 
&callback=initMap&v=weekly"
      defer
></script>

Discover two necessary issues right here – first my key (which I’ve locked to a couple domains so it is protected to be right here) and extra importantly, the callback operate. This will likely be known as when Google Maps is prepared.

Here is my initMap, taken from the Google Maps docs and modified barely:

// earlier within the code: 
let map;
// The placement of Uluru
const uluru = { lat: -25.344, lng: 131.031 };           


operate initMap() {
    
  // The map, centered at Uluru
  map = new google.maps.Map(doc.getElementById("map"), {
    zoom: 4,
    middle: uluru,
  });

  window.dispatchEvent(new Occasion('map-loaded'));
}

Discover how I am dispatching a customized occasion? Again on the Alpine facet, I can then add an app-wide listener for that like so:

<div x-data="app" @map-loaded.window="doMapStuff()">
    
    <div id="map"></div>
</div>

Now let’s return to Alpine:

doc.addEventListener('alpine:init', () => {
  Alpine.knowledge('app', () => ({
        init() {
            if("google" in window) this.doMapStuff(); 
        },
        doMapStuff() {
            console.log('do map stuff');
            
            // The marker, positioned at Uluru
            const marker = new google.maps.Marker({
                place: uluru,
                map: map,
            });
        }
  }))
});

First, it is doable Google Maps masses earlier than Alpine, so in init, I examine for it and if it is there, I do my map stuff. That operate, doMapStuff, is identical one known as by the Alpine occasion listener. So both means – I am lined. On this case, I simply add a marker to the map. You may see the entire demo beneath.

See the Pen Alpine + Google Maps 2 by Raymond Camden (@cfjedimaster) on CodePen.

Map with Alpine Information

Alright, so let’s mix that map knowledge from the primary pattern with the dynamic model from the second instance. First, I modified the HTML a bit to incorporate a brand new management that lets the consumer filter to shops open twenty-four hours a day:

<div x-data="app" @map-loaded.window="doMapStuff()">
    <h2>Shops</h2>
    <p>
    <label><enter kind="checkbox" x-model="alldayfilter"> Filter to 24 Hour Shops</label>
    </p>
    <div id="map"></div>
</div>

Within the JavaScript, I started by modifying doMapStuff to render one marker per retailer:

doMapStuff() {
    console.log('do map stuff');
    
    this.shops.forEach(retailer => {
        retailer.marker = new google.maps.Marker({
            place: { lat: retailer.lat, lng: retailer.lng },
            map: map,
        });
    });

}

Discover that I am making a marker object and storing it in my retailer knowledge. Why? This enables me to toggle visibility when the checkbox is modified. To assist that function I used a watcher:

this.$watch('alldayfilter', val => {
    this.shops.forEach(retailer => {
        if(!val) retailer.marker.setVisible(true);
        else {
            if(!retailer.allday) retailer.marker.setVisible(false);
        }
    });
});

When alldayfilter modifications, I both set each marker to seen or conditionally disguise people who aren’t open all day.

As soon as once more, here is the CodePen:

See the Pen Alpine + Google Maps 2 by Raymond Camden (@cfjedimaster) on CodePen.

That is it – let me know what you assume, and in case you’ve used Google Maps with Alpine, give me a shout-out so I can see it in motion!

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments