I'm trying to achieve a "bent" effect with an image in Fabric.js. Specifically, I want to manipulate the positions of the corners (for example, the top-right and bottom-right corners) of an image so that the image looks as if it's "folding" or "bending" along the edges.
One approach I considered is using a polygon and overlaying the image, adjusting the polygon's points and using them to "fold" the image in the desired way. However, I'm not sure how to properly apply such a transformation to the image in Fabric.js.
Is there a built-in way to "bend" or distort an image along the edges or how can I use polygons to overlay and give the appearance of a bent image?
Here's a simplified example:
I want to manipulate the top-right and bottom-right corners of the image to make it look like the image is folded or bent at those points.
I’m looking for a solution that works smoothly when the object is moved or resized as well.
Can someone guide me on how to achieve this effect?
const addPointsAndLines = (canvas: fabric.Canvas) => { const r = 6; const points = [ { x: 167, y: 200 }, { x: 500, y: 200 }, { x: 500, y: 400 }, { x: 200, y: 400 }, ]; const circles: fabric.Circle[] = points.map((pt) => { const circle = new fabric.Circle({ left: pt.x - r, top: pt.y - r, radius: r, fill: "red", hasBorders: false, hasControls: false, selectable: true, }); canvas.add(circle); return circle; }); const polygon = new fabric.Polygon(points, { fill: "rgba(128,128,128,0.4)", selectable: false, evented: false, }); fabric.Image.fromURL("public/FD1C43.webp").then((img) => { const pattern = new fabric.Pattern({ source: img.getElement(), repeat: "no-repeat", }); polygon.set({ fill: pattern, }); canvas.renderAll(); }); canvas.add(polygon); canvas.sendObjectToBack(polygon); polygonRef.current = polygon; const lines: fabric.Line[] = circles.map((_, i) => { const curr = circles[i]; const next = circles[(i + 1) % circles.length]; const line = new fabric.Line( [curr.left! + r, curr.top! + r, next.left! + r, next.top! + r], { stroke: "#000", strokeWidth: 2, strokeDashArray: [6, 4], selectable: false, evented: false, } ); canvas.add(line); return line; }); canvas.on("object:moving", () => { circles.forEach((circle, i) => { const cx = circle.left + r; const cy = circle.top + r; polygon.points[i].x = cx; polygon.points[i].y = cy; const prevLine = lines[(i - 1 + lines.length) % lines.length]; const nextLine = lines[i]; prevLine.set({ x2: cx, y2: cy }); nextLine.set({ x1: cx, y1: cy }); }); polygon.set({ dirty: true, }); polygon.setCoords(); polygon.setBoundingBox(true); canvas.renderAll(); }); canvas.renderAll(); };
