PageSourceSearch

https://alsimon.net/js/bubble-placement.js

js alsimon.net collected 2026-10-09 01:08:41 UTC 2,698 bytes, 45 lines download raw bytes

1// Direction d'affichage d'une bulle de dialogue / emoticon par rapport à la tête
2// de son propriétaire. Remplace l'ancien positionnement libre en pixels
3// (`js/bubble-offset.js`, supprimé) : une position en pixels dépend du zoom, or
4// le jeu a deux zooms fixes (z18 mobile / z19 bureau, voir map.js#FIXED_ZOOM) et
5// un réglage fait à l'un tombait toujours faux à l'autre — l'auteur devait
6// valider chaque scène deux fois, et la mise à l'échelle ×2/÷2 de secours
7// n'était qu'une approximation qui « bougeait mal » dès que la bulle visait un
8// point précis (typiquement : à côté d'un autre habitant).
9//
10// Huit directions (les 4 cardinales + les 4 diagonales), choisies par l'auteur
11// par réplique/emoticon dans l'éditeur (pavé 3×3, voir
12// editor/js/entry-detail-panel.js) :
13//   - `top` (défaut, ou valeur absente/inconnue) : la bulle part au-dessus de la
14//     tête — comportement historique, rendue comme la tooltip du marqueur.
15//   - les 7 autres (`right`, `bottom`, `left`, `top-right`, `top-left`,
16//     `bottom-right`, `bottom-left`) : la bulle part de ce côté / ce coin de la
17//     tête (voir js/population.js#partitionBubbles, qui en fait une bulle
18//     flottante indépendante).
19// Dans tous les cas ce n'est qu'un POINT DE DÉPART : le solveur anti-chevauchement
20// (js/dialogue-layout.js#computeBubbleLayout) écarte ensuite toute bulle qui en
21// recouvre une autre — ou qui tomberait sur la tête d'un habitant voisin —, quel
22// que soit son `placement`.
23// Indépendant du zoom par construction : la bulle reste collée à la tête, seul le
24// côté change ; Leaflet reprojette la tête depuis lat/lng à n'importe quel zoom.
25//
26// Pas de dépendance navigateur ici (fonctions pures) : ce module est importé
27// transitivement côté Node par editor/ai-server/pregenerate.mjs, comme le reste
28// de la chaîne population.js.
29
30export const BUBBLE_PLACEMENTS = [
31  'top', 'top-right', 'right', 'bottom-right', 'bottom', 'bottom-left', 'left', 'top-left'
32];
33export const DEFAULT_PLACEMENT = 'top';
34
35// Les directions qui sortent de l'empilement `top` pour devenir une bulle
36// flottante (voir population.js) — toutes sauf `top`.
37export const FLOATING_PLACEMENTS = BUBBLE_PLACEMENTS.filter((p) => p !== DEFAULT_PLACEMENT);
38
39// `value` : `entry.dialogues[i].placement` / `entry.emojis[i].placement` tel
40// qu'il vient du JSON — absent, `null`, ou une chaîne. Toute valeur non reconnue
41// retombe sur `top` : un `world.json` plus ancien (aucun `placement` nulle part)
42// se comporte donc exactement comme avant.
43export function normalizePlacement(value) {
44  return BUBBLE_PLACEMENTS.includes(value) ? value : DEFAULT_PLACEMENT;
45}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.