Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update Selection Box in fabric.Path

Version

3.4.0

Information about environment

Google Chrome | 77.0.3865.120 (Official Build) (64-bit) (cohort: Stable) Revision | 416d6d8013e9adb6dd33b0c12e7614ff403d1a94-refs/branch-heads/3865@{#884} OS | Windows 10 OS Version 1803 (Build 17134.1099) JavaScript | V8 7.7.299.13

Test Case

https://jsfiddle.net/areuohm/y2not8em/32/

(function(){
var canvas = new fabric.Canvas('canvasWorkspaceFamiliogram', { selection: false });
 		fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
    
var itemM = new fabric.Rect({width: 30,height: 30,fill: 'white',stroke: 'black',strokeWidth: 1, left:50,top:50});   
var itemF = new fabric.Circle({radius: 15,fill: 'white',stroke: 'black',strokeWidth: 1,left: 400,top: 200});

 itemF.relations = [];
 itemM.relations = [];
 
 canvas.add(itemM);
 canvas.add(itemF);
 createSVGPath(itemF,itemM,canvas);
 canvas.renderAll();

}());
function createSVGPath(startObj, endObj, context){                
  var svgCommands = [
    [ 'L', startObj.left, startObj.top],
    [ 'V',  startObj.top + 50],
    [ 'H', endObj.left, endObj.top + 50],
    [ 'V', endObj.top]
  ];

  var line = new fabric.Path(svgCommands, {
    fill: '', stroke: 'black', objectCaching: false, dirty: false,  
    perPixelTargetFind: true, selectable: true, hasControls: false
  });               
        
  context.add(line);         
  let mi = svgCommands.length - 1;

  startObj.relations.push({relation: line, maxIndex: mi, type:'M'});
  endObj.relations.push({relation: line, maxIndex: mi, type:'Z'});

  startObj.on('moving', function (e) {               
    this.relations.forEach((T,index) => {                        
      if(T.type === 'M'){                    
        T.relation.path[0][1] = e.target.left;
        T.relation.path[0][2] = e.target.top;                    
      }
    });
    context.requestRenderAll();
  });

  endObj.on('moving', function (e) {
    this.relations.forEach((T,index) => {                
      if(T.type === 'Z'){                    
        T.relation.path[T.maxIndex - 1][1] = e.target.left;                    
        T.relation.path[T.maxIndex ][1] = e.target.top;                    
      }                
    });
    context.requestRenderAll();
  });
}
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.4.0/fabric.min.js"></script>
<canvas id="canvasWorkspaceFamiliogram" width="500" height="470" style="border:1px solid #ccc"></canvas>

Steps to reproduce

In the initial state when i create the path the selection box is according to the line. but if i move the circle or square, the selection box in the path line doesnt update

Expected Behavior

¿How can i refresh or update this box?

Issue in Github

https://github.com/fabricjs/fabric.js/issues/5928

like image 714
Areu Avatar asked Nov 06 '22 13:11

Areu


1 Answers

You need to update the pathoffset of path object and call setCoords after any of your start or end point modified.

DEMO

(function() {
  const canvas = new fabric.Canvas('canvasWorkspaceFamiliogram', {
    selection: false
  });
  fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';

  const itemM = new fabric.Rect({
    width: 30,
    height: 30,
    fill: 'white',
    stroke: 'black',
    strokeWidth: 1,
    left: 50,
    top: 50
  });
  const itemF = new fabric.Circle({
    radius: 15,
    fill: 'white',
    stroke: 'black',
    strokeWidth: 1,
    left: 400,
    top: 200
  });

  itemF.relations = [];
  itemM.relations = [];

  canvas.add(itemM);
  canvas.add(itemF);
  createSVGPath(itemF, itemM, canvas);
  canvas.renderAll();

}());

function createSVGPath(startObj, endObj, context) {
  const svgCommands = [
    ['L', startObj.left, startObj.top],
    ['V', startObj.top + 50],
    ['H', endObj.left, endObj.top + 50],
    ['V', endObj.top]
  ];

  const line = new fabric.Path(svgCommands, {
    fill: '',
    stroke: 'black',
    objectCaching: false,
    dirty: false,
    perPixelTargetFind: true,
    selectable: true,
    hasControls: false
  });

  context.add(line);
  const mi = svgCommands.length - 1;

  startObj.relations.push({
    relation: line,
    maxIndex: mi,
    type: 'M'
  });
  endObj.relations.push({
    relation: line,
    maxIndex: mi,
    type: 'Z'
  });

  startObj.on('moving', function(e) {
    this.relations.forEach((T, index) => {
      if (T.type === 'M') {
        T.relation.path[0][1] = e.target.left;
        T.relation.path[0][2] = e.target.top;
      }
    });
    context.requestRenderAll();
  });

  endObj.on('moving', function(e) {
    this.relations.forEach((T, index) => {
      if (T.type === 'Z') {
        T.relation.path[T.maxIndex - 1][1] = e.target.left;
        T.relation.path[T.maxIndex][1] = e.target.top;
      }
    });
    context.requestRenderAll();
  });

  startObj.on('modified', updatePath);
  endObj.on('modified', updatePath);
}

function updatePath() {
  this.relations.forEach((T, index) => {
    const obj = T.relation;
    if (obj.type === 'path') {
      fabric.Polyline.prototype._setPositionDimensions.call(obj, {});
      obj.setCoords();
    }
  })
}
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.4.0/fabric.min.js"></script>
<canvas id="canvasWorkspaceFamiliogram" width="500" height="470" style="border:1px solid #ccc"></canvas>
like image 194
Durga Avatar answered Nov 12 '22 18:11

Durga