feat(donut): noms de catégories en arc tout à l'extérieur du donut
Les libellés des 6 catégories thématiques (Data, Démocratie, Habitat,
Territoire, Écologie, Éducation) étaient posés HORIZONTAUX au milieu
de leur wedge dans la zone sûre. Ils chevauchaient les points-projets
quand on en avait beaucoup et compliquaient la lecture.
Déplacement à R=275, ARC autour du donut, dans la couleur de la catégorie :
- Nouvelle constante R_CAT_LABEL (la plus extérieure : > planétaires à 252)
- viewBox 600x600 (vs 560x560) pour caser la nouvelle frontière
- Fond cream étendu à R=295 pour soutenir les labels jusqu'au bord
- Font-size 11 + weight 700 + lettre-espacement 0.5px pour lisibilité
- Réutilisation du helper arcLabelPaths (halfSpan 28° = quasi-pleine
largeur du secteur de 60°)
- Couleur récupérée par index depuis la liste categories réactive
Suppression du rendu in-wedge des labels catégorie : redondance avec les
arcs extérieurs + meilleure lisibilité des points-projets dans la zone sûre.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -58,13 +58,14 @@ onMounted(load)
|
|||||||
// lisibles : circonférence ≈ 2π × R, donc plus R est grand, plus chaque label
|
// lisibles : circonférence ≈ 2π × R, donc plus R est grand, plus chaque label
|
||||||
// d'arc dispose de place. Le centre et le ring extérieur ne bougent pas, c'est
|
// d'arc dispose de place. Le centre et le ring extérieur ne bougent pas, c'est
|
||||||
// uniquement la zone intérieure qui grossit, en mangeant un peu sur l'espace sûr.
|
// uniquement la zone intérieure qui grossit, en mangeant un peu sur l'espace sûr.
|
||||||
const R_PLANET_LABEL = 252 // étiquettes des limites planétaires (extérieur)
|
const R_CAT_LABEL = 275 // noms de catégories EN ARC, tout à l'extérieur
|
||||||
|
const R_PLANET_LABEL = 252 // étiquettes des limites planétaires (entre catégories et ceiling)
|
||||||
const R_CEILING_OUTER = 225
|
const R_CEILING_OUTER = 225
|
||||||
const R_CEILING_INNER = 200
|
const R_CEILING_INNER = 200
|
||||||
const R_FLOOR_OUTER = 125 // ↑ (était 100)
|
const R_FLOOR_OUTER = 125
|
||||||
const R_FLOOR_INNER = 102 // ↑ (était 78)
|
const R_FLOOR_INNER = 102
|
||||||
const R_SOCIAL_LABEL = 88 // ↑ (était 67) — arc de label = 2π·88/12 ≈ 46u
|
const R_SOCIAL_LABEL = 88 // arc de label = 2π·88/12 ≈ 46u
|
||||||
const R_CENTER = 55 // ↑ légèrement pour ne pas écraser "LE DONUT"
|
const R_CENTER = 55
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format : chaque entrée est un tableau de string. Un tableau à 1 élément →
|
* Format : chaque entrée est un tableau de string. Un tableau à 1 élément →
|
||||||
@@ -233,16 +234,12 @@ const wedgeDividers = computed(() => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
/** Position du label catégorie (juste sous l'anneau écologique, sur la zone sûre). */
|
/** Arcs des noms de catégories, tout à l'extérieur du donut, dans la couleur de la catégorie.
|
||||||
const categoryLabels = computed(() => {
|
* 6 catégories × 60° d'arc chacune ; halfSpan=28° laisse une petite marge avant la suivante. */
|
||||||
const n = categories.value.length || 6
|
const categoryArcs = computed(() =>
|
||||||
const step = 360 / n
|
arcLabelPaths(categories.value.map(c => [c.name] as Label), R_CAT_LABEL, 'cat', 28),
|
||||||
return categories.value.map((cat, i) => {
|
)
|
||||||
const center = i * step + step / 2
|
const categoryArcLines = computed(() => categoryArcs.value.flatMap(c => c.lines))
|
||||||
const [x, y] = pt(center, (R_CEILING_INNER + R_FLOOR_OUTER) / 2)
|
|
||||||
return { cat, x, y }
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
/** Paths d'arc pour les 9 limites planétaires (anneau extérieur). */
|
/** Paths d'arc pour les 9 limites planétaires (anneau extérieur). */
|
||||||
const planetaryArcs = computed(() => arcLabelPaths(PLANETARY_BOUNDARIES, R_PLANET_LABEL, 'pb', 18))
|
const planetaryArcs = computed(() => arcLabelPaths(PLANETARY_BOUNDARIES, R_PLANET_LABEL, 'pb', 18))
|
||||||
@@ -361,15 +358,19 @@ function gotoProject(p: ProjectListRow) {
|
|||||||
<div v-else class="mt-10 grid grid-cols-1 lg:grid-cols-5 gap-10 items-start">
|
<div v-else class="mt-10 grid grid-cols-1 lg:grid-cols-5 gap-10 items-start">
|
||||||
<!-- Donut SVG (3/5 sur grands écrans) -->
|
<!-- Donut SVG (3/5 sur grands écrans) -->
|
||||||
<div class="lg:col-span-3 flex flex-col items-center">
|
<div class="lg:col-span-3 flex flex-col items-center">
|
||||||
<svg viewBox="-280 -280 560 560" class="w-full max-w-[640px] aspect-square">
|
<svg viewBox="-300 -300 600 600" class="w-full max-w-[680px] aspect-square">
|
||||||
<defs>
|
<defs>
|
||||||
<!-- Anneaux gris légèrement striés -->
|
<!-- Anneaux gris légèrement striés -->
|
||||||
<pattern id="ring-stripes" patternUnits="userSpaceOnUse" width="6" height="6" patternTransform="rotate(45)">
|
<pattern id="ring-stripes" patternUnits="userSpaceOnUse" width="6" height="6" patternTransform="rotate(45)">
|
||||||
<rect width="6" height="6" fill="#ECECE7" />
|
<rect width="6" height="6" fill="#ECECE7" />
|
||||||
<line x1="0" y1="0" x2="0" y2="6" stroke="#D1D5DB" stroke-width="0.9" />
|
<line x1="0" y1="0" x2="0" y2="6" stroke="#D1D5DB" stroke-width="0.9" />
|
||||||
</pattern>
|
</pattern>
|
||||||
<!-- Arcs invisibles pour textPath : un par LIGNE de label (1 ligne par limite
|
<!-- Arcs invisibles pour textPath : 1 par catégorie (extérieur), 1 par limite
|
||||||
planétaire, 1 à 2 lignes par dimension sociale selon la longueur). -->
|
planétaire, 1 à 2 par dimension sociale selon la longueur. -->
|
||||||
|
<path
|
||||||
|
v-for="ln in categoryArcLines" :key="ln.pathId"
|
||||||
|
:id="ln.pathId" :d="ln.d" fill="none"
|
||||||
|
/>
|
||||||
<path
|
<path
|
||||||
v-for="ln in planetaryArcLines" :key="ln.pathId"
|
v-for="ln in planetaryArcLines" :key="ln.pathId"
|
||||||
:id="ln.pathId" :d="ln.d" fill="none"
|
:id="ln.pathId" :d="ln.d" fill="none"
|
||||||
@@ -381,8 +382,8 @@ function gotoProject(p: ProjectListRow) {
|
|||||||
</defs>
|
</defs>
|
||||||
|
|
||||||
<!-- 1) ZONE D'OVERSHOOT (au-delà du plafond) -->
|
<!-- 1) ZONE D'OVERSHOOT (au-delà du plafond) -->
|
||||||
<!-- fond cream clair pour soutenir les labels limites planétaires -->
|
<!-- fond cream clair pour soutenir les labels limites planétaires + catégories -->
|
||||||
<circle r="270" fill="#F5F2EA" />
|
<circle r="295" fill="#F5F2EA" />
|
||||||
|
|
||||||
<!-- 2) Étiquettes des 9 LIMITES PLANÉTAIRES, le long de leur arc -->
|
<!-- 2) Étiquettes des 9 LIMITES PLANÉTAIRES, le long de leur arc -->
|
||||||
<g>
|
<g>
|
||||||
@@ -423,17 +424,19 @@ function gotoProject(p: ProjectListRow) {
|
|||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- 7) Étiquettes catégories au milieu de leur wedge -->
|
<!-- 7) Noms des CATÉGORIES en arc, tout à l'extérieur du donut, en couleur catégorie -->
|
||||||
<g>
|
<g>
|
||||||
<text
|
<text
|
||||||
v-for="l in categoryLabels" :key="`label-${l.cat.id}`"
|
v-for="arc in categoryArcs" :key="`cat-text-${arc.key}`"
|
||||||
:x="l.x" :y="l.y"
|
font-size="11"
|
||||||
text-anchor="middle"
|
|
||||||
font-size="9"
|
|
||||||
:fill="l.cat.color_hex"
|
|
||||||
font-weight="700"
|
font-weight="700"
|
||||||
opacity="0.85"
|
:fill="categories[arc.key]?.color_hex ?? '#111827'"
|
||||||
>{{ l.cat.name }}</text>
|
style="letter-spacing: 0.5px"
|
||||||
|
>
|
||||||
|
<textPath :href="`#${arc.lines[0].pathId}`" startOffset="50%" text-anchor="middle">
|
||||||
|
{{ arc.lines[0].text }}
|
||||||
|
</textPath>
|
||||||
|
</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- 8) Étiquettes des 12 DIMENSIONS DU PLANCHER SOCIAL, le long de leur arc -->
|
<!-- 8) Étiquettes des 12 DIMENSIONS DU PLANCHER SOCIAL, le long de leur arc -->
|
||||||
|
|||||||
Reference in New Issue
Block a user