0

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?

enter image description here

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(); 

};

2
  • Old school is "perspective slice". Slice the image vertically and drawImage the slices in shrinking height into the background) New school, and best is WebGL because it can do actual 3d transformations. Commented May 14 at 3:51
  • fabricjs is really meant for 2D and does not seem to have perspective/skew options. one alternative solution would be to use a 3D library and use the image as a texture on a plane. Commented May 29 at 11:17

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.