Rotating sweep with afterglow, contacts fade between passes.
A round scope with range rings and a sweep turning clockwise. Its
afterglow trails behind; contacts light as the beam crosses them, then
fade. As upstream draws it, contacts cross on made-up tracks over a
coast; give it contacts and it shows yours.
Options
Give them to Ascii.new/2 as options:, and new ones while it plays
with Ascii.put_options/2 (or a Phoenix player's options), as your
contacts move: the scope is drawn anew from them, the beam where play
time puts it.
contacts- each a map of itsbearing, in degrees clockwise from north, itsrange, in the scope's units, and optionally itssize, 1 or 2 cells wide. They light as the beam crosses them and fade until it comes round again, as upstream's do, over the land too; one beyond the scope's range, or without a bearing or range, is not shown, and one at its very edge is drawn just inside the bezel. Default[]: contacts cross the scope on upstream's tracks.range- the scope's reach, in the top corner; its rings are a third of it apart, in the bottom one. Default 24.unit- the range's unit. Default"nm".land-falseleaves out the coast that lies to the south-west. Defaulttrue.
The frame is always 53 by 25.
Colours
In one ink, or a gradient, with :ink and :gradient (see
Ascii.Ink); part by part with :parts (see Ascii.Parts),
parts: true taking the colours suggested here:
bezel- the rim, grey.ring- the range rings' dots and the centre's+, grey.scale- the bearings at the rim, grey.land- the coast's land, orange;land.coast, its edge, which flares as the beam passes, as the land's unless given its own.sweep- the beam's afterglow, green;sweep.beam, the beam itself, as the sweep's unless given its own.contact- the contacts, green.readout- the texts in the corners.
Each frame's parts are drawn again from its time, so they are exact.
Keys and clicks
It takes none: it shows contacts, and Ascii.handle_event/2 ignores
every event. A Phoenix player given interactive and notify still tells
your LiveView where it was clicked, and on which part
(Ascii.part_at/4): a contact, say.
Screen readers
Ascii.describe/1 reads the contacts given and the scope's range:
"radar: 2 contacts within 24 nm". Playing upstream's tracks, it gives the
piece's name and note.
Example
contacts = [%{bearing: 40, range: 9}, %{bearing: 130, range: 18, size: 2}]
scope = Ascii.new!("radar", options: %{contacts: contacts, land: false}, parts: true)
Ascii.describe(scope)
#=> "radar: 2 contacts within 24 nm"
{frame, _scope} = Ascii.frame(scope, 2.0)
frame.text =~ "contacts 2"
#=> true<Ascii.Phoenix.live_player id="scope" piece="radar" options={%{contacts: @contacts, land: false}} parts />Ported from src/pieces/radar.ts in bas3line/ascii (MIT).