Fabric.js clipping and panning
- 1 Min. Read.
A client of ours required an interactive canvas with the ability to clip uploaded images into rectangles.
We created a ClipRect class that abstracts all the complexity away, and takes 2 arguments in its constructor:
- The canvas object
- Coordinates of the clipRect
1 2 3 4 5 6 7 |
const canvas = new fabric.Canvas('canvas'); const clipRect = new ClipRect(canvas, { left: 0, top: 0, width: 100, height: 100 }); |
The most interesting part is the clipTo
method on our uploaded image, take a look at our code snippet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
clipTo(ctx) { // Get the viewport absolute panning X and Y let panLeft = this.canvas.viewportTransform[4]; let panTop = this.canvas.viewportTransform[5]; this.setCoords(); ctx.save(); // Reset the context ctx.setTransform(1, 0, 0, 1, 0, 0); // Start drawing ctx.beginPath(); // Get the values ctx.rect( _this._zoom(_this.clipRect.left) + _this._multiplied(panLeft), _this._zoom(_this.clipRect.top) + _this._multiplied(panTop), _this._zoom(_this.clipRect.width), _this._zoom(_this.clipRect.height) ); // Stop drawing ctx.closePath(); // Restore ctx.restore(); } |
Our _zoom
helper will multiply our coordinates with the devicePixelRatio
, so our coordinate system will work well on HiDPI screens (like Macbooks).
1 2 3 4 5 |
// Get the canvas zoom and multiply the given value, dom elements don't need the multiplication with devicePixelRatio _zoom(value, needsDevicePixelRatio = true) { const multiplier = this.canvas.getZoom() * (needsDevicePixelRatio ? fabric.window.devicePixelRatio : 1); // HiDPI ready! return value * multiplier; } |
You can find the source code and a demo on our Github.