Skip to content

FoodWeb

Cargo featurefeatures = ["biology"]

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 from level_names.
  • Motion: from delay the levels appear from the bottom, one every level_time seconds, and the arrows into each level draw as it does. With flow, dots of energy then run along every arrow.

Gallery scene: FoodWeb.

FoodWeb demo, first frame
FoodWeb 7.5 s
use 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).

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 of species: 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