Group
A Group is a container for organizing elements into a hierarchy — much like a <div> in HTML. Groups support property inheritance, child management, and powerful querying capabilities inspired by the DOM.
Groups are the backbone of Ripl's scene graph. By nesting elements inside groups, you can apply shared styles (which cascade to children like CSS), manage collections of elements as a unit, and use CSS-like selectors to find elements deep in the tree. Groups themselves don't draw anything — they orchestrate their children.
Demo
Creating a Group
import {
createCircle,
createGroup,
createRect,
} from '@ripl/web';
const circle = createCircle({
cx: 100,
cy: 100,
radius: 40,
});
const rect = createRect({
x: 160,
y: 60,
width: 80,
height: 80,
});
const group = createGroup({
fill: '#3a86ff',
children: [circle, rect],
});Property Inheritance
Style properties set on a group are inherited by all child elements that don't explicitly set those properties. This works just like CSS inheritance:
const group = createGroup({
fill: '#3a86ff', // inherited by all children
lineWidth: 2, // inherited by all children
children: [
createCircle({
cx: 80,
cy: 100,
radius: 40,
}), // uses group's fill
createCircle({
cx: 200,
cy: 100,
radius: 40,
fill: '#ff006e',
}), // overrides fill
],
});Child Management
add(element)
Add one or more elements to the group:
group.add(newCircle);
group.add([circle1, circle2]);If an element already has a parent, it is automatically removed from its previous parent before being added.
remove(element)
Remove one or more elements:
group.remove(circle);
group.remove([circle1, circle2]);clear()
Remove all children:
group.clear();set(elements)
Replace all children with a new set:
group.set([newCircle, newRect]);children
Get an array of direct child elements:
const kids = group.children; // Element[]graph(includeGroups?)
Flatten the entire element tree into a single array. This recursively collects all non-group elements. Pass true to include group elements in the result:
const allElements = group.graph(); // only leaf elements
const everything = group.graph(true); // includes groups tooQuerying Elements
Groups provide several methods for finding elements, inspired by the DOM API.
getElementById(id)
const circle = group.getElementById('my-circle');getElementsByType(type)
const circles = group.getElementsByType('circle');
const rectsAndLines = group.getElementsByType(['rect', 'line']);getElementsByClass(classes)
const highlighted = group.getElementsByClass('highlighted');
const both = group.getElementsByClass(['active', 'visible']);query(selector) / queryAll(selector)
CSS-like selector querying. Returns the first match or all matches:
const el = group.query('circle.highlighted');
const all = group.queryAll('.shape');Supported Selector Syntax
/* Type */
circle
/* ID */
#my-element
/* Class */
.highlighted
/* Attribute */
circle[radius="50"]
/* Descendants */
.parent circle
.parent > circle
/* Sibling */
rect + circleNOTE
Type and id matching is case-sensitive — #Item and rect will not match an element with id item or type Rect. Extra whitespace in a selector is collapsed, so group circle and group circle are equivalent.
matches(selector)
Tests whether an element matches a CSS-like selector, returning a boolean. matches is a method on every element (it comes from Element, so leaf shapes have it too — not just groups). Multi-segment selectors (with combinators) are evaluated relative to the element's root, so ancestor and sibling constraints are honoured:
group.matches('group'); // true
group.matches('#chart.active'); // matches id + class
circle.matches('circle.highlighted'); // works on any elementA standalone matches(element, selector) function is also exported:
import {
matches,
} from '@ripl/core';
matches(circle, 'circle.highlighted');closest(selector)
Walks up the parent chain (starting with the element itself) and returns the nearest ancestor that matches the selector, or undefined if none do — the inverse of query. Like matches, closest is available on every element:
const chart = marker.closest('#chart'); // nearest ancestor group with id "chart"
group.closest('.panel');A standalone closest(element, selector) function is exported as well.
Nesting Groups
Groups can contain other groups, creating a tree structure:
const innerGroup = createGroup({
fill: '#3a86ff',
children: [circle1, circle2],
});
const outerGroup = createGroup({
lineWidth: 2,
children: [innerGroup, rect],
});Child elements inherit properties through the full chain — circle1 inherits lineWidth from outerGroup and fill from innerGroup.
Rendering
Call render(context) to draw all children in order:
group.render(context);Groups themselves are abstract — they don't draw anything directly. They simply iterate over their children and render each one.
NOTE
For the full list of Group properties and methods, see the Group API Reference.