fix(skewt): stack overlapping critical-level labels + widen rail
LCL/LFC and 0 °C/WBZ landed within ~5 px of each other on the right- edge label rail and stomped on each other's text. Sort by y, bump each subsequent label down by at least 14 px from the previous one, and draw a thin leader from the true tick to the bumped baseline so nothing reads as misaligned. Also widened the SVG from 720 → 820 user units so longer entries like `LCL 925 mb` no longer get clipped by the right edge.
This commit is contained in:
parent
2fc434df56
commit
6967614dfb
1 changed files with 34 additions and 11 deletions
|
|
@ -12,8 +12,10 @@ defmodule MicrowavepropWeb.SkewtSvg do
|
|||
"""
|
||||
alias Microwaveprop.Weather.SkewtParams
|
||||
|
||||
# Plot canvas (SVG user units).
|
||||
@width 720
|
||||
# Plot canvas (SVG user units). The right margin (right edge of the
|
||||
# plot box → SVG edge) is sized to fit the longest critical-level
|
||||
# label rail entry, e.g. `LCL 925 mb`, without clipping.
|
||||
@width 820
|
||||
@height 640
|
||||
@left 60
|
||||
@right 660
|
||||
|
|
@ -142,26 +144,46 @@ defmodule MicrowavepropWeb.SkewtSvg do
|
|||
# in-plot tick. Mirrors SPC's `143 mb`, `158 mb (mix)`, etc. rail.
|
||||
defp critical_level_markers([]), do: ""
|
||||
|
||||
# Walk the levels in y order and bump any text whose baseline would
|
||||
# land within @critical_label_min_dy of the previous one. The tick
|
||||
# always sits at the level's true y; only the label gets nudged with
|
||||
# a thin leader so close levels (e.g. LCL/LFC, 0 °C/WBZ) read cleanly.
|
||||
defp critical_level_markers(levels) do
|
||||
Enum.flat_map(levels, fn
|
||||
levels
|
||||
|> Enum.flat_map(fn
|
||||
%{label: label, pressure_mb: p} when is_number(p) ->
|
||||
y = pressure_y(p)
|
||||
|
||||
if y >= @top and y <= @bottom do
|
||||
[render_critical_marker(label, p, y)]
|
||||
else
|
||||
[]
|
||||
end
|
||||
if y >= @top and y <= @bottom, do: [{label, p, y}], else: []
|
||||
|
||||
_ ->
|
||||
[]
|
||||
end)
|
||||
|> Enum.sort_by(fn {_lbl, _p, y} -> y end)
|
||||
|> Enum.map_reduce(@top, fn {label, p, y}, last_text_y ->
|
||||
text_y = max(y, last_text_y + @critical_label_min_dy)
|
||||
iodata = render_critical_marker(label, p, y, text_y)
|
||||
{iodata, text_y}
|
||||
end)
|
||||
|> elem(0)
|
||||
end
|
||||
|
||||
defp render_critical_marker(label, pressure_mb, y) do
|
||||
# Minimum vertical gap between two stacked label baselines (px in
|
||||
# SVG user units). 14 leaves the 10 px text plus a hair of breathing
|
||||
# room — anything tighter starts overlapping descenders.
|
||||
@critical_label_min_dy 14
|
||||
|
||||
defp render_critical_marker(label, pressure_mb, y, text_y) do
|
||||
leader =
|
||||
if abs(text_y - y) > 0.5 do
|
||||
~s|<line class="critical-leader" x1="#{@right}" y1="#{r(y)}" x2="#{@right + 4}" y2="#{r(text_y)}"/>|
|
||||
else
|
||||
""
|
||||
end
|
||||
|
||||
[
|
||||
~s|<line class="critical-tick" x1="#{@right - 8}" y1="#{r(y)}" x2="#{@right}" y2="#{r(y)}"/>|,
|
||||
~s|<text class="critical-label" x="#{@right + 4}" y="#{r(y) + 3}">#{label} #{round(pressure_mb)} mb</text>|
|
||||
leader,
|
||||
~s|<text class="critical-label" x="#{@right + 6}" y="#{r(text_y) + 3}">#{label} #{round(pressure_mb)} mb</text>|
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -245,6 +267,7 @@ defmodule MicrowavepropWeb.SkewtSvg do
|
|||
.virtual-temp-line { fill: none; stroke: #fb7185; stroke-width: 1; stroke-dasharray: 1 3; stroke-linejoin: round; stroke-linecap: round; }
|
||||
.wet-bulb-line { fill: none; stroke: #2563eb; stroke-width: 1.4; stroke-linejoin: round; stroke-linecap: round; opacity: 0.85; }
|
||||
.critical-tick { stroke: currentColor; stroke-width: 1.2; }
|
||||
.critical-leader { stroke: currentColor; stroke-opacity: 0.45; stroke-width: 0.8; }
|
||||
.critical-label { font: 10px ui-sans-serif, system-ui, sans-serif; fill: currentColor; fill-opacity: 0.85; }
|
||||
.skewt-cursor-line { stroke: currentColor; stroke-opacity: 0.5; stroke-width: 0.8; stroke-dasharray: 3 3; pointer-events: none; }
|
||||
.skewt-cursor-dot-t { fill: #ff0000; pointer-events: none; }
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue