polygon
Draws a closed polygon. Its points are either literal local coordinates — for non-rectangular glyphs (trapezoids, arrows, custom shapes) that the standard shape primitives can't express — or the name of a field holding one ring per data row, which is how a map's outlines are drawn.
gf.chart([{}])
.mark(
gf.polygon({
points: [
[0, 0],
[60, 0],
[50, 40],
[10, 40],
],
fill: "steelblue",
})
)
.render(root, { w: 100, h: 60 });Signature
polygon({ points, fill?, stroke?, strokeWidth?, opacity = 1 })points is either a literal ring or a field name.
Parameters
A closed polygon defined by local-coordinate points (y-up), given literally or read from a field. No dims channels — the bbox is computed from points.
| Option | Type | Default | Description |
|---|---|---|---|
points | [number, number][] | string | Required. Vertex list, at least 3 points — either a literal ring, or the name of a field holding one ring per row (which is how one mark draws a whole basemap). | |
fill | string | FieldExpr | "black" | Fill color, or a field name for a color scale. |
stroke | string | FieldExpr | Stroke color. Defaults to fill. | |
strokeWidth | number | 0 | Stroke width in pixels. |
opacity | number | 1 | Opacity, 0 to 1, applied to both fill and stroke. |
debug | boolean | Dev-only flag: logs this mark's key and datum to the console as it is built. It changes nothing about what is drawn. |
Coordinates
Points are interpreted in the local coordinate system of whatever places the polygon — typically a layer or a constraint. The polygon's bounding box is the axis-aligned extent of its points; the parent placement system translates the whole polygon to position it.
GoFish is y-up internally, so a trapezoid whose wide edge sits at the bottom and narrow edge at the top is written:
polygon({
points: [
[0, 0], // bottom-left (the wider edge)
[width, 0], // bottom-right
[width - 10, h], // top-right (inset)
[10, h], // top-left (inset)
],
});Examples
// Trapezoidal weight glyph (from the pulley diagram)
polygon({
points: [
[0, 0],
[width, 0],
[width - 10, height],
[10, height],
],
fill: "#545454",
}).name("body");
// Triangle with stroke
polygon({
points: [
[0, 0],
[40, 0],
[20, 30],
],
fill: "transparent",
stroke: "black",
strokeWidth: 2,
});Field-bound points
When points is a string, it names a field on each row of the mark's data, and the mark draws one polygon per row. The vertices are then data positions, not local pixels: they go through the chart's position scales, and each polygon places itself where its own coordinates put it.
That is how a basemap is drawn — one row per country ring, each ring a list of [longitude, latitude] pairs, under a geo coordinate space:
chart(world110m, {
coord: geo("equalEarth", { lon: [-170, -30], lat: [-60, 75] }),
}).mark(polygon({ points: "ring", fill: "#f7f7f7", stroke: "#aaa" }));Under a curved coordinate space the edges are adaptively resampled, so an outline follows the projection rather than joining its vertices with straight pixels.
Data-driven fill
fill and stroke work as they do on rect. A field name reads that field off each row and sends it through the chart's color scale. Any other string is a literal color. When stroke is omitted it follows the fill.
chart(counties, { color: gradient(["#fff5eb", "#7f2704"]) }).mark(
polygon({ points: "ring", fill: "rate" })
);Notes
- The polygon is always closed — the last point connects back to the first automatically.
- A polygon has no holes. A ring drawn inside another ring paints over it rather than cutting it out.
