Depth actual
The water under the vessel, with a seabed that rises as the depth shrinks and a gauge that marks it.
On this page
Plenty of water: keep the approach speed under 3 kn.
Forward sonar lost the bottom in the weed: steer by the echosounder until it reads again.
Code
import { AdviceType, DepthActual, Priority, Readout, ReadoutDataQuality, VesselImage } from "@bosunkit/instruments";
import type { LinearAdvice } from "@bosunkit/instruments";
import { useEffect, useState } from "react";
import type { CSSProperties, Dispatch, ReactElement, SetStateAction } from "react";
export const description: string =
"Althea feeling her way into the anchorage at Cala Galdana on a one-second sounding feed, with a shallow-water caution range that triggers under 3.5 m and an advice range above it, beside a second sounder that has lost its bottom.";
const DRAFT_METERS: number = 2.2;
/** Feed steps for one approach and back out. */
const CYCLE: number = 40;
const SHALLOW_ADVICE: LinearAdvice[] = [
{ min: 0, max: 3.5, type: AdviceType.caution, hinted: false },
{ min: 3.5, max: 5, type: AdviceType.advice, hinted: true },
];
const CAPTION_STYLE: CSSProperties = { margin: 0, fontSize: 12, color: "var(--element-neutral-color)" };
/** The sounding over the approach: 14 m at the entrance, shoaling to 3.1 m off the beach, then back out. */
function depthAt(step: number): number {
const progress: number = step < CYCLE / 2 ? step / (CYCLE / 2) : (CYCLE - step) / (CYCLE / 2);
return 14 - 10.9 * progress + 0.15 * Math.sin(step * 1.7);
}
export default function Showcase(): ReactElement {
const [step, setStep]: [number, Dispatch<SetStateAction<number>>] = useState<number>(0);
useEffect((): (() => void) => {
const timer: number = window.setInterval((): void => {
setStep((previous: number): number => (previous + 1) % CYCLE);
}, 1000);
return (): void => {
window.clearInterval(timer);
};
}, []);
const depth: number = depthAt(step);
const underKeel: number = depth - DRAFT_METERS;
const note: string =
depth <= 3.5
? `Under keel ${underKeel.toFixed(1)} m: stop here and anchor, or turn back to deeper water.`
: depth <= 5
? "Approaching the 3.5 m limit: slow down and prepare the anchor."
: "Plenty of water: keep the approach speed under 3 kn.";
return (
<div style={{ display: "flex", flexWrap: "wrap", gap: 24, justifyContent: "center", alignItems: "flex-start" }}>
<div style={{ display: "grid", gap: 8, justifyItems: "center", width: 300 }}>
<div style={{ width: 280, height: 280 }}>
<DepthActual
depth={depth}
draft={DRAFT_METERS}
advice={SHALLOW_ADVICE}
maxDepth={15}
primaryTickmarkInterval={5}
secondaryTickmarkInterval={1}
vesselImage={VesselImage.sailingYachtFore}
priority={Priority.enhanced}
/>
</div>
<div style={{ display: "flex", gap: 24 }}>
<Readout label="Depth" unit="m" src="Echosounder" value={depth} fractionDigits={1} />
<Readout label="Under keel" unit="m" src="Draft 2.2 m" value={underKeel} fractionDigits={1} />
</div>
<p style={{ ...CAPTION_STYLE, textAlign: "center" }}>{note}</p>
</div>
<div style={{ display: "grid", gap: 8, justifyItems: "center", width: 200 }}>
<div style={{ width: 180, height: 180 }}>
<DepthActual
depth={Number.NaN}
draft={DRAFT_METERS}
advice={SHALLOW_ADVICE}
maxDepth={15}
primaryTickmarkInterval={5}
secondaryTickmarkInterval={1}
vesselImage={VesselImage.sailingYachtFore}
/>
</div>
<Readout label="Depth" unit="m" src="Forward sonar" value={null} dataQuality={ReadoutDataQuality.invalid} />
<p style={{ ...CAPTION_STYLE, textAlign: "center" }}>
Forward sonar lost the bottom in the weed: steer by the echosounder until it reads again.
</p>
</div>
</div>
);
}
Depth actual draws the water column under the vessel. The seabed rises as the depth shrinks, the vessel floats at its
draft, and a linear gauge column maps the depth on a scale from the surface to maxDepth, or with none set to the first
rung of the range ladder, 25 meters. A depth beyond the range is drawn at the end of the scale. The draft is the dark
band at the top of the gauge. advice marks shallow-water ranges and turns one to triggered when the depth is inside
it.
The instrument fills the box it is given, so the example sets one.
Examples
Depth
Code
import { DepthActual } from "@bosunkit/instruments";
import type { ReactElement } from "react";
export const description: string = "A depth of 12.4 meters and a draft of 2.2 meters on the default 10 meter scale.";
export default function Depth(): ReactElement {
return (
<div style={{ width: 200, height: 200 }}>
<DepthActual depth={12.4} draft={2.2} />
</div>
);
}
Surface depth and under-keel clearance
depth is depth below the surface in meters, and draft is the vessel's draft in meters. Normalize a transducer
reading to that reference before passing it in; do not feed under-keel clearance into the surface-depth prop.
If a separate readout shows clearance, label it explicitly and use the same vessel offsets and source data.
A value beyond maxDepth reaches the end of the drawing, so retain the numeric reading when exact depth
matters. Choose advice ranges from the vessel's operational limits, not from a convenient visual scale. Treat a
lost bottom or invalid sample as unavailable; omitting the prop selects its default value and does not declare
missing telemetry. Follow the no-reading example and expose source quality in the containing panel.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| depth | number | undefined | 0 | Depth below the surface in meters. |
| draft | number | undefined | 0 | Vessel draft in meters — drawn as the dark band at the top of the gauge. |
| advice | LinearAdvice[] | undefined | [] | Shallow-water advice zones; triggered when the depth is inside the range. |
| vesselScale | number | undefined | 1 | Factor on the range's vessel size. |
| vesselImage | VesselImage | undefined | VesselImage.psvFore | Fore-view vessel silhouette floating at the waterline. |
| priority | Priority | undefined | Priority.regular | Regular or enhanced palette of the depth fill and the draft band. |
| showLabels | boolean | undefined | true | Label the scale ends and the primary ladder beside the frame. Default true. |
| ranges | readonly DepthRange[] | undefined | DEPTH_RANGES | Range ladder shared with the other depth instruments. Defaults to the design's three rungs. |
| maxDepth | number | undefined | – | Explicit scale maximum; wins over autoRange. |
| autoRange | boolean | undefined | false | Steps the ladder with depth. |
| primaryTickmarkInterval | number | undefined | – | Distance between the labeled tickmarks on the depth scale, in meters; overrides the range's. |
| secondaryTickmarkInterval | number | undefined | – | Distance between the secondary tickmarks on the depth scale, in meters; overrides the range's. |
| className | string | undefined | – | Class name added to the root element. |
Related
- Main engine: another linear instrument.
- Data integrity: how a live value shows how far to trust it.
- Instruments: the other instruments.