Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-1/work
This commit is contained in:
commit
b0cd3140bd
11 changed files with 70 additions and 35 deletions
|
|
@ -63,6 +63,29 @@ export function ensureGeocoder(provider = 'mapbox') {
|
|||
// `new mapboxgl.Popup` throws on the first pin click. Now the library's engineFor (one copy).
|
||||
export { engineFor as glFor } from '@map/composables/useMapProvider.js'
|
||||
|
||||
// Resolves once every GeoJSON source on the map has LOADED and a frame has RENDERED after that,
|
||||
// or after `timeoutMs` (a safety net, never a hang). The views flipped `dataReady` (which hides the
|
||||
// LoadingGlobe) right after addSource(); the engine then still tiles tens of thousands of points in
|
||||
// its worker, so the globe disappeared and the map sat EMPTY. Measured on the DX-life gallery: 0
|
||||
// dots for 20 s, then 19,376 features from 30 s. Not 'idle': an animating map may never go idle.
|
||||
export function whenGeojsonDrawn(map, timeoutMs = 45000) {
|
||||
return new Promise((resolve) => {
|
||||
if (!map) return resolve(false)
|
||||
let done = false
|
||||
const finish = (drawn) => { if (done) return; done = true; clearTimeout(timer); map.off('sourcedata', check); resolve(drawn) }
|
||||
const timer = setTimeout(() => finish(false), timeoutMs)
|
||||
const check = () => {
|
||||
try {
|
||||
const srcs = (map.getStyle() || {}).sources || {}
|
||||
const ids = Object.keys(srcs).filter((k) => srcs[k].type === 'geojson')
|
||||
if (ids.every((id) => map.isSourceLoaded(id))) { map.once('render', () => finish(true)); map.triggerRepaint() }
|
||||
} catch (_) { /* style mid-swap: wait for the next sourcedata */ }
|
||||
}
|
||||
map.on('sourcedata', check)
|
||||
check()
|
||||
})
|
||||
}
|
||||
|
||||
// Verification handle (the gospel-resources __grState contract): what the ACTIVE view's map
|
||||
// actually did, so a check can assert "loaded" rather than inferring it from missing requests.
|
||||
// window.__pplrMap() -> { engine, loaded, styleLayers, pplrLayers }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { dataUrl, glFor, exposeMap } from '../utils/pplrData.js'
|
||||
import { dataUrl, glFor, exposeMap, whenGeojsonDrawn } from '../utils/pplrData.js'
|
||||
/**
|
||||
* pplr-coverage.vue — Country choropleth: avg # of locales filled per PG in that country.
|
||||
*
|
||||
|
|
@ -118,6 +118,8 @@ onMounted(async () => {
|
|||
.setLngLat(f.geometry.coordinates).setHTML(popupForPG(f.properties)).addTo(map.value)
|
||||
})
|
||||
status.value = `Ready · ${countryStats.size} countries colored by avg translation locales / 17 (all ${[...countryStats.values()].reduce((n, c) => n + c.pgCount, 0).toLocaleString('en-US')} PG-in-country rows)`
|
||||
// keep the LoadingGlobe up until the pins are actually drawn, not merely added
|
||||
await whenGeojsonDrawn(map.value)
|
||||
dataReady.value = true
|
||||
} catch (e) {
|
||||
status.value = `Error: ${e.message}`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { dataUrl, glFor, exposeMap } from '../utils/pplrData.js'
|
||||
import { dataUrl, glFor, exposeMap, whenGeojsonDrawn } from '../utils/pplrData.js'
|
||||
/**
|
||||
* pplr-language-families.vue — PG pins colored by PPLR ethnolinguistic family.
|
||||
*
|
||||
|
|
@ -490,6 +490,8 @@ onMounted(async () => {
|
|||
|
||||
const coverage = Math.round(100 * matched / fc.features.length)
|
||||
status.value = `Ready · ${fc.features.length.toLocaleString()} pins · ${coverage}% family coverage · top-25 = ${Math.round(100 * inTop25 / fc.features.length)}%`
|
||||
// keep the LoadingGlobe up until the pins are actually drawn, not merely added
|
||||
await whenGeojsonDrawn(map.value)
|
||||
dataReady.value = true
|
||||
} catch (err) {
|
||||
status.value = `Error: ${err.message}`
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* Individual pins at all zoom levels; click pin for full Rosetta popup; hover country for highlight.
|
||||
*/
|
||||
import { inject, onMounted, onBeforeUnmount, ref } from 'vue'
|
||||
import { glFor, exposeMap } from '../utils/pplrData.js'
|
||||
import { glFor, exposeMap, whenGeojsonDrawn } from '../utils/pplrData.js'
|
||||
import { useMapInstance } from '@map/composables/useMapInstance.js'
|
||||
import { addCountryPolygons, addPGPoints, popupForPG, POPUP_CSS } from '../utils/pplrMap.js'
|
||||
import LoadingGlobe from '../components/LoadingGlobe.vue'
|
||||
|
|
@ -50,6 +50,8 @@ onMounted(async () => {
|
|||
.addTo(map.value)
|
||||
})
|
||||
status.value = `Ready · ${fc.features.length.toLocaleString('en-US')} PG-in-country pins · click any pin`
|
||||
// keep the LoadingGlobe up until the pins are actually drawn, not merely added
|
||||
await whenGeojsonDrawn(map.value)
|
||||
dataReady.value = true
|
||||
} catch (e) {
|
||||
status.value = `Error: ${e.message}`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { dataUrl, glFor, exposeMap } from '../utils/pplrData.js'
|
||||
import { dataUrl, glFor, exposeMap, whenGeojsonDrawn } from '../utils/pplrData.js'
|
||||
/**
|
||||
* pplr-religion.vue — PG pins colored by primary religion.
|
||||
*
|
||||
|
|
@ -267,6 +267,8 @@ onMounted(async () => {
|
|||
const dominant = RELIGION_GROUPS.reduce((a, b) => (counts[a.key] || 0) > (counts[b.key] || 0) ? a : b)
|
||||
// Per user 2026-05-02: drop the "Ready" prefix — it was unclear and chewed up width.
|
||||
status.value = `${pgData.value.features.length.toLocaleString()} pins · ${dominant.label} most common (${(counts[dominant.key]||0).toLocaleString()})`
|
||||
// keep the LoadingGlobe up until the pins are actually drawn, not merely added
|
||||
await whenGeojsonDrawn(map.value)
|
||||
dataReady.value = true
|
||||
} catch (err) {
|
||||
status.value = `Error: ${err.message}`
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
* Click any pin → popup with full Rosetta table.
|
||||
*/
|
||||
import { inject, onMounted, onBeforeUnmount, ref } from 'vue'
|
||||
import { glFor, exposeMap } from '../utils/pplrData.js'
|
||||
import { glFor, exposeMap, whenGeojsonDrawn } from '../utils/pplrData.js'
|
||||
import { useMapInstance } from '@map/composables/useMapInstance.js'
|
||||
import { addCountryPolygons, loadOnce, popupForPG, POPUP_CSS } from '../utils/pplrMap.js'
|
||||
import LoadingGlobe from '../components/LoadingGlobe.vue'
|
||||
|
|
@ -141,6 +141,8 @@ onMounted(async () => {
|
|||
map.value.on('mouseleave', 'rosetta-pin', () => map.value.getCanvas().style.cursor = '')
|
||||
|
||||
status.value = `Ready · ${pgFc.features.length} pins · ${rosKeys.size} Rosetta samples (gold ★)`
|
||||
// keep the LoadingGlobe up until the pins are actually drawn, not merely added
|
||||
await whenGeojsonDrawn(map.value)
|
||||
dataReady.value = true
|
||||
} catch (e) {
|
||||
status.value = `Error: ${e.message}`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { dataUrl, glFor, exposeMap } from '../utils/pplrData.js'
|
||||
import { dataUrl, glFor, exposeMap, whenGeojsonDrawn } from '../utils/pplrData.js'
|
||||
/**
|
||||
* pplr-translations.vue — PG name in all 17 locales.
|
||||
*
|
||||
|
|
@ -92,6 +92,8 @@ onMounted(async () => {
|
|||
})
|
||||
|
||||
status.value = `${fc.features.length.toLocaleString()} pins · click any pin to see all 17 locale names`
|
||||
// keep the LoadingGlobe up until the pins are actually drawn, not merely added
|
||||
await whenGeojsonDrawn(map.value)
|
||||
dataReady.value = true
|
||||
} catch (err) {
|
||||
status.value = `Error: ${err.message}`
|
||||
|
|
|
|||
|
|
@ -837,7 +837,7 @@
|
|||
"bundle": "pplr-data-maps",
|
||||
"scriptUrl": "./pplr-data-maps/pplr-data-maps.js",
|
||||
"output": "dx-maps/pplr-data-maps/pplr-data-maps.js",
|
||||
"integrity": "sha384-nMEYoH17y92xbERsRYP3x9sroR//lz8NvipOQvUfV8zV40pJ7DmW0avOm7sARD82",
|
||||
"integrity": "sha384-e6wVt+dC86mFb8TgX2jBn7wh/R9gA6rGxNgS6umNBeNrir3TstupaJKf4XElRP2T",
|
||||
"elements": [
|
||||
"pplr-data-maps"
|
||||
],
|
||||
|
|
@ -853,7 +853,7 @@
|
|||
"scriptUrl": "./pplr-data-maps/pplr-data-maps.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./pplr-data-maps/pplr-data-maps/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-nMEYoH17y92xbERsRYP3x9sroR//lz8NvipOQvUfV8zV40pJ7DmW0avOm7sARD82\" crossorigin=\"anonymous\"></script>\n<pplr-data-maps profile-config='{\"profile\":\"pplr-data-maps\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></pplr-data-maps>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-e6wVt+dC86mFb8TgX2jBn7wh/R9gA6rGxNgS6umNBeNrir3TstupaJKf4XElRP2T\" crossorigin=\"anonymous\"></script>\n<pplr-data-maps profile-config='{\"profile\":\"pplr-data-maps\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></pplr-data-maps>"
|
||||
},
|
||||
"bundle": "pplr-data-maps"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -837,7 +837,7 @@
|
|||
"bundle": "pplr-data-maps",
|
||||
"scriptUrl": "./pplr-data-maps/pplr-data-maps.js",
|
||||
"output": "dx-maps/pplr-data-maps/pplr-data-maps.js",
|
||||
"integrity": "sha384-nMEYoH17y92xbERsRYP3x9sroR//lz8NvipOQvUfV8zV40pJ7DmW0avOm7sARD82",
|
||||
"integrity": "sha384-e6wVt+dC86mFb8TgX2jBn7wh/R9gA6rGxNgS6umNBeNrir3TstupaJKf4XElRP2T",
|
||||
"elements": [
|
||||
"pplr-data-maps"
|
||||
],
|
||||
|
|
@ -853,7 +853,7 @@
|
|||
"scriptUrl": "./pplr-data-maps/pplr-data-maps.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./pplr-data-maps/pplr-data-maps/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-nMEYoH17y92xbERsRYP3x9sroR//lz8NvipOQvUfV8zV40pJ7DmW0avOm7sARD82\" crossorigin=\"anonymous\"></script>\n<pplr-data-maps profile-config='{\"profile\":\"pplr-data-maps\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></pplr-data-maps>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-e6wVt+dC86mFb8TgX2jBn7wh/R9gA6rGxNgS6umNBeNrir3TstupaJKf4XElRP2T\" crossorigin=\"anonymous\"></script>\n<pplr-data-maps profile-config='{\"profile\":\"pplr-data-maps\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></pplr-data-maps>"
|
||||
},
|
||||
"bundle": "pplr-data-maps"
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <pplr-data-maps> custom element. -->
|
||||
<script src="../pplr-data-maps.js" integrity="sha384-nMEYoH17y92xbERsRYP3x9sroR//lz8NvipOQvUfV8zV40pJ7DmW0avOm7sARD82" crossorigin="anonymous"></script>
|
||||
<script src="../pplr-data-maps.js" integrity="sha384-e6wVt+dC86mFb8TgX2jBn7wh/R9gA6rGxNgS6umNBeNrir3TstupaJKf4XElRP2T" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
Loading…
Reference in a new issue