From ff734fcea10964975e1215739457c152a55b12f1 Mon Sep 17 00:00:00 2001 From: jenstandstad Date: Thu, 23 Apr 2026 17:55:37 +0200 Subject: [PATCH] Opacity issue --- plugins/festinger/festinger/main.py | 31 +++++++++++++++++++---------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/plugins/festinger/festinger/main.py b/plugins/festinger/festinger/main.py index d1caead..3072764 100644 --- a/plugins/festinger/festinger/main.py +++ b/plugins/festinger/festinger/main.py @@ -1999,11 +1999,12 @@ const svg = d3.select(svgEl); const root = svg.append('g'); const defs = svg.append('defs'); -// Layer order matters: hulls behind links behind nodes -const hullLayer = root.append('g').attr('class', 'hulls'); -const linkLayer = root.append('g').attr('class', 'links'); -const edgeLblLayer = root.append('g').attr('class', 'edge-labels'); -const nodeLayer = root.append('g').attr('class', 'nodes'); +// Layer order: hulls → links → edge-labels → nodes → dim-labels (top) +const hullLayer = root.append('g').attr('class', 'hulls'); +const linkLayer = root.append('g').attr('class', 'links'); +const edgeLblLayer = root.append('g').attr('class', 'edge-labels'); +const nodeLayer = root.append('g').attr('class', 'nodes'); +const dimLblLayer = root.append('g').attr('class', 'dim-labels'); // always on top const zoom = d3.zoom().scaleExtent([0.04, 14]).on('zoom', e => root.attr('transform', e.transform)); svg.call(zoom).on('dblclick.zoom', null); @@ -2199,9 +2200,8 @@ function renderGraph(nodes, edges) {{ .attr('fill', dimColor(g.dim)); }}); - // Dimension labels — rendered without filter so they stay sharp. - // Positioned at the top of each blob cluster. - hullLayer.selectAll('text.blob-label') + // Dimension labels — in dimLblLayer (above nodes) so they're always crisp. + dimLblLayer.selectAll('text.blob-label') .data(groups, g => g.dim) .join('text').attr('class', 'blob-label') .attr('x', g => centroid(g.nodes)[0]) @@ -2211,9 +2211,13 @@ function renderGraph(nodes, edges) {{ .attr('font-size', '12px') .attr('font-family', 'monospace') .attr('font-weight', 'bold') - .attr('opacity', 0.8) + .attr('opacity', 0.9) .style('pointer-events', 'none') - .text(g => g.dim); + // White halo so label is readable over any blob color + .style('paint-order', 'stroke fill') + .style('stroke', 'rgba(255,255,255,0.85)') + .style('stroke-width', '3px') + .style('stroke-linejoin', 'round'); }} // ── Links ── @@ -2259,7 +2263,12 @@ function renderGraph(nodes, edges) {{ nodeEnter.append('circle'); nodeEnter.append('text') .style('pointer-events', 'none').style('user-select', 'none') - .attr('text-anchor', 'middle').style('font-size', '10px').style('fill', '#222'); + .attr('text-anchor', 'middle').style('font-size', '10px').style('fill', '#111') + // White halo punches through any blob color sitting beneath the text + .style('paint-order', 'stroke fill') + .style('stroke', 'rgba(255,255,255,0.9)') + .style('stroke-width', '3.5px') + .style('stroke-linejoin', 'round'); const nodeMerge = nodeEnter.merge(node); nodeMerge.select('circle')