#StackBounty: #javascript #html #canvas #html5-canvas #fabricjs FabricJS Alternating between canvas elements?

Bounty: 50

Let’s say I have two canvas elements:

<canvas id="c1" width="400" height="300"></canvas>
<canvas id="c2" width="400" height="300"></canvas>
<canvas id="c3" width="400" height="300"></canvas>

From looking at the docs, it tells me that I can use this to convert the canvas into a FabricJS canvas.

var c = new fabric.Canvas('c1', {
    preserveObjectStacking: true,
    isDrawingMode: false
});

Now, if I wanted to do something with this new canvas, adding a circle for instance, I could use this function:

function AddCircle() {
  var object = new fabric.Circle({
      radius: 15,
      fill: 'blue',
      left: 100,
      top: 100
  });
  c.add(object);
}

Now, this is all well and good for c1 but c2 and c3 won’t do anything because it’s never being initialized. So is it possible to alternate between FabricJS canvas elements?

I’d like the functionality to be similar to activeCanvas.add(object) instead of just c.add(object).

Before you respond, please note that I’m well aware that I could just use the same method for the c2 element, but I’d like to alternate between canvas elements instead as I have something planned for that.


Get this bounty!!!

#StackBounty: #javascript #canvas #fabricjs Apply effects/filters to more than just image objects in FabricJS

Bounty: 50

I’ve been using FabricJS for a while now for my interactive comic builder and for the most part, it’s been great. A limitation however is that – to date – I haven’t been able to find any way to make objects that aren’t images apply effects.

For instance, this guide shows how to render effects over an image object but let’s say for example, I wanted to apply the effect to shapes like rectangles and circles drawn with Fabric or text objects. Is there a way to do this already?

I’m not too interested in presets such as sepia or vintage etc, I really only need the ability to blur, lighten/darken and saturate/unsaturate.


Get this bounty!!!

#StackBounty: #javascript #canvas #html5-canvas #fabricjs #fabricjs2 FabricJS clippath border color and move the overlay image behind c…

Bounty: 50

I am trying to add the clippath area(rect object) over canvas using fabricJS. Currently i set Overlay Image to the canvas and in addition to that am adding clippath area to place objects. I successfully able to place the object inside the clippath, but the problem is whatever image i place it inside clippath has opacity(means object also has transparency), i know is because i set transparent image as overlay which is always top over other object.

My query is

  1. Can i set the clippath area alone to ignore overlay? Or atleast to set the preference like clippath is first priority and next overlay?
  2. Currently clippath has no border and i couldn’t know where the clippath is? So is there a way to set the border over clippath area?

Here is my below code

HTML

<canvas id="ex8" width="300" height="400"></canvas>

JS

(function() {
  var canvas = new fabric.Canvas('ex8');
  canvas.controlsAboveOverlay = true;
  var clipPath = new fabric.Rect({ width: 100, height: 100, fill: 'red' , top:100, left: 100});
 
  
   canvas.setOverlayImage("https://i.ibb.co/88QkSMC/crew-front.png", canvas.renderAll.bind(canvas), {

});
  var group = new fabric.Group([
    new fabric.Rect({ width: 100, height: 100, fill: 'red',globalCompositeOperation : 'xor' }),
    
  
    new fabric.Rect({ width: 100, height: 100, fill: 'blue', top: 100 }),
    new fabric.Rect({ width: 100, height: 100, fill: 'green', left: 100, top: 100 })
  ]);
  
  canvas.clipPath = clipPath;
  canvas.add(group);
})()

Appreciate your help !!!

FIDDLE


Get this bounty!!!

#StackBounty: #javascript #html5-canvas #fabricjs Controlling the Zoom out view port in FabricJS

Bounty: 50

I am trying out the examples given here on the pan and zoom in fabric js and got it working. I am using the zoom to point to zoom where the cursor was. However, the problem I face is that if I zoomIn in one place and zoomOut in another, there is an offset created between the border and background. Even though the code works for restricting the pan area to 1000×400 px, while zooming out, the boundaries are not restricted.

How can I restrict the boundaries even while zooming out, such that there is no offset?

Code here:

(function(){
var canvas = new fabric.Canvas('canvas1',{backgroundImage:"https://images.unsplash.com/photo-1520299607509-dcd935f9a839?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1489&q=80"});
 viewportTransform=canvas.viewportTransform;
    canvas.add(new fabric.Rect({ width: 50, height: 50, fill: 'blue', angle: 10 }))
    canvas.add(new fabric.Circle({ radius: 50, fill: 'red', top: 44, left: 80 }))
    canvas.add(new fabric.Ellipse({ rx: 50, ry: 10, fill: 'yellow', top: 80, left: 35 }))
    canvas.add(new fabric.Rect({ width: 50, height: 50, fill: 'purple', angle: -19, top: 70, left: 70 }))
    canvas.add(new fabric.Circle({ radius: 50, fill: 'green', top: 110, left: 30 }))
    canvas.add(new fabric.Ellipse({ rx: 50, ry: 10, fill: 'orange', top: 12, left: 100, angle: 30 }))
    canvas.on('mouse:wheel', (opt) => {
      var delta = opt.e.deltaY;
      var zoom = canvas.getZoom();
      zoom *= 0.999 ** delta;
      if (zoom > 20) zoom = 20;
      if (zoom < 0.01) zoom = 0.01;
      canvas.zoomToPoint(new fabric.Point(opt.e.offsetX, opt.e.offsetY), zoom);
      opt.e.preventDefault();
      opt.e.stopPropagation();
      var vpt = viewportTransform;
      if (zoom < 0.4) {
        vpt[4] = 200 - 1000 * zoom / 2;
        vpt[5] = 200 - 400 * zoom / 2;
      } else {
        if (vpt[4] >= 0) {
          vpt[4] = 0;
        } else if (vpt[4] < canvas.getWidth() - 1000 * zoom) {
          vpt[4] = canvas.getWidth() - 1000 * zoom;
        }
        if (vpt[5] >= 0) {
          vpt[5] = 0;
        } else if (vpt[5] < canvas.getHeight() - 400 * zoom) {
          vpt[5] = canvas.getHeight() - 400 * zoom;
        }
      }
    });
    canvas.on('mouse:down', function (opt) {
      var evt= opt.e;
      if (evt.altKey === true) {
        this.isDragging = true;
        this.selection = false;
        this.lastPosX = evt.clientX;
        this.lastPosY = evt.clientY;
      }
    });
    canvas.on('mouse:move', function (opt) {
      if (this.isDragging) {
        var e = opt.e;
        var zoom = canvas.getZoom();
        var vpt = this.viewportTransform;
        if (zoom < 0.4) {
          vpt[4] = 200 - 1000 * zoom / 2;
          vpt[5] = 200 - 400 * zoom / 2;
        } else {
          vpt[4] += e.clientX - this.lastPosX;
          vpt[5] += e.clientY - this.lastPosY;
          if (vpt[4] >= 0) {
            vpt[4] = 0;
          } else if (vpt[4] < canvas.getWidth() - 1000 * zoom) {
            vpt[4] = canvas.getWidth() - 1000 * zoom;
          }
          if (vpt[5] >= 0) {
            vpt[5] = 0;
          } else if (vpt[5] < canvas.getHeight() - 400 * zoom) {
            vpt[5] = canvas.getHeight() - 400 * zoom;
          }
        }
        this.requestRenderAll();
        this.lastPosX = e.clientX;
        this.lastPosY = e.clientY;
      }
    });
    canvas.on('mouse:up', function (opt) {
      this.setViewportTransform(this.viewportTransform);
      this.isDragging = false;
      this.selection = true;
    });
})()
https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.6/fabric.min.js
  <canvas id="canvas1" height="300" width="400" style="border:1px solid"></canvas>

Issue Screenshot:
enter image description here


Get this bounty!!!

#StackBounty: #javascript #canvas #html5-canvas #fabricjs How to Limit Object inside Transparent Rectangle Area – FabricJS?

Bounty: 50

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';
});


Get this bounty!!!

#StackBounty: #javascript #canvas #fabricjs Contain a rotated object inside another rotated object FabricJS

Bounty: 100

I have two objects a parent (red) and a child (blue). The parent object is fixed and can’t be moved, only the child object is movable and the child is always bigger than the parent. In whatever way the child object is moved it should always be contained inside the child, which means we should never see the red rectangle.

enter image description here

Demo: https://codesandbox.io/s/force-contain-of-object-inside-another-object-fabric-js-7nt7q

I know there are solutions to contain an object within the canvas or other object boundaries (ex. Move object within canvas boundary limit) which mainly force the top/right/bottom/left values to not exceed the parent values, but here we have the case of two rotated objects by the same degree.

I have a real-life scenario when a user uploads a photo to a frame container. The photo is normally always bigger than the frame container. The user can move the photo inside the frame, but he should not be allowed to create any empty spaces, the photo should always be contained inside the photo frame.


Get this bounty!!!

#StackBounty: #fabricjs Fabricjs function to join 2 objects with line

Bounty: 50

I have a canvas where I can click to place icons and link those icons with a line, but I can’t manage to get the lines to follow when moving the icon objects. I tried the following, but I can’t manage to lock the ends of the lines to the icon objects.

My effort so far: JSFIDDLE

canvas.on('mouse:move', function (obj) {
var line = canvas.getItemByName('line');
var objEl = canvas.getActiveObject();
var type = objEl.get('type');
var leftEl = objEl.left;
var topEl = objEl.top;

canvas.getObjects().forEach((obj) => {
    var lineX1 = line.get('x1');
    var lineY1 = line.get('y1');
    var lineX2 = line.get('x2');
    var lineY2 = line.get('y2');

    if (lineX1 == leftEl && lineY1 == topEl) {
        line.set({
            x1: leftEl,
            y1: topEl
        });
        canvas.renderAll();
    };
});

line.set('opacity', 1);
});


Get this bounty!!!