Skip to contents

Two rpic extensions delegate presentation to the host document that embeds the SVG: class attaches CSS class names to shapes, and animate emits a timing manifest a player can drive. Neither changes rpic’s own rendering — classic output stays byte-identical — but together they make diagrams that respond to the page they live in.

class: CSS hooks on shapes

class has two forms writing to the same hook — inline at creation, and a statement form that reuses pic’s object references (labels, last line, 2nd box), which also reaches shapes drawn inside macros:

library(rpic)

svg <- rpic_svg('
boxht = 0.4; boxwid = 0.9
box class "service" "api"
arrow
box class "service hot" "billing"
arrow
box class "storage" "database"
class last arrow "dataflow"
')

Each class lands on the shape’s SVG group (<g id="sN" class="…">). The names are validated ([A-Za-z_][A-Za-z0-9_-]* only), so there is no attribute-injection surface.

Styling happens in the host page. This very vignette embeds the SVG inline below and styles it with a <style> block — the “billing” box is hot, services get a blue border, and the last arrow is dashed. That is live CSS, not something rpic drew:

apibillingdatabase

Note the delegation contract: CSS only reaches inline-embedded SVG. An <img src="…svg"> reference isolates the document, and raster (PNG/PDF) output ignores classes entirely — there, the diagram renders exactly as if no class existed.

animate: a timing manifest

animate schedules an effect (draw, fade, pop) per shape, again without touching the static rendering:

bundle <- rpic_manifest('
boxht = 0.35; boxwid = 0.8
A: box "build"
arrow
box "test"
arrow
box "ship"
animate A with "pop"
animate 2nd box with "fade"
animate 3rd box with "draw" for 0.8
')

The drawing itself is the ordinary static SVG:

three boxes labelled build, test and ship connected by arrows
three boxes labelled build, test and ship connected by arrows

and the bundle carries an animations array — shape ids (the same stable s<N> ids the class hooks ride on), effect names and a resolved timeline:

"animations":[{"id":"s0","effect":"pop","start":0,"duration":0.6},
 {"id":"s2","effect":"fade","start":0.6,"duration":0.6},
 {"id":"s4","effect":"draw","start":1.2,"duration":0.8}]

Playing it is the host’s job. In the browser, the @strategicprojects/rpic npm package ships a GSAP player: animate(stage, animations, gsap) builds the timeline (draw traces strokes, pop scales in, fade fades). The animate extension page shows it running live.

Unknown effect names are accepted but reported: the bundle’s warnings array flags them (unknown_animation_effect, with the supported list), the same structured-diagnostic shape used by compile errors.

Both layers together

Class hooks and animation target the same shape groups, so a diagram can be styled by the page and animated by the player at once — the classes ride on <g id="sN" class="…"> while the manifest addresses sN. Everything stays a plain, portable SVG for any consumer that ignores them.