App
Rendering app to DOM and animating it.
cm.app([options])
Constructs a new app with the specified options. If no argument is specified, constructs with default options.
All the apps support the following options:
- width - the outer width of the app, number in pixels
- height - the outer height of the app, number in pixels
- frameRate - the number of frames to draw per second
- renderer - the renderer to draw shapes and handle events, defaults to canvas renderer
const app = cm.app({
width: 600,
height: 400,
renderer: cm.canvas(),
});
Apps with terminal renderer support the extra options:
- cols - the number of columns, with a priority level higher than the width
- rows - the number of rows, with a priority level higher than the height
- fontSize - the font size used to render text, see [CSS font-size](CSS font-size)
- fontWeight - the font weight used to render text, see [CSS font-weight](CSS font-weight)
- fontFamily - the font family used to render text, see [CSS font-family](CSS font-family)
- mode - the render mode, single or double, defaults to single
const app = cm.app({
cols: 30,
rows: 30,
renderer: await cm.terminal(),
fontSize: 20,
fontWeight: "bold",
fontFamily: "Georgia, serif",
mode: "double",
});
If mode is single, a cell in terminal renders both single-width and double-width character once . If mode is double, a cell in terminal renders single-width character twice and double-width character once.
Single-width characters include characters like A, a, 1, @, etc,. Double-width characters are characters include characters like 中, 🚀 and strings made of two single-width characters like AB. Double mode aims to address the overlapping issues that arise from the inconsistent widths of single-width and double-width characters.
app.data(data)
Appends a new flow with the specified array of data to the root flow of app, returning the new flow.
app.data([1, 2, 3]);
app.datum([datum])
Appends a new flow with an array containing the specified datum to the root flow app, returning the new flow.
app.datum(1);
The shorthand is thus equivalent to:
app.data([1]);
If no argument is specified, return groups of this app:
app.datum(); // [[1]]
app.append(shape[, options])
Appends a shape with the specified options to this app, returning the new flow that contains the shape. Each shape has its own options, and different shape types support different options. See the respective shape type for details.
app.append(cm.circle, { x: 100, y: 100, r: 50, fill: "orange" });
app.render()
Renders shapes in flows to canvas and removes existing flows, returning this app.
app.append(cm.circle, {
x: cm.random(50, 100),
y: cm.random(50, 100),
r: 25,
fill: "orange",
});
app.render();
app.append(cm.circle, {
x: cm.random(50, 100),
y: cm.random(50, 100),
r: 25,
fill: "steelblue",
});
app.render();
app.start()
Starts this app and returns it, firing update event repeatedly until calling app.stop. This allows this app to invoke the update callback every delay milliseconds, which is controlled by the frameCount option. Note that app.render will be invoked automatically at the end of each frame, so there is no need to call it explicitly. For example, to draw a moving rect:
let x = 0;
function update() {
app.append(cm.rect, {
x: x++,
y: 0,
width: 100,
height: 50,
});
}
app.on("update", update);
app.start();
app.stop()
Stops this app and returns it, cancelling firing update, thereby stops the animation.
app.on("update", update);
app.start();
// Stops animation after 5 seconds.
setTimeout(() => app.stop(), 5000);
app.dispose()
Disposes this app and returns it, stopping the timer to firing update event and removing all event listeners.
app.on("update", update);
app.on("mouseMove", mouseMove);
app.dispose();
app.node()
Returns the [canvas element](canvas element) for drawing shapes.
document.body.append(app.node());
app.prop(name)
Returns the property with the specified name for this app. See the respective property name for details.
app.prop("width"); // 640
app.on(type, listener)
Adds a listener for the specified event type. Multiple listeners can be registered to receive the same event.
function mouseMove() {}
function mouseMove1() {}
app.on("mouseMove", mouseMove).on("mouseMove", mouseMove1);
See the respective event type for details.
app.call(callback[, …argument])
Calls the specified function on this app with any optional arguments and returns this app. This is equivalent to calling the function by hand but avoids to break method chaining. For example, to draw two concentric circles in a reusable function:
function ring(app, { x, y, r, r1, fill, fill1 }) {
app.append(cm.circle, { x, y, r, fill });
app.append(cm.circle, { x, y, r1, fill2 });
}
ring(app, {
x: 100,
y: 100,
r: 25,
r1: 50,
fill: "orange",
fill1: "steelblue",
});
Instead of invoking this function directly on app, now say:
app.call(ring, {
x: 100,
y: 100,
r: 25,
r1: 50,
fill: "orange",
fill2: "steelblue",
});
app.textBBox(text, textOptions)
Computes the bounding box for the specified textOptions. The returned bounding box has the following properties:
- x - the x coordinate of the text
- y - the y coordinate of the text
- width - the width of the text
- height - the height of the text
const bbox = app.textBBox({
text: "hello world",
fontSize: 20,
fontWeight: "bold",
});
cm.canvas()
Constructs a canvas renderer, drawing shapes with CanvasRenderingContext2D. It is the default renderer for app and there is no need to specify it explicitly.
const app = cm.app({
height: 200,
renderer: cm.canvas(), // not necessary
});
app.append(cm.circle, {
x: 100,
y: 100,
r: 50,
fill: "orange",
});
app.render();
