79306590

Date: 2024-12-24 22:43:39
Score: 0.5
Natty:
Report link

I've found a solution. Im using a circle as a clip path for the image, and then adding a slightly bigger transparent circle for the border. I ended up not having to use the globalCompositeOperation thanks to the clipPath and had to set preserveObjectStacking: true on the canvas to prevent the image (only selectable component) from jumping to the front of the stack.

/** Initialize base canvas */
const initBaseCanvas = (imageSize) => {
const container = document.getElementById("customizer-container");
const containerWidth = container.offsetWidth;
const containerHeight = container.offsetHeight;

// Create base canvas
const initCanvas = new fabric.Canvas("base-image", {
  width: containerWidth,
  height: containerHeight,
  selectable: false,
  evented: false,
  allowTouchScrolling: true,
  backgroundColor: "transparent",
  preserveObjectStacking: true, // Need this to not bring uploaded image to front when moving
});

// Create the image boundary
const circle = new fabric.Circle({
  radius: imageSize / 2,
  backgroundColor: "transparent",
  fill: "#f9f9f9",
  selectable: false,
  evented: false,
  absolutePositioned: true,
});
initCanvas.add(circle);
initCanvas.centerObject(circle);

// Insert uploaded image in the center of the circle and pre-select
const image = new fabric.Image();
image.clipPath = circle;
initCanvas.add(image);

image.setSrc(URL.createObjectURL(uploadedFile), (img) => {
  //  Scale image down if bigger than canvas to ensure bounding box is visible
  const imgWidht = img.width;
  if (!imgWidht || imgWidht >= containerWidth) {
    img.scaleToWidth(containerWidth - 50);
  }

  initCanvas.centerObject(img);
  initCanvas.setActiveObject(img);

  // Colored border
  const circle2 = new fabric.Circle({
    radius: imageSize / 2 + 1,
    stroke: "#fd219b",
    fill: "transparent",
    strokeWidth: 2,
    selectable: false,
    evented: false,
  });
  initCanvas.add(circle2);
  initCanvas.centerObject(circle2);
  initCanvas.getObjects()[2].bringToFront();
  initCanvas.renderAll();
});

return initCanvas;
};
Reasons:
  • Blacklisted phrase (0.5): thanks
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (1):
Posted by: Mich