This guide demonstrates changing which part of an image is visible in an Editor.
Related APIs:
Command
that moves/zooms/rotates the viewport.Command
.Viewport.transformBy
how to move/scale/rotate.
Mat33.scaling2D(2)
zooms in by a factor of 2.For example, to zoom out by a factor of 4,
import { Editor, Viewport, Mat33 } from 'js-draw'; const editor = new Editor(document.body); // 1 editor.addToolbar(); const command = Viewport.transformBy(Mat33.scaling2D(1/4)); // 2 editor.dispatch(command); // 3
Above:
document.body
.transformBy
command is created. In this case, the command scales the viewport by a factor of 4.
1/4
with 1/2
. This should zoom out by a factor of 2.1/4
with 4
. This should zoom in by a factor of 4.command
to the editor.
transformBy
command is unapplied.In the example above, pressing "undo" unapplies the zoom command. There are at least two ways to prevent this:
editor.dispatch(command)
with command.apply(editor)
.
command
was done for accessibility tools.editor.dispatch(command)
with editor.dispatch(command, false)
.import { Editor, Viewport, Mat33 } from 'js-draw'; const editor = new Editor(document.body); // 1 editor.addToolbar(); ---visible--- const command = Viewport.transformBy(Mat33.scaling2D(1/4)); // 2 editor.dispatch(command, false); // false: Don't add to history // Alternatively, // command.apply(editor);
See also Editor.dispatchNoAnnounce.
Let's start by creating an editor and adding it to the document:
import { Editor } from 'js-draw'; // Create an editor with a toolbar: const editor = new Editor(document.body); editor.addToolbar();
Next, to make it clear that the editor is moving, let's give the editor a repeating background:
---use-previous--- ---visible--- import { Color4, BackgroundComponentBackgroundType } from 'js-draw'; editor.dispatch( editor.setBackgroundStyle({ color: Color4.orange, type: BackgroundComponentBackgroundType.Grid, // Make the background autoresize so that it's always // visible: autoresize: true, }), );
Next, let's move the viewport in a loop:
---use-previous--- ---visible--- import { Viewport } from 'js-draw'; import { Mat33, Vec2 } from '@js-draw/math'; // When moveLeftUpdate is applied to the viewport, it moves the // viewport to the left by 1 unit. const moveLeftUpdate = Mat33.translation(Vec2.of(-1, 0)); function update() { const moveLeftCommand = Viewport.transformBy(moveLeftUpdate); moveLeftCommand.apply(editor); requestAnimationFrame(update); } update();
Above, the Vec2.of(-1, 0)
gives the direction to move the viewport.
Things to try:
Vec2.of(-1, 0)
with Vec2.of(0, 1)
. How is the viewport updated?.apply
twice or use Mat33.rightMul to combine the two transformations.The above update loop has a problem — on some devices, the viewport moves faster than on others.
To fix this, we determine the time elapsed between each animation frame and use this to scale the position change:
import { Editor } from 'js-draw'; import { Color4, BackgroundComponentBackgroundType } from 'js-draw'; const editor = new Editor(document.body); editor.addToolbar(); editor.dispatch( editor.setBackgroundStyle({ color: Color4.orange, type: BackgroundComponentBackgroundType.Grid, autoresize: true, }), ); ---visible--- import { Viewport } from 'js-draw'; import { Mat33, Vec2 } from '@js-draw/math'; let lastTime = performance.now(); function update() { // Get how long many milliseconds have elapsed since the last update. const nowTime = performance.now(); const millisecondsElapsed = nowTime - lastTime; const seconds = millisecondsElapsed / 1000; lastTime = nowTime; const moveLeftRate = -10; // units/second const moveLeftAmount = Vec2.of(moveLeftRate * seconds, 0); const moveLeftUpdate = Mat33.translation(moveLeftAmount); const moveLeftCommand = Viewport.transformBy( moveLeftUpdate ); moveLeftCommand.apply(editor); requestAnimationFrame(update); } update();