FoodWeb draws who eats whom: species, and the arrows of eats as (prey, predator)
pairs pointing the way energy flows. Names that are not in species are left out.
- Levels: producers (species that eat nothing here) sit at the bottom, and every other
species sits one level above its highest prey, so the longest food chain sets its trophic
level (
levels()). - Order: each level is ordered by where its prey and predators sit, to keep arrows from crossing. Arrows that would run through another species bend round it.
- Look: each species is a pill coloured by its level from
level_colors, and the levels are named at the left fromlevel_names. - Motion: from
delaythe levels appear from the bottom, one everylevel_timeseconds, and the arrows into each level draw as it does. Withflow, dots of energy then run along every arrow.
Gallery scene: FoodWeb.

FoodWeb 7.5 suse fframes_kit::prelude::*;
let pond = FoodWeb { species: ["Algae", "Snail", "Fish", "Heron"].map(String::from).to_vec(), eats: [("Algae", "Snail"), ("Snail", "Fish"), ("Algae", "Fish"), ("Fish", "Heron")] .map(|(a, b)| (a.to_owned(), b.to_owned())) .to_vec(), ..FoodWeb::default()};assert_eq!(pond.levels(), [0, 1, 2, 3]); // the fish eats the snail, so it sits above it
fn pond_web<'a>(ui: &mut Ui<'a, '_, '_>) -> Svgr<'a> { ui.show(FoodWeb { flow: false, ..ui.defaults() })}Components are plain structs. Set the fields you need and fill the rest with ..ui.defaults(): the defaults below come from the current theme (theme. values are fields of Theme).
FoodWeb
Section titled “FoodWeb”| Field | Type | Default | Description |
|---|---|---|---|
species |
Vec<String> |
— | Names of the species, each drawn as a pill. |
eats |
Vec<(String, String)> |
pairs .iter() .map(|&(a, b)| (a.to_owned(), b.to_owned())) .collect() |
(prey, predator) pairs by species name; each draws an arrow from prey to predator, the way energy flows. |
delay |
f32 |
0.0 |
Seconds after the container’s start before the bottom level appears. |
level_time |
f32 |
0.8 |
Seconds between one trophic level appearing and the next above it. |
center |
(f64, f64) |
(0.4, -0.35) |
The middle of the web, in units of ui.space. |
level_gap |
f32 |
150.0 |
Pixels between neighbouring trophic levels. |
slot |
f32 |
230.0 |
Pixels between neighbouring species on one level. |
flow |
bool |
true |
Dots of energy run along every arrow once it is drawn when true. |
level_colors |
Vec<Color> |
— | Fill of the species pills by trophic level, producers first; the last colour repeats for higher levels. |
level_names |
Vec<String> |
— | Names written at the left of each level, producers first; a level past the end has no name. |
arrow_color |
Color |
theme.colors.muted |
Colour of the arrows. |
flow_color |
Color |
Color::hex("#ffe066") |
Colour of the energy dots. |
name_style |
TextStyle |
name_style |
The font of the species names: family, size in pixels and weight. |
level_style |
TextStyle |
theme.typography.caption |
The font of the level names: family, size in pixels and weight. |
text_color |
Color |
Color::WHITE |
Colour of the species names. |
level_color |
Color |
theme.colors.muted |
Colour of the level names. |
enter |
Option<FadeIn> |
None |
Fade in at the start; None for none. |
exit |
Option<FadeOut> |
None |
Fade out before the end; None for none. |
Methods:
fn levels(&self) -> Vec<usize>: The trophic level of each ofspecies: 0 for producers (they eat nothing here), otherwise one above the highest of their prey, so the longest food chain sets it. Feeding cycles stop climbing after one level per species.
Feature biology · Source
