Q:

How to Limit Object inside Transparent Rectangle Area - FabricJS?

I am implementing designer functionality using FabricJS in my side. My Idea is to set the background image using setBackgroundImage from fabric, also i add specific area of transparent rectangle with size and position fetch from JCrop. Now come to my question, i want to restrict the object placement within that specific area of transparent rectangle. Let say i want to add text/image/shapes that should be in that limited area, i able to implement the background image, position of transparent rectangle and even circle shape object but i unable to find details to limit object place it inside transparent rectangle and only in that region.
Here is my below code and working fiddle, If you see it in fiddle the image where you need to select the cropping portion and below that canvas background with transparent rectangle which is the one of same like crop selection. Now i want to limit the object placement anything to be in that transparent rectangle, right now i can place object in anywhere in the canvas.
HTML
   <img src="https://images.unsplash.com/photo-1595438337199-d50ba5072c7e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=330&q=80" id="target">

   <div class="canvas-container" style="position: relative; user-select: none;">
     <canvas id="c1" width="600" height="600" style="border:1px solid #ccc; position: absolute;  left: 0px; top: 0px; touch-action: none; user-select: none;"></canvas>
   </div>

JS
function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
  var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
  return {
    width: srcWidth * ratio,
    height: srcHeight * ratio,
    aspectratio: ratio
  };
}

jQuery(function($) {
    //alert("Testing");
  var img = new Image();
  img.onload = function() {
    var data = calculateAspectRatioFit(this.width, this.height, '400', '600');
    console.log(data);
    jQuery('#target').attr('width', data.width);
    jQuery('#target').attr('height', data.height);
    jQuery('#pdr-drawing-area').html("Aspect Ratio: " + data.aspectratio);
    const stage = Jcrop.attach('target');
    stage.listen('crop.change', function(widget, e) {
      const pos = widget.pos;
      console.log(pos.x, pos.y, pos.w, pos.h);
      //fabric js
      var canvas = new fabric.Canvas('c1');
      var center = canvas.getCenter();
      var img = 'https://images.unsplash.com/photo-1595438337199-d50ba5072c7e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=330&q=80';
      canvas.setBackgroundImage(img, function() {
        canvas.backgroundImage && canvas.backgroundImage.scaleToWidth(data.width);
        canvas.backgroundImage && canvas.backgroundImage.scaleToHeight(data.height);
        //canvas.sendToBack(img);
        canvas.renderAll();
      });
      console.log(pos.x * data.aspectratio);
      var rect = new fabric.Rect({
        left: pos.x,
        top: pos.y,
        fill: 'transparent',
        width: (pos.w),
        height: (pos.h),
        strokeDashArray: [5, 5],
        stroke: "black",
        selectable: false,
        evented: false,
        //visible: false
      });

      canvas.add(new fabric.Circle({
        radius: 30,
        fill: '#f55',
        top: pos.y + 2,
        left: pos.x + 2
      }));

      canvas.add(rect);
      canvas.setHeight(data.height);
      canvas.setWidth(data.width);
      canvas.renderAll();
    });
  },
   img.src = 'https://images.unsplash.com/photo-1595438337199-d50ba5072c7e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=330&q=80';
});

A:

Here is an example of how to restrict movement in FabricJS.
I'm using the stateful property of the canvas, see function objectMoving below.

var canvas = new fabric.Canvas("canvas");
canvas.stateful = true;

function inside(p, vs) {
    var inside = false;
    for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
        var xi = vs[i].x, yi = vs[i].y;
        var xj = vs[j].x, yj = vs[j].y;
        var intersect = yi > p.y !== yj > p.y && p.x < ((xj - xi) * (p.y - yi)) / (yj - yi) + xi;
        if (intersect) inside = !inside;
    }
    return inside;
}

function getCoords(rect) {
    var coords = []
    coords.push(rect.aCoords.tl);
    coords.push(rect.aCoords.tr);
    coords.push(rect.aCoords.br);
    coords.push(rect.aCoords.bl);
    coords.push(rect.aCoords.tl);
    return coords;
}

function objectMoving(e) {
    var cCoords = getCoords(parent);
    var inBounds = inside({ x: e.target.left + 30, y: e.target.top + 30 }, cCoords);

    if (inBounds) {
        e.target.setCoords();
        e.target.saveState();
    } else {
        e.target.left = e.target._stateProperties.left;
        e.target.top = e.target._stateProperties.top;
    }
}

var boundary = new fabric.Rect({
    width: 310, height: 170,
    left: 5, top: 5,
    selectable: false,
    strokeDashArray: [5, 2],
    stroke: "blue",
    fill: "transparent"
});

var parent = new fabric.Rect({
    width: 250, height: 110,
    left: 35, top: 35,
    selectable: false,
    strokeDashArray: [2, 5],
    stroke: "black",
    fill: "transparent"
});

var child = new fabric.Circle({
    radius: 30,
    fill: "rgba(255,0,0,0.8)",
    top: 50, left: 50,
    hasControls: false,
});

canvas.add(boundary);
canvas.add(parent);
canvas.add(child);
canvas.on("object:moving", objectMoving);
<canvas id="canvas" width="400" height="180"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.2/fabric.min.js"></script>

In the function inside I'm using the ray-casting algorithm, you can read more about it here:
https://github.com/substack/point-in-polygon/blob/master/index.js
I prefer this algorithm because it opens the door for later allowing more complex shapes as the parent boundaries, it can work with a polygon of any shape.
If you need any clarifications on that code let me know.

Now you do need to integrate that into your project and dynamically change the parent boundaries as they change in the user in the "JCrop" selection

