UPG Neighbor Campaigns: hovering a dot names its group
After a language was picked, its believer (green) and unreached (red) dots were anonymous until clicked, and a green dot could not be clicked at all. Hovering either now shows the group and its country, as Mobilize does.
This commit is contained in:
parent
77c7b16fef
commit
beb82f2e2e
1 changed files with 13 additions and 0 deletions
|
|
@ -82,6 +82,9 @@ function exportAll() {
|
|||
// ─── Map: believers (green) and the unreached they would reach (red) ─────────
|
||||
const SRC_R = 'cp-r', SRC_U = 'cp-u'
|
||||
const fc = (features) => ({ type: 'FeatureCollection', features })
|
||||
// Hover label: after a language is picked, its believers (green) and the unreached they reach (red)
|
||||
// were anonymous until clicked, and a green dot could not be clicked at all. Same label as Mobilize.
|
||||
const hover = ref(null) // { x, y, text }
|
||||
const pt = (g) => ({ type: 'Feature', geometry: { type: 'Point', coordinates: [g.lng, g.lat] }, properties: { id: g.pgid, pop: g.pop, b: g.believers } })
|
||||
function setSrc(m, id, d) { const s = m.getSource(id); if (s) s.setData(d); else m.addSource(id, { type: 'geojson', data: d }) }
|
||||
let repaintPending = false
|
||||
|
|
@ -131,6 +134,14 @@ onMounted(async () => {
|
|||
})
|
||||
m.on('mouseenter', 'cp-u', () => { m.getCanvas().style.cursor = 'pointer' })
|
||||
m.on('mouseleave', 'cp-u', () => { m.getCanvas().style.cursor = '' })
|
||||
const byId = (id) => active.value && [...active.value.reached, ...active.value.unreached].find((g) => g.pgid === id)
|
||||
for (const id of ['cp-u', 'cp-r']) {
|
||||
m.on('mousemove', id, (ev) => {
|
||||
const g = byId(ev.features?.[0]?.properties?.id)
|
||||
hover.value = g ? { x: ev.point.x, y: ev.point.y, text: `${g.name} · ${g.country}` } : null
|
||||
})
|
||||
m.on('mouseleave', id, () => { hover.value = null })
|
||||
}
|
||||
})
|
||||
m.on('style.load', repaint)
|
||||
})
|
||||
|
|
@ -169,6 +180,7 @@ useShadowStyles(`
|
|||
.cp-line { display:flex; justify-content:space-between; gap:8px; font-size:12.5px; padding:5px 0; border-bottom:1px solid #f1f3f6; }
|
||||
.cp-line button { border:0; background:none; padding:0; font:inherit; color:${NAVY}; cursor:pointer; text-align:left; }
|
||||
.cp-note { padding:14px; color:#6b7280; font-size:13px; line-height:1.45; }
|
||||
.cp-hover { position:absolute; z-index:25; pointer-events:none; background:rgba(0,27,68,.92); color:#fff; font-size:12px; line-height:1.3; padding:5px 8px; border-radius:6px; max-width:260px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
||||
.cp-maperr { position:absolute; right:12px; top:12px; z-index:15; background:#fff; border:1px solid #d9dee6; border-radius:8px; padding:8px 12px; font-size:13px; color:#6b7280; }
|
||||
@media (max-width:760px) { .cp-panel { top:auto; left:6px; right:6px; bottom:6px; width:auto; height:55%; } }
|
||||
`, 'upgn-campaigns')
|
||||
|
|
@ -178,6 +190,7 @@ useShadowStyles(`
|
|||
<div class="cp-root">
|
||||
<div ref="mapContainer" class="cp-map"></div>
|
||||
<div v-if="mapError" class="cp-maperr" role="status">{{ mapError }}</div>
|
||||
<div v-if="hover" class="cp-hover" :style="{ left: hover.x + 12 + 'px', top: hover.y + 12 + 'px' }">{{ hover.text }}</div>
|
||||
|
||||
<aside class="cp-panel">
|
||||
<template v-if="!active">
|
||||
|
|
|
|||
Loading…
Reference in a new issue