Browse Source

structures: performances optimization

Olivier Massot 4 years ago
parent
commit
a6ac6d668a
8 changed files with 238 additions and 1734 deletions
  1. 58 52
      components/Ui/Map/Structures.vue
  2. 15 13
      layouts/default.vue
  3. 36 0
      lib/geo.js
  4. BIN
      logo.png
  5. 6 0
      nuxt.config.js
  6. 2 1
      package.json
  7. 120 1667
      pages/structures_adherentes/index.vue
  8. 1 1
      yarn.lock

+ 58 - 52
components/Ui/Map/Structures.vue

@@ -1,35 +1,7 @@
 <template>
   <LayoutContainer>
     <v-responsive :aspect-ratio="1" width="100%">
-      <no-ssr>
-        <l-map
-          id="map"
-          ref="vMap"
-          :zoom="zoom"
-          :center="center"
-          :bounds="bounds"
-          :options="{scrollWheelZoom: false, zoomSnap: 0.25}"
-          @update:bounds="boundsUpdated"
-        >
-          <l-tile-layer
-            url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"
-            attribution="&copy; <a href='http://osm.org/copyright'>OpenStreetMap</a> contributors"
-          />
-          <v-marker-cluster>
-            <l-marker
-              v-for="structure in structures"
-              :key="structure.id"
-              :lat-lng="[structure.latitude, structure.longitude]"
-            >
-              <l-popup>
-                <b>{{ structure.name }}</b><br>
-                {{ structure.postalCode }} {{ structure.addressCity }}<br>
-                <a :href="structure.website" target="_blank">{{ structure.website }}</a>
-              </l-popup>
-            </l-marker>
-          </v-marker-cluster>
-        </l-map>
-      </no-ssr>
+      <div id="map" />
     </v-responsive>
 
     <div class="advice">
@@ -50,6 +22,13 @@
 </template>
 
 <script>
+import 'leaflet/dist/leaflet.css'
+let L
+if (typeof window !== 'undefined') {
+  // only require leaflet on client-side
+  L = require('leaflet')
+}
+
 export default {
   props: {
     structures: {
@@ -59,18 +38,9 @@ export default {
     }
   },
   data () {
-    const defaultCenter = [46.71, 1.94]
-    const defaultZoom = 5.75
-    const defaultBounds = [[51.03, -5.78], [41.2, 9.70]]
-
     return {
-      defaultCenter,
-      defaultZoom,
-      defaultBounds,
-      center: defaultCenter,
-      zoom: defaultZoom,
-      bounds: defaultBounds,
-      isFirstRendering: true,
+      map: null,
+      defaultBounds: [[51.03, -5.78], [41.2, 9.70]],
       shortcuts: [
         { src: '/images/metropole.png', alt: 'Metropole', bounds: [[51.03, -5.78], [41.2, 9.70]] },
         { src: '/images/guadeloupe.png', alt: 'Guadeloupe', bounds: [[16.62, -62.03], [15.74, -60.97]] },
@@ -83,17 +53,61 @@ export default {
     }
   },
   watch: {
-    structures () {
+    structures (oldval, newval) {
+      if (oldval !== newval) {
+        this.populateMarkers()
+      }
+
       if (this.zoomRequired) {
         this._fitBoundsToMarkers()
         this.zoomRequired = false
       }
     }
   },
+  mounted () {
+    const options = { scrollWheelZoom: false, zoomSnap: 0.25 }
+    const defaultCenter = [46.71, 1.94]
+    const defaultZoom = 5.75
+    const layerSource = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png'
+    const attribution = '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
+
+    this.map = L.map('map', options)
+    this.map.setView(defaultCenter, defaultZoom)
+    L.tileLayer(layerSource, { attribution }).addTo(this.map)
+
+    this.populateMarkers()
+
+    this.map.on('zoomend moveend', () => {
+      this.$emit('boundsUpdated', this.map.getBounds())
+    })
+  },
+  beforeDestroy () {
+    if (this.map) {
+      this.map.remove()
+    }
+  },
   methods: {
+    populateMarkers () {
+      // remove any existant marker layers
+      this.map.eachLayer((layer) => {
+        if (layer instanceof L.MarkerClusterGroup) {
+          this.map.removeLayer(layer)
+        }
+      })
+
+      // populate new layer
+      const clusters = L.markerClusterGroup()
+      for (const s of this.structures) {
+        if (!s.latitude || !s.longitude) { continue }
+
+        const marker = L.marker([s.latitude, s.longitude])
+        marker.bindPopup(`<b>${s.name}</b><br/>${s.postalCode} ${s.addressCity}<br/><a href="${s.website}" target="_blank">${s.website}</a>`)
+        clusters.addLayer(marker)
+      }
+      this.map.addLayer(clusters)
+    },
     setMapBounds (bounds) {
-      this.bounds = bounds
-      this.$refs.vMap.mapObject.fitBounds(bounds) // << without this, the new bounds may not be properly set when the current view overlaps the new bounds.
+      this.map.fitBounds(bounds) // << without this, the new bounds may not be properly set when the current view overlaps the new bounds.
     },
     resetBounds () {
       this.setMapBounds(this.defaultBounds)
@@ -109,15 +123,7 @@ export default {
       if (!coords.length > 0) {
         return
       }
-      this.$refs.vMap.mapObject.fitBounds(coords)
-    },
-    boundsUpdated (newBounds) {
-      // do not send and event on first automatic rendering
-      if (this.isFirstRendering) {
-        this.isFirstRendering = false
-        return
-      }
-      this.$emit('boundsUpdated', newBounds)
+      this.setMapBounds(coords)
     }
   }
 }

+ 15 - 13
layouts/default.vue

@@ -1,18 +1,20 @@
 <template>
-  <v-app dark>
-    <v-main>
-      <v-container>
-        <Nuxt />
-      </v-container>
-    </v-main>
+  <main>
+    <v-app dark>
+      <v-main>
+        <v-container>
+          <Nuxt />
+        </v-container>
+      </v-main>
 
-    <v-footer
-      :absolute="!fixed"
-      app
-    >
-      <span>&copy; Opentalent {{ new Date().getFullYear() }}</span>
-    </v-footer>
-  </v-app>
+      <v-footer
+        :absolute="!fixed"
+        app
+      >
+        <span>&copy; Opentalent {{ new Date().getFullYear() }}</span>
+      </v-footer>
+    </v-app>
+  </main>
 </template>
 
 <script>

+ 36 - 0
lib/geo.js

@@ -0,0 +1,36 @@
+/**
+ * Converts numeric degrees to radians
+ * @param val
+ * @returns {number}
+ */
+function toRad (val) {
+  return val * Math.PI / 180
+}
+
+/**
+ * This function takes in latitude and longitude of two location and returns the distance between them as the crow flies (in km)
+ * @param lat1
+ * @param lon1
+ * @param lat2
+ * @param lon2
+ * @returns {number}
+ */
+function sphericDistance (lat1, lon1, lat2, lon2) {
+  lat1 = Number.parseFloat(lat1)
+  lon1 = Number.parseFloat(lon1)
+  lat2 = Number.parseFloat(lat2)
+  lon2 = Number.parseFloat(lon2)
+
+  const R = 6371 // km
+  const dLat = toRad(lat2 - lat1)
+  const dLon = toRad(lon2 - lon1)
+  lat1 = toRad(lat1)
+  lat2 = toRad(lat2)
+
+  const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
+    Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2)
+  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
+  return R * c
+}
+
+export default sphericDistance

BIN
logo.png


+ 6 - 0
nuxt.config.js

@@ -97,5 +97,11 @@ export default {
 
   // Build Configuration: https://go.nuxtjs.dev/config-build
   build: {
+  },
+  publicRuntimeConfig: {
+    baseURL: process.env.NODE_ENV === 'production' ? 'https://local.api.opentalent.fr' : 'https://local.api.opentalent.fr'
+  },
+  privateRuntimeConfig: {
+    baseURL: process.env.NODE_ENV === 'production' ? 'https://local.api.opentalent.fr' : 'http://nginx'
   }
 }

+ 2 - 1
package.json

@@ -3,7 +3,7 @@
   "version": "1.0.0",
   "private": true,
   "scripts": {
-    "dev": "nuxt --hostname '0.0.0.0' --port 3333",
+    "dev": "nuxt --hostname '0.0.0.0' --port 3004",
     "build": "nuxt build",
     "start": "nuxt start",
     "generate": "nuxt generate",
@@ -19,6 +19,7 @@
     "@nuxt/image": "^0.6.0",
     "@nuxtjs/i18n": "^7.0.3",
     "core-js": "^3.15.1",
+    "leaflet": "^1.7.1",
     "nuxt": "^2.15.7",
     "nuxt-fontawesome": "^0.4.0",
     "nuxt-leaflet": "^0.0.25",

File diff suppressed because it is too large
+ 120 - 1667
pages/structures_adherentes/index.vue


+ 1 - 1
yarn.lock

@@ -7331,7 +7331,7 @@ leaflet.markercluster@^1.4.1:
     jshint "^2.13.1"
     npm-ci "0.0.2"
 
-leaflet@^1.6.0:
+leaflet@^1.6.0, leaflet@^1.7.1:
   version "1.7.1"
   resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.7.1.tgz#10d684916edfe1bf41d688a3b97127c0322a2a19"
   integrity sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw==

Some files were not shown because too many files changed in this diff