Images in js-draw are made up of images, text, strokes, and other components. Each is represented by a subclass of AbstractComponent.
Let's see how to add a stroke to an editor. Here's a few of the APIs we'll use:
import {
Editor, EditorImage, Stroke, Path, Color4,
} from 'js-draw';
// 1.
const editor = new Editor(document.body);
editor.addToolbar();
// Create path data that we'll use to make the stroke.
const path = Path.fromString('m0,0 l0,40 l40,4 l0,-48 z');
// 2.
const stroke = Stroke.fromFilled(
path, Color4.red,
);
// 3.
const command = editor.image.addComponent(stroke);
// 4.
editor.dispatch(command);
Above:
Editor is created and added to the document.path. For information about how to specify paths, see the MDN documentation on <path> elements.4..editor.dispatch adds the command to the undo history and announces it for accessibility tools. Try replacing editor.dispatch(command) with command.apply(editor). What's the difference?Next, we'll create a large number of strokes
import {
Editor, EditorImage, Stroke, Path, Color4, uniteCommands,
} from 'js-draw';
const editor = new Editor(document.body);
editor.addToolbar();
// 1.
const commands = [];
for (let x = 0; x < 100; x += 10) {
for (let y = 0; y < 100; y += 10) {
// 2. Try changing these!
const strokeWidth = 3;
const strokeColor = Color4.orange;
// 3.
const stroke = Stroke.fromStroked(
// A path that starts at (i,i) then moves three units to the right
`m${x},${y} l3,0`,
{ width: strokeWidth, color: strokeColor },
);
const command = editor.image.addComponent(stroke);
commands.push(command);
}
}
// 4.
const compoundCommand = uniteCommands(commands);
editor.dispatch(compoundCommand);
Above:
Color4.orange with Color4.ofRGBA(x / 100, 0, y / 100, 1).strokeWidth = 3 with strokeWidth = 10.editor.dispatch into the for loop and dispatching the commands one-by-one. Does this change what the undo and redo buttons do? See uniteCommands for more information.Let's start with the previous example and see how to:
---use-previous---
---visible---
// This example starts by running the code from the previous example --
// make sure the previous example compiles!
import { Rect2 } from 'js-draw';
// 1.
const components = editor.image.getComponentsIntersecting(
new Rect2( // a 2D rectangle
5, // x
6, // y
60, // width
30, // height
)
);
// 2.
const styleCommands = [];
for (const component of components) {
// Only process Strokes -- there **are** other types of components.
if (!(component instanceof Stroke)) continue;
const command = component.updateStyle({ color: Color4.red });
styleCommands.push(command);
}
// 3.
editor.dispatch(uniteCommands(styleCommands));
Above:
components.
Stroke.Instead of component.updateStyle, we could have changed the component in some other way. For example, replacing the component.updateStyle(...) with component.transformBy,
---use-previous---
---visible---
// This example starts by running the code from the previous example --
// make sure the previous example compiles!
import { Mat33, Vec2 } from 'js-draw';
const transformCommands = [];
for (const component of components) {
const command = component.transformBy(
Mat33.translation(Vec2.of(45, 0))
);
transformCommands.push(command);
}
editor.dispatch(uniteCommands(transformCommands));
See Mat33 for more transformation types.
The Erase command can be used to remove components from the image:
---use-previous---
---visible---
// This example starts by running the code from the previous example --
// make sure the previous example compiles!
import { Erase } from 'js-draw';
// Deletes all components found in the previous steps
const eraseCommand = new Erase(components);
editor.dispatch(eraseCommand);
Things to try:
eraseCommand.apply(editor). What's the effect on the undo/redo behavior?Erase command with a Duplicate command, then repositioning the original strokes.