Track view¶
| Garmin | Wear OS | Apple Watch | |
|---|---|---|---|
| Status | 🟡 | ✅ | ⏳ |
| Code | source/views/TrackView.mc, source/views/TrackPlot.mc, source/views/MapTrackView.mc, source/TripDelegate.mc, source/TripContext.mc (position buffer) |
wear/…/presentation/views/TrackView.kt, wear/…/presentation/TrackMapLayer.kt, core/…/TrackMap.kt, wear/…/presentation/TrackingScreen.kt, wear/…/recording/TripEngine.kt (position buffer) |
— |
Verified against code: 2026-10-13
Purpose¶
Instrument screen 2. It shows the shape of the last 50 minutes of the track around the boat, north up, so the skipper sees tacks, drift and the course made good at a glance. Course and speed stay on screen as numbers; the plot is for shape. After a tack or jibe it shows the turn angle.
The screen sits between the Dashboard and the Environment view in the instrument pager (input.md). Colours and fonts come from the visual system.
Layout / behaviour¶
The screen is black, or shows a map with the setting Track map (Map background). Positions are fractions of screen width (x) and height (y); x 0.50 / y 0.50 is the centre. Nothing on this screen is a header: the top stays empty except for the turn angle.
| Element | Position | Font / size | Colour | Content & format | Constraints |
|---|---|---|---|---|---|
| Turn angle | x 0.50, y 0.12, centred | Header font | Orange 0xFF5500 |
Signed whole degrees: +75° (clockwise turn), -66° (anticlockwise) |
Only while a turn is detected; otherwise nothing is drawn here |
| Track line | Around the centre | — | Accent of the current vessel state; newest two segments orange | Line through the buffered positions, oldest to newest | Needs at least 2 buffered positions |
| Course vector | From the centre | — | White | Line in the COG direction, tip dot | Only while COG is valid and at least 2 positions are buffered |
| Boat marker | x 0.50, y 0.50 | — | White ring | Hollow circle | Only while at least 2 positions are buffered |
no fix |
x 0.50, y 0.50, centred | Label font (Garmin FONT_XTINY) |
Dim 0xAAAAAA |
no fix |
Instead of line, vector and marker while fewer than 2 positions are buffered |
| COG | x 0.30, y 0.76, centred | Small font (Garmin FONT_TINY) |
White | Whole degrees with °, e.g. 215°; - without a valid COG |
Always shown |
| SOG | x 0.70, y 0.76, centred | Small font | White | One decimal plus unit: 5.3 kn; 0.0 kn without speed |
Always shown |
| Zoom-in badge | x 0.86, y 0.24 | Small font for the sign | Disc sail blue 0x00AAFF, + in black |
Filled disc with + |
Radius width/22, at least 8 px |
| Zoom-out badge | x 0.86, y 0.68 | Small font for the sign | Disc engine red 0xFF5555, - in black |
Filled disc with - |
Same radius |
| Scale bar | Centre of the group at x 0.50, y 0.89 | Label in FONT_XTINY |
White | \|____\| then the distance label, e.g. 0.1nm |
Always shown, also without a fix |
Plot¶
- Projection. Flat (equirectangular) around the newest buffered position. Longitude differences are scaled by cos(latitude of that position). One degree of latitude is 60 nm.
- Centre. The newest buffered position sits at the screen centre. It is up to 5 s old, not the live fix.
- North up. The plot never rotates.
- Line. Each pair of consecutive positions is one straight segment, pen 2 px, in the accent of the current vessel state (vessel-state.md). The whole line takes the current colour; it does not keep the colour each part was recorded in.
- Turn highlight. While a turn angle is shown and at least 3 positions are buffered, the newest two segments are drawn orange
0xFF5500with pen 3 px. These are always the newest two segments (about the last 10 s), not the part of the line where the turn began. - Course vector. A 2 px white line from the centre in the COG direction, 0.20 × width long, ending in a filled white dot of radius width/60 + 1.
- Boat marker. A white disc of radius width/40 + 1 with a black disc of radius 2 px smaller inside, so a 2 px white ring. Drawn last, on top of the line and the vector.
- Segments that run off the screen are clipped by the screen edge. Nothing marks the start of the track.
Position buffer¶
The plot reads a ring buffer of positions kept for the current track.
| Property | Value |
|---|---|
| Sampling | One position every 5 s of the 1 Hz tick |
| Capacity | 600 positions |
| History | 600 × 5 s = 50 minutes; when full, the oldest position is overwritten |
| Empty at | The start of every new track |
| Pause | Not sampled while paused. The buffer is saved with the paused track and restored on resume (lifecycle.md) |
This buffer is only for the plot. What gets recorded and uploaded is described in recording.md.
Garmin¶
A sample takes Activity.Info.currentLocation, or the last Position event when that is null. Any position is accepted, whatever its quality. Without a position the sample is skipped.
Wear OS¶
A sample takes the last location fix, and only if it is current (younger than 10 s). Otherwise the sample is skipped.
Turn angle¶
The turn angle is the course change the COG calculation reports: the signed difference between the mean of the first two and the mean of the last two of the last 30 one-second COG values, shown only when it is more than 30° either way. Positive is clockwise. The maths is in shared/calculations.md.
- It appears as soon as the newest courses differ by more than 30° from the oldest in the 30 s window, and disappears when the window no longer spans the turn, so it stays for up to about 30 s.
- It is cleared at once when COG becomes invalid (speed below 1 kn or no usable GPS course).
- There is no text label (no "TRACK", no "Jibe"); only the angle.
Zoom¶
Seven zoom steps, 0 to 6. The default is step 3. The scale bar is 10 % of the screen width (rounded, at least 16 px), and the zoom step sets how far that bar is.
| Step | Scale bar label | Bar distance | Screen width spans about |
|---|---|---|---|
| 0 (widest) | 1nm |
1.0 nm | 10 nm |
| 1 | 0.5nm |
0.5 nm | 5 nm |
| 2 | 0.2nm |
0.2 nm | 2 nm |
| 3 (default) | 0.1nm |
0.1 nm | 1 nm |
| 4 | 0.05nm |
0.05 nm | 0.5 nm |
| 5 | 0.02nm |
0.02 nm | 0.2 nm |
| 6 (closest) | 0.01nm |
0.01 nm | 0.1 nm |
Zoom in raises the step, zoom out lowers it. Both stop at the ends; nothing wraps.
Scale bar¶
- Bar: 2 px white line,
round(0.10 × width)px long (at least 16 px). - End ticks: 2 px white vertical lines at both ends, reaching
round(0.015 × width)px (at least 3 px) above and below the bar. - Label: the zoom step's label in
FONT_XTINY, white, left-aligned,round(0.02 × width)px (at least 4 px) right of the bar, vertically centred on it. - Bar, gap and label together are centred horizontally at y 0.89.
Garmin¶
| Input | On the Track view |
|---|---|
| START/STOP | Zoom in |
| BACK | Zoom out |
| Tap, right half, upper half (touch screens) | Zoom in |
| Tap, right half, lower half | Zoom out |
| Tap, left half | Nothing (default handling) |
| UP / DOWN | Previous / next instrument screen, as on every instrument screen |
On the Track view START/STOP and BACK do not open the action menu or the vessel state menu. To reach them the user pages to another instrument screen (input.md, menus.md).
The zoom step is not kept: each time the Track view is shown it starts at step 3.
Wear OS¶
| Input | On the Track view |
|---|---|
Tap, right half, upper half (on or near the + badge) |
Zoom in |
Tap, right half, lower half (on or near the - badge) |
Zoom out |
| Tap anywhere else | Toggle crown zoom mode |
| Crown, zoom mode off | Pages the instruments, as on every instrument screen |
| Crown, zoom mode on | Zooms one step per 40 px of rotary scroll; the direction that pages forward zooms in |
Stem button 1 (KEYCODE_STEM_1, = Garmin BACK) |
Zoom out |
| Stem button 2 / 3 (= Garmin START) | Zoom in |
| Swipe right | Controls page, as on every instrument screen |
- Zoom mode is shown by a 2 px ring of radius r + 4 around both badges, in each badge's colour. It ends when the user taps outside the badges again or leaves the Track view.
- While touch lock is on, taps do nothing; the first crown turn or a 2 s hold unlocks (input.md).
- While an alert or auto-stats overlay is up, a stem press only closes the overlay.
- The zoom step is kept when the user pages away and back, and across detours (picker, stats). It resets to step 3 only when the app's screen is created again.
Apple Watch¶
⏳ As decided in docs/apple_watch_port_plan.md: the crown pages the instruments, so zoom uses on-screen + / - buttons, or a tap on the map puts the crown into zoom mode until the next tap. Same zoom steps, plot and scale bar as above.
Map background¶
With the setting Track map on, a map is drawn behind the Track view instead of the black backdrop. The overlay above stays the same in content and position.
- Map area: centred on the newest buffered position, north up, at the zoom step's scale, so the map and the plot match. The map moves with the 5 s position samples and with each zoom step, not every second.
- Contrast: the track line gets a black outline 2 px wider than the line; the course vector, its tip dot and the boat marker get a 1 px black outline; the turn angle, COG, SOG and the scale bar sit on black rounded boxes; the zoom badges get a 1 px black ring. Without the map none of this is drawn.
- Without a fix (fewer than 2 positions): the black Track view with
no fix. If GPS is lost later, the map stays where it was. - No map for the area: whatever the watch's map shows there; SailEver adds no error text.
- Not on the Pause view.
Garmin¶
- Map: the map the firmware gives Connect IQ apps (
WatchUi.MapViewin preview mode, so it takes no buttons; all inputs stay as in Garmin). Apps can't list or choose the installed maps or a map theme: on a quatix 6 it is the general (topo) map, not the marine chart that Garmin's own activities offer. Nothing leaves the watch. - Scale: the firmware fits the requested area into the round screen with the area's diagonal on the screen's diameter, so it shows √2 times as far as asked for (measured on a quatix 6 at all seven zoom steps, 2026-11-01: map 1.27–1.52 × our scale, mean 1.39). The app asks for the plot's area divided by √2, so map, track line and scale bar share one scale. No API reports the map's actual scale.
- Map area updates come from a 1 s timer and from the zoom keys, never from
onUpdate(setting the area there makes the map flicker). - Devices: only those whose SDK device file has
MapView(the(:maps)list inmonkey.jungle: fēnix 5X / 5 Plus and later map models, epix 2, MARQ, D2 Delta / Mach, Descent Mk2 / Mk3, FR945 / 955 / 965 / 970, enduro 3). On every other device the setting isn't shown and the Track view stays black. - Setting:
Track maptoggle in the Settings menu, default off on every watch, quatix included (owner, 2026-11-01): a quatix shares its device file and app build with a fēnix or epix (quatix 6 =fenix6pro), and the app can't tell them apart at runtime. It takes effect the next time the Track view is shown.
Wear OS¶
- Map: SailEver's tiles from
tiles.sailever.com(base map and depth, maps.md), drawn by MapLibre with the watch styleassets/track_map_style.json: water, depth bands, drying and no-depth areas, depth lines, land, coastline; no labels, no seamarks. Why: ADR 018. - Paired watches only: the map needs the pairing and the current privacy consent. An unpaired watch makes no tile request and its Track view is black.
- Setting:
Track mapin the Settings menu, shown on a paired watch only, default on;ON/OFF, a tap switches it. - When: only while the Track view is the page on screen; in the low-power layout and in ambient mode there's no map. While it's shown the app holds an internet network request.
- Offline: tiles already loaded stay in a 50 MB cache and keep showing; where nothing is cached the Track view stays black, with no error.
- Scale: the camera zoom is computed so the scale bar's pixels cover its distance (
TrackMap.cameraZoom); the map shows the zoom steps beyond the tiles' data (zoom 15) scaled up.
States and edge cases¶
| Situation | What the screen shows |
|---|---|
| Fewer than 2 buffered positions (first ~10 s of a track, or no position yet) | no fix in the centre; COG - or a value, SOG, scale bar and badges as normal |
| Positions buffered but COG invalid (below 1 kn, or no GPS course) | Line and boat marker, no course vector, COG -, no turn angle |
| GPS lost after positions were buffered | The last line stays, centred on the last buffered position. no fix does not come back |
| Boat stationary for a long time | All positions pile up in the centre; the line shrinks to a dot under the marker |
| Track longer than 50 min | Only the newest 50 min are drawn |
| Vessel state changed | The whole line switches to the new state's colour at the next redraw |
| Track wider than the screen at the current step | Parts outside the screen are cut off; the user zooms out |
| Small screens (218 px) | Scale bar keeps its 16 px minimum; badges keep their 8 px minimum radius |
Known deviations¶
- Garmin — zoom is not kept. Garmin resets the zoom step to 3 each time the Track view is shown, because
TripDelegate.viewForcreates a newTrackViewon every page switch. Wear OS keeps it. Garmin is behind (parity.md P2). - Garmin — code comment.
TrackView.mcline 9 says zoom in is the LIGHT button. The code binds zoom in to START/STOP (TripDelegate.onSelect). The behaviour above is the code's. - Both — turn highlight. The orange highlight always covers the newest two segments, not the segments where the turn happened. With 5 s sampling these lag the start of the turn.