how to detect when geojson is fullly loaded in Google Maps

I have a google maps with a geojson that is loaded into the map.

Because the geojson takes 2-4 seconds to load, I want to put a loading circle.
However, when attempting the loading circle, the map comes up only when the tiles are loaded before the geojson is loaded. What is the proper lifecycle marker for waiting until the geojson is loaded?
Thanks

HTML:

<!DOCTYPE html>
<html>
<head>
    <title>Simple Map</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
    <link rel="stylesheet" type="text/css" href="css/main.css" />
    <script src="js/main.js"></script>
</head>
<body>
<h1>Hex Map</h1>
<div id="map_wrapper">
    <div id="map"></div>
</div>
<div id="mapinfo">Testbox</div>

<!-- Async script executes immediately and must be after any DOM elements used in callback. -->
<script
        src="https://maps.googleapis.com/maps/api/js?key=THEKEY&callback=initMap&v=weekly"
        async
></script>
</body>
</html>

JS:

let map;
var infowindow = null;

function initMap() {

    map = new google.maps.Map(document.getElementById("map"), {
        center: {lat: 30.1572523, lng: -92.0299477},
        zoom: 3,
    });

    google.maps.event.addListenerOnce(map, 'bounds_changed', function () {
        //alert(map.getBounds().getNorthEast().lat());
    });

    map.data.loadGeoJson(
      "hexmap.geojson"
    );

    google.maps.event.addListenerOnce(map, 'tilesloaded', function () {
        document.getElementById('map').style.opacity = 1;
    })
    map.data.setStyle({
        fillColor: 'green',
        strokeWeight: 1
    })

    // map.data.addListener('mouseover', function(event) {
    //     console.log(event.feature.getProperty('_uid1_'))
    //     document.getElementById('mapinfo').innerHTML = event.feature.getProperty('_uid1_');
    // })

    const constentString = 'hex + '

    map.data.addListener('click', function(event) {
        message = 'hex id: ' + event.feature.getProperty('_uid1_');
        infowindow && infowindow.close();
        infowindow = new google.maps.InfoWindow();
        infowindow.setContent(message);
        infowindow.setPosition(event.latLng);
        infowindow.open(map);

    })


}
//"https://drive.google.com/file/d/1v-VZtbbz4H2KiMvkRcc7nL_6JKQqlHwM/view?usp=sharing'"

CSS:

#map {
    height: 600px;
    width:800px;
    opacity:0;
}

/* Optional: Makes the sample page fill the window. */
html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

#map_wrapper {
    background:url(https://ressio.github.io/lazy-load-xt/dist/loading.gif) center center no-repeat;
    height: 600px;
    width:800px;
}