Search code examples
widthfabricjs

Fabric.js: parts of Line not rendered after updating its dimensions programmatically


I draw a line, then try to change it, leaving the same starting point with x1(left) and x1(top) and moving the endpoint by changing the line's width (x2-x1 - negative when moved left of originating point) and height (determined by y2-y1).

The line is drawn repeatedly with positive width value but 90% of the time it has gaps in the stroke as if the line is not fully stretched from border to border.

Below I define the line, it works well and connects my 2 points. Then, I modify the line when one of the flow objects is moved. When I move the bottom object to the right (positive width), it works fine, when I move to the left (negative width) the line does not reach its borders. The line has borders: true so I can see that the borders are lined up perfectly with the flow objects they are trying to connect (visible in the images).

//[startleft, starttop, endleft, endtop] 
canvas.add(new fabric.Line(
  [globalConnect[0], globalConnect[1], globalConnect[2], globalConnect[3]], {
      stroke:'black', 
      strokeWidth:3,  
      lockScalingX:true, 
      lockScalingY:true, 
      lockRotation:true, 
      hasControls:true, 
      hasBorders:true, 
      lockMovementX:true, 
      lockMovementY:true
    })
);


canvas.item(tempObjectIdx + 1).left = tempX1;
canvas.item(tempObjectIdx + 1).top = tempY1;
canvas.item(tempObjectIdx + 1).width = tempX2-tempX1;
canvas.item(tempObjectIdx + 1).height = tempY2-tempY1;

Example of the line when it's not fully drawn: screenshot

Example of what line looks like with positive width or negative width when it works fine: screenshot

Anybody having similar problems with negative widths when redrawing a line? Is there something to do with origination point - or recalculating coordinates, I do redraw canvas after setting these values - works great for positive value, but the line does not span the border box when width is negative (I have tried redrawing line from bottom origin with positive width and negative height - no better?)


Solution

  • If you just need the line to connect two points and update it whenever those two points are updated, you only have to set the line's x1,y1 and x2,y2 on each appropriate event. Here's an example where such line is updated when the boxes fire moving events:

    const canvas = new fabric.Canvas('c')
    const box1 = new fabric.Rect({
      left: 50,
      top: 50,
      width: 100,
      height: 100,
      fill: 'green'
    })
    const box2 = new fabric.Rect({
      left: 250,
      top: 250,
      width: 100,
      height: 100,
      fill: 'red'
    })
    const box1point = box1.getPointByOrigin('center', 'bottom')
    const box2point = box2.getPointByOrigin('center', 'top')
    const connector = new fabric.Line(
        [box1point.x, box1point.y, box2point.x, box2point.y],
        {
          stroke: "black",
          strokeWidth: 3,
          lockScalingX: true,
          lockScalingY: true,
          lockRotation: true,
          hasControls: true,
          hasBorders: true,
          lockMovementX: true,
          lockMovementY: true
        }
      )
    box1.on('moving', function() {
      const connectPoint = this.getPointByOrigin('center', 'bottom')
      connector.set({
        x1: connectPoint.x,
        y1: connectPoint.y
      })
    })
    box2.on('moving', function() {
      const connectPoint = this.getPointByOrigin('center', 'top')
      connector.set({
        x2: connectPoint.x,
        y2: connectPoint.y
      })
    })
    canvas.add(box1, box2, connector)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.3/fabric.js"></script>
    <canvas id='c' width="500" height="400"></canvas>