#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 #html #canvas #html5-canvas #createjs How to apply ColorMatrix along with Canvas Context

Bounty: 50

I am working on canvas and using EaselJS library to play along.
With EaselJS, I am able to apply the ColorMatrix using Filters

    const myGraphics = new createjs.Shape();
    myGraphics.graphics.bf(img, 'no-repeat')
        .drawCircle(x, y, cursorSize);

    const colorMatrix = [0.3, 0.3, 0.3, 0, 0, 0.3, 0.3, 0.3, 0, 0, 0.3, 0.3, 0.3, 0, 0, 0, 0, 0, 1, 0];
    const blurFilter = new createjs.BlurFilter(5, 5, 1);
    myGraphics.filters = [new createjs.ColorMatrixFilter(colorMatrix), blurFilter];

    myGraphics.cache(0, 0, 500, 500);

Can the same be applied without using EaselJS ?
I have the below code

    const patt = ctx.createPattern(img, 'no-repeat');
    ctx.filter = 'blur(5px)';
    ctx.fillStyle = patt;
    ctx.beginPath();
    ctx.arc(x, y, r1, 0, Math.PI * 2);
    ctx.fill();

How can I apply the colorMatrix filter to the above canvas context?

Thanks in advance


Get this bounty!!!

#StackBounty: #javascript #image-processing #canvas #html5-canvas #createjs Apply grayscale and sepia filters on mousemove – canvas

Bounty: 50

I am trying to apply grayscale and sepia filters on canvas at the time of mouseMove.
Am using CanvasRenderingContext2D.filter for applying the filters.
Here’s the sample code

var radgrad = this.ctx.createRadialGradient(x, y, 50 / 8, x, y, 50 / 2);
radgrad.addColorStop(0, 'rgb(0, 0, 0)');
radgrad.addColorStop(1, 'rgb(0, 0, 0, 1)');

this.ctx.filter = "grayscale(100%) blur(5px) opacity(50%)";
this.ctx.fillStyle = radgrad;
this.ctx.beginPath();
this.ctx.arc(x, y, 50, 0, Math.PI * 2);
this.ctx.fill();

Problem is when I am trying to apply grayscale am not able to achieve it but the blur(5px) is getting applied.

Any solution how to apply grayscale or sepia filter in the above method.

Here’s a sample fiddle

Any lead on the solution will be helpful. Thanks


Get this bounty!!!

#StackBounty: #javascript #canvas #html5-canvas #webrtc #mobile-safari Mobile safari out of memory during video capturing

Bounty: 50

I have React class with two main elements. Canvas and video.
I get video stream and render it at 30fps to canvas.

class GetImage extends Component {

  constructor() {
    super();
    this.constraints = {
      video: {
        width: { ideal: 2048 },
        height: { ideal: 1080 },
        facingMode: {
          exact: 'environment'
        }
      }
    }
  }

  componentDidMount() {
    setVideo(this.video, this.constraints, this.readyToPlayVideo)
  }

  capture = () => {
    const { video } = this
    let canvas = document.createElement('canvas')
    canvas.width = video.videoWidth
    canvas.height = video.videoHeight

    let context = canvas.getContext('2d')
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.drawImage(this.video, 0, 0, canvas.width, canvas.height)
    this.setState({ capture: canvas.toDataURL('image/jpeg') })
    stopVideo()
  }


  readyToPlayVideo = () => {
    const { canvas, video }  = this
    const { offsetHeight, offsetWidth } = video
    const ctx = canvas.getContext('2d')
    ctx.canvas.setAttribute('height', offsetHeight)
    ctx.canvas.setAttribute('width', offsetWidth)

    const timeout = 1000 / 30 // drawing at 30fps

    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

    let _listener = () => {
      (function loop() {
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        ctx.drawImage(video, 0, 0)
        setTimeout(loop, timeout)
      })()
    }

    _listener();
  }


  retake = () =>
    this.setState({ capture: null },
      () => {
        setVideo(this.video, this.constraints, this.readyToPlayVideo, this.handleError)
      }
    )

  render() {
    return (
        
) } }

So far so good.
But I faced a problem with mobile Safari. Looks like it keep every Canvas object ever created in memory.

After several pictures was taken Safari crashes with “out of memory”.
I already do clearRect before rendering a new image, but it doesn’t help.


Get this bounty!!!

#StackBounty: #javascript #jquery #html5 #canvas #html5-canvas Brush effect on page through canvas

Bounty: 50

I am working on a functionality where I have to create a brush like effect on the web-page.

The requirement is that there will be multiple patterns/textures available in the background. And the user will drag the mouse to create the effect of that pattern on the page.

Below is the JSFiddle link where I have created the structure, I am able to create the pattern, but the functionality where I am confused, is that how to create the pattern with the brush effect.

I have added the brush image as a data source in my JSFiddle Link

I am a beginner in canvas, I don’t have any idea on where to move forward, also please let me know if I am going in the right direction.

Check the Reference Website where this functionality is running and working.


Get this bounty!!!