wavy
Warps the plane with a sinusoidal ripple, so a straight edge is drawn as a wave. Used for decorative geometry — a balloon string, a flag, a squiggly connector.
ts
import { color, color6, ellipse, layer, rect, wavy } from "gofish-graphics";
import { mix } from "spectral.js";
import _ from "lodash";
import { catchLocations, seafood } from "./dataset";
const scatterData = _(seafood)
.groupBy("lake")
.map((lakeData, lake) => ({
lake,
x: catchLocations[lake].x,
y: catchLocations[lake].y,
collection: lakeData.map((item) => ({
species: item.species,
count: item.count,
})),
}))
.value();
const container = document.getElementById("app");
const colorMap = {
0: color.red,
1: color.blue,
2: color.green,
3: color.yellow,
4: color.purple,
5: color.orange,
};
const Balloon = (options) =>
layer(
{
x: options?.x - 15 * (options?.scale ?? 1),
y: options?.y + 27 * (options?.scale ?? 1),
box: true,
transform: {
scale: { x: options?.scale ?? 1, y: (options?.scale ?? 1) * -1 },
},
},
[
ellipse({
cx: 15,
cy: 15,
w: 24,
h: 30,
fill: (options?.color ?? color.red)[4],
}),
ellipse({
cx: 12,
cy: 11,
w: 7,
h: 11,
fill: (options?.color ?? color.red)[3],
}),
rect({
cx: 15,
cy: 32,
w: 8,
h: 4,
fill: (options?.color ?? color.red)[5],
rx: 3,
ry: 2,
}),
rect({
cx: 15,
cy: 32,
w: 5,
h: 2.4,
fill: (options?.color ?? color.red)[6],
rx: 2,
ry: 1,
}),
]
);
layer(
{ coord: wavy(), x: 0, y: 0 },
scatterData.map((data, i) =>
layer({ x: data.x }, [
rect({
x: 0,
y: 0,
w: 1,
h: data.y,
emY: true,
fill: color.black,
}),
Balloon({
scale: 1,
x: 0,
y: data.y,
color: /* colorMap[i % 6] */[
null,
null,
null,
mix(color6[i % 6], color.white, 0.5),
color6[i % 6],
mix(color6[i % 6], color.black, 0.1),
mix(color6[i % 6], color.black, 0.35),
],
}),
])
)
).render(container, {
axes: true,
});Dataset
ts
export type Lakes =
| "Lake A"
| "Lake B"
| "Lake C"
| "Lake D"
| "Lake E"
| "Lake F";
export type CatchData = {
lake: Lakes;
species: "Bass" | "Trout" | "Catfish" | "Perch" | "Salmon";
count: number;
};
export const catchLocations: Record<Lakes, { x: number; y: number }> = {
"Lake A": { x: 5.26, y: 22.64 },
"Lake B": { x: 30.87, y: 120.75 },
"Lake C": { x: 50.01, y: 60.94 },
"Lake D": { x: 115.13, y: 94.16 },
"Lake E": { x: 133.05, y: 50.44 },
"Lake F": { x: 85.99, y: 172.78 },
};
export const catchLocationsArray = Object.entries(catchLocations).map(
([lake, { x, y }]) => ({
lake,
x,
y,
})
);
export const seafood: CatchData[] = [
{
lake: "Lake A",
species: "Bass",
count: 23,
},
{
lake: "Lake A",
species: "Trout",
count: 31,
},
{
lake: "Lake A",
species: "Catfish",
count: 29,
},
{
lake: "Lake A",
species: "Perch",
count: 12,
},
{
lake: "Lake A",
species: "Salmon",
count: 8,
},
// … 25 more rows
];
export const catchData = seafood;
export const catchDataWithLocations = seafood.map((catchItem) => {
const location = catchLocationsArray.find(
(loc) => loc.lake === catchItem.lake
);
return {
...catchItem,
x: location?.x,
y: location?.y,
};
});
export type CatchDataWithLocation = (typeof catchDataWithLocations)[0];Signature
ts
wavy();Pass it as the coord of a layer (or of a chart) to warp everything inside that scope:
ts
layer({ coord: wavy(), x: 0, y: 0 }, [rect({ w: 4, h: 120 })]);Parameters
A sinusoidal warp of the plane. No options.
No options.
