Playground
Try every knob
Adjust the controls — the code block updates with the exact options to recreate this configuration. Hit Copy and paste into your project.
Settings
Press ↑ ↓ ← → (or WASD) to move the pen — the knobs spin to match. Hold two arrows for diagonals. Click either knob to clear.
Install
Drop it in
No build step, no framework — one stylesheet, one script, one container.
<link rel="stylesheet" href="path/to/etchasketch.css">
<script src="path/to/etchasketch.js"></script>
<div id="toy"></div>
<script>
const sketch = new EtchASketch('#toy', {
penColor: '#1f1f1f',
penWidth: 2,
stepPx: 1.8,
screenColor: '#b8b8a9',
});
// Live tuning — every option is hot-swappable.
sketch.setOptions({ cursor: true });
</script>
new EtchASketch(target, options?) mounts the red bezel + knobs + canvas into target (a selector or element) and starts listening for arrow keys. Mount as many as you like on a page — each is its own instance.
Controls
What every input does
The left knob is the horizontal axis; the right knob is the vertical axis — just like the real toy.
| Input | Effect |
|---|---|
| → / D | Pen right; left knob spins clockwise |
| ← / A | Pen left; left knob spins counterclockwise |
| ↓ / S | Pen down; right knob spins clockwise |
| ↑ / W | Pen up; right knob spins counterclockwise |
| Hold two arrows | Diagonal — normalized so it's the same speed as a single arrow |
| Click either knob | Clear the screen (with shake animation) |
| Shake the phone | Clear (via DeviceMotionEvent; iOS needs enableShake()) |
| Mouse / touch drag | Draw — only when cursor: true |
Reference
Options
Pass these at construction, or pass any of them later via setOptions().
new EtchASketch('#toy', {
penColor: '#1f1f1f', // CSS color of the line
penWidth: 2, // stroke width in CSS px
stepPx: 1.8, // pen pixels per frame per held arrow
screenColor: '#b8b8a9', // background fill (defaults to aluminum gray)
chrome: true, // render the red bezel + knobs (false = headless canvas)
cursor: false, // allow mouse/touch drag to draw (off = classic mode)
shakeToErase: true, // listen for devicemotion and clear on a hard shake
shakeThreshold: 22, // accelerometer magnitude required (m/s²)
knobsClickToClear: true, // click either knob to clear
knobDegPerPx: 2.2, // how fast each knob spins per pen pixel
});
Methods
sketch.clear(); // wipe the screen + run the shake animation
sketch.setOptions({ ... }); // merge + apply (hot-swap any option)
sketch.getDataURL('image/png'); // PNG data URL of the current drawing
sketch.enableShake(); // call from a user gesture on iOS to grant motion access
sketch.resetPenTo(x, y); // move the pen without drawing a line
sketch.destroy(); // tear down DOM + listeners
Recipes
Cursor mode
By default, only the keyboard moves the pen. That keeps the experience faithful to the original 1960s Magic Screen — and means mouse/touch input on the canvas does nothing. To enable click-drag and finger-drag drawing:
const sketch = new EtchASketch('#toy', { cursor: true });
// ...or toggle it later:
sketch.setOptions({ cursor: true });
When cursor: true, the canvas shows a crosshair cursor, the pen jumps to wherever the user presses, and dragging strokes a line that the knobs also follow.
Headless mode
Skip the red bezel + knobs entirely and paint the interaction model onto your own design:
new EtchASketch('#raw', { chrome: false });
Your host element gets just the canvas. Arrow keys still draw; cursor: true still enables drag drawing.
Phone shake to clear (iOS)
Android and desktop browsers fire devicemotion events without a permission grant — shake works out of the box. iOS 13+ requires a one-time grant tied to a user gesture:
document.getElementById('btn-enable').addEventListener('click', () => {
sketch.enableShake(); // shows the iOS permission dialog
});