第一次移动后对象松散交互

时间:2016-02-16 13:46:51

标签: javascript canvas fabricjs

我试图制作一个构造函数并且遇到一些Fabricjs的问题,看起来像一个bug。

我有很多对象,例如在fabricjs示例中:http://fabricjs.com/stickman/

我有一些点(circle = Array(); circle [i] = new Fabric.Circle({...})和与它们相连的行(var line = new Fabric.Line({...} ); circle [i] .line = line;)

我让用户用点画一些图,然后我想让他像一个火山人一样编辑这个图。

但我有一定的规则:水平线应保持水平,垂直线应保持垂直,并且我们编辑的点之后的线条尺寸应保留。

所以,我用

抓住了一个元素

canvas.on(' object:moving',function(e){     var p = e.target;

然后我改变前一行和下一行(根据规则)然后(SIC!)我改变所有其他点的坐标(我根据规则改变circle [i] .left和circle [i] .top)。

之后重新绘制点,但实际上画布仍然认为它们位于以前的坐标上! (我不能选择我看到的点,但我可以选择以前的点空位)

在这里,我抓住了用户想要移动的对象:

canvas.on('object:moving', function(e) {
    var p = e.target;
    var x2;
    var y2;
    var type;


    if (p.line1) type=p.line1.type;
    else type=p.line2.type;

    if (type==1)
      {
        x2=p.left;
        y2=p.y;
      }
    if (type==2)
      {
        x2=p.x;
        y2=p.top;
      }
    if (type==3)
      {
        var delta=Math.sqrt((p.top-p.y)*(p.top-p.y)+(p.left-p.x)*(p.left-p.x));
        if (p.left>p.x)
        x2=p.x+delta;
         else x2=p.x-delta;
        if (p.top<p.y)
            y2=p.y-delta;
            else y2=p.y+delta;
       }

     p.left=x2;
     p.top=y2;
     p=fix_point(p);
     points=reorder(points,p.id);

    });

`

这是fix_point(p):

 function fix_point (p)
     {

     if (p.line1)
     {
       p.line1.set({ 'x1': p.left, 'y1': p.top });
       if (p.line1.type==1)
         {
         p.line1.line1.set({ 'x1': p.left, 'y1': p.top+3 });
         p.line1.line2.set({ 'x1': p.left, 'y1': p.top-3 });
           }
         else
         {
          p.line1.line1.set({ 'x1': p.left+3, 'y1': p.top });
          p.line1.line2.set({ 'x1': p.left-3, 'y1': p.top });
             }
      }
     if (p.line2)
    {  p.line2.set({ 'x2': p.left, 'y2': p.top });
        if (p.line2.type==1)
         {
         p.line2.line1.set({ 'x2': p.left, 'y2': p.top+3 });
         p.line2.line2.set({ 'x2': p.left, 'y2': p.top-3 });
           }
         else
         {
          p.line2.line1.set({ 'x2': p.left+3, 'y2': p.top });
          p.line2.line2.set({ 'x2': p.left-3, 'y2': p.top });
             }
       }
     return p;
     }

这是重新排序(points,id):

function reorder(points, id)
{

   points[id].fill='green';
   var x2;
   var y2;
   var m;
   var delta;
    for (var k=id; k<points.length-2; k++)
    {
     points[k+1].fill='yellow';
     if (points[k].line2)
      {
        if (points[k].line2.type==1)
         {  if (points[k+1].top!=points[k].top)
               {x2=points[k+1].left;
                y2=points[k].top;
                 }
             else
             {  delta=points[k].left-points[k].x;
                    x2=points[k+1].left+delta;
                    y2=points[k+1].top;

             }

          }
        if (points[k].line2.type==2)
        {

            if (points[k+1].left!=points[k].left)
               {x2=points[k].left;
                y2=points[k+1].top;
                 }
             else
             {  delta=points[k].top-points[k].y;
                    x2=points[k+1].left;
                    y2=points[k+1].top+delta;

             }
         }
         if (points[k].line2.type==3)
          {
          if ((points[k].line1)&&(points[k].line1.type==1))
              {
                delta=points[k].left-points[k].x;
                x2=points[k+1].left+delta;
                y2=points[k+1].top;
              }

            if ((points[k].line1)&&(points[k].line1.type==2))
              {
                delta=points[k].top-points[k].y;
                x2=points[k+1].left;
                y2=points[k+1].top+delta;
              }
          } 

       if (x2<0) x2=0;
       if (y2<0) y2=0;
       if (x2>500) x2=500;
       if (y2>500) y2=500;
       points[k+1].left=x2;
       points[k+1].top=y2;
       canvas.renderAll();
      }
    }

    for (var k=id; k<points.length-1; k++)
    {
     points[k].x=points[k].left;
     points[k].y=points[k].top;
     points[k].text.left=points[k].left+10;
     points[k].text.top=points[k].top;
     points[k]=fix_point(points[k]);
         }
  return points;
}

您可以在此处尝试:jsfiddle.net/Lasana/bwdoy5v1/

首先按下DRAW并加点。以双击结束。然后按编辑 - 您将看到所有点红色和编号。尝试改变水平或垂直线的某些点。然后看看画布!绿色和红色点可供选择。

在他们的新地方绘制黄点,但可以选择点击他们的旧地方 - 空白空间!但如果我发现那个空的空间 - 我也可以编辑这一点......

我无法理解这是什么? :)))))

我如何解决它?...

1 个答案:

答案 0 :(得分:1)

fabricjs中的常见错误是修改对象topleft而不使用obj.setCoords();

在第一次编辑后,这将不允许进一步的鼠标交互。 请参阅随附的片段,小提琴的副本。 我刚刚在reorder函数的末尾添加了point[k].setCoords()调用。

      var canvas=new fabric.Canvas('c',{ selection: false });
      var start=0;
      var cur=0;
      var i=0;
      var xcoord=[];
      var ycoord=[];
      var points=[];
      var lines=[];

      var DrawMode = document.getElementById('draw'),
      EditMode = document.getElementById('edit');

      DrawMode.onclick=Drawing;
      EditMode.onclick=Editing;

      var drawline=new fabric.Line([0,0,0,0], {stroke: 'rgba(0,255,0,0.3)'});
   	  canvas.add(drawline);

   
    function putPoint(x,y)
      {
        var point=new fabric.Circle({
         radius: 7,
         fill: '#fff',
         stroke: '#000',
         originX: 'center',
         originY: 'center',
         strokeWidth: 4,
         left: x,
         top: y
            });
         point.hasControls = point.hasBorders = point.selectable = false;
         point.x=x;
         point.y=y;
         point.id=0;


         return point;
    }

    function goStraight(x1, x2, y1, y2)
     {
   
         if ((Math.abs(x2-x1)>0)&&(Math.abs(y2-y1)==0))
         {
         if (x2>x1)
              { x1=x1+5;}
           else
              { x1=x1-5;}

            var line=new fabric.Line([x2,y2,x1,y1],{stroke: 'rgba(0,0,0,0.3)'});
            var line1=new fabric.Line([x2,y2+3,x1,y1+3],{stroke: 'rgba(0,0,0,0.3)'});
            var line2=new fabric.Line([x2,y2-3,x1,y1-3],{stroke: 'rgba(0,0,0,0.3)'});
            line.type=1;
           }

         if ((Math.abs(x2-x1)==0)&&(Math.abs(y2-y1)>0))
          {

         if (y2>y1)
             {y1=y1+5;}
           else
             {y1=y1-5;}


             var line=new fabric.Line([x2,y2,x1,y1],{stroke: 'rgba(0,0,0,0.3)'});
             var line1=new fabric.Line([x2+3,y2,x1+3,y1],{stroke: 'rgba(0,0,0,0.3)'});
             var line2=new fabric.Line([x2-3,y2,x1-3,y1],{stroke: 'rgba(0,0,0,0.3)'});
             line.type=2;
          }


         if (Math.abs(x2-x1)==Math.abs(y2-y1))
           {
         if (x2>x1)
              { x1=x1+5;}
           else
              { x1=x1-5;}

            var line=new fabric.Line([x2,y2,x1,y1],{stroke: 'rgba(0,0,0,0.3)'});
            var line1=new fabric.Line([x2,y2+3,x1,y1+3],{stroke: 'rgba(0,0,0,0.3)'});
            var line2=new fabric.Line([x2,y2-3,x1,y1-3],{stroke: 'rgba(0,0,0,0.3)'});
            line.type=3;
           }

         line.hasControls = line.hasBorders = line.selectable = false;
         line1.hasControls = line1.hasBorders = line1.selectable = false;
         line2.hasControls = line2.hasBorders = line2.selectable = false;

         var start=new fabric.Circle({originX:'center', originY:'center', radius: 4, left:x1, top: y1, fill: 'blue'});
         start.hasControls=false;

         line.line1=line1;
         line.line2=line2;
         line.start=start;


         return line;

    }

   function joinPoint(point, lineleft, lineright)
            {
            point.line1=lineleft;
            point.line2=lineright;

            return point;
            }

    function DrawPoint(event)
     {
  
     var CX = event.offsetX==undefined?event.layerX:event.offsetX;  // x2
     var CY = event.offsetY==undefined?event.layerY:event.offsetY;  // y2

     var x1=xcoord[cur-1];  // x1
     var y1=ycoord[cur-1];  // y1
     var newx=CX;
     var newy=CY;


   //  *(0,0)                Y
   //                        |             Z
   //                  1     | 1     2   /
   //                        |         /
   //                        |       /   2
   //           6        y2  |------------ *
   //                        |   /         |
   //                        | /           |    3
   //   ---------------------*-------------------------X
   //           6          / |x1,y1        x2
   //                    /   |
   //                5 /     |                 3
   //                /  5    |
   //              /         |
   //            /         4 |    4
   //                        |
   //                        |
   //
   //

     var x=CX-x1;
     var y=y1-CY;

     var type=0;

  
     if ((x>=0)&&(y>=0))
       {
       	if (y<=0.5*x)
       	  type=3;
       	if ((y>0.5*x)&&(y<2*x))
       	  type=2;
       	if (y>=2*x)
       	  type=1;

       }


     if ((x>=0)&&(y<0))
        {
        	if (Math.abs(y)<x)
        	  type=3;
        	else
        	  type=4;
        }


     if ((x<0)&&(y<0))
       {
       	if (Math.abs(y)<0.5*Math.abs(x))
       	    type=6;
       	if ((Math.abs(y)>=0.5*Math.abs(x))&&(Math.abs(y)<=2*Math.abs(x)))
       	    type=5;
       	if (Math.abs(y)>2*Math.abs(x))
       	   type=4;
       	}


     if ((x<0)&&(y>=0))
       {
       	if (Math.abs(x)<y)
        	  type=1;
        	else
        	  type=6;
       }

     if ((type==1)||(type==4))
        {
         newx=x1;
         newy=CY;
        }

     if ((type==3)||(type==6))
        {
         newx=CX;
         newy=y1;
        }

      if ((type==2)||(type==5))
         {

        var d=0.5*Math.abs(x-y);
        if (type==2)
          {
          	if (Math.abs(CX-x1)>=Math.abs(CY-y1))
          	  {
          	  	newx=CX-d;
          	  	newy=CY-d;
          	  }
          	 else
          	   {
          	   	newx=CX+d;
          	   	newy=CY+d;
          	   }

           }

        else
          {
          	if (Math.abs(CX-x1)>=Math.abs(CY-y1))
          	  {
          	  	newx=CX+d;
          	  	newy=CY+d;
          	  }
          	 else
          	   {
          	   	newx=CX-d;
          	   	newy=CY-d;
          	   }
          }


         }

        xcoord[cur]=newx;
        ycoord[cur]=newy;
        points[i]=putPoint(newx,newy);

        if (start>1)
        { 
         var XPREV=xcoord[cur-1];
         var YPREV=ycoord[cur-1];

         lines[i-1]=goStraight(XPREV,newx,YPREV,newy);
         canvas.add(lines[i-1],lines[i-1].line1,lines[i-1].line2,points[i]);

         points[i]=joinPoint(points[i],lines[i-1],null);
         if (i>1) {
         	       points[i-1]=joinPoint(points[i-1],lines[i-2],lines[i-1]);
         	       points[i-1].id=i-1;
         	       }
           else points[0]=joinPoint(points[0],null,lines[0]);
         i++;
         cur++;
          }

        else
         {
         if (start==1)
          {
          	var xline=new fabric.Line([0, CY, 700, CY], { stroke:	'rgba(0,0,255,0.3)' } );
          	var yline=new fabric.Line([CX, 0, CX, 700], { stroke:	'rgba(0,255,0,0.3)' } );
          	var zline=new fabric.Line([CX-350, CY+350, CX+350, CY-350], { stroke:	'rgba(255,0,0,0.3)' } );

            xline.set('selectable', false);
          	yline.set('selectable', false);
            zline.set('selectable', false);
            canvas.add(xline, yline, zline, points[i]);

            points[i]=joinPoint(points[i],null,null);

            start++;
            i++;
            cur++;
          }
          else
             start++;
           }

    }


    function DrawLine(event)
    {
    	if (start>1)
    	  {

    	    var CX = event.offsetX==undefined?event.layerX:event.offsetX;
            var CY = event.offsetY==undefined?event.layerY:event.offsetY;
   	        var X=xcoord[cur-1];
   	        var Y=ycoord[cur-1];
            var color='';

            if (Math.abs(CX-X)<Math.abs(CY-Y))
                color='rgba(0,255,0,0.3)';
                else  color='rgba(0,0,255,0.3)';
            if ((Math.abs(Math.abs(CX-X)-Math.abs(CY-Y))<75)&&((CX-X)*(CY-Y)<0))
                     color='rgba(255,0,0,0.3)';
            drawline.set({'x1': CX, 'y1': CY, 'x2': X, 'y2': Y, stroke: color });
            canvas.renderAll();

              	  }


    }

    function StopLine(event)
    {
    	cur=0;
    	start=0;
    	xcoord=[];
    	ycoord=[];

    }

     function Editing ()
     {
      cur=0;

      canvas.defaultCursor='default';
      var n=points.length
      canvas.remove(points[n-1]);
      canvas.remove(points[n-1].line1);
      canvas.remove(points[n-1].line1.line1);
      canvas.remove(points[n-1].line1.line2);
      var text;
      var strokes=new Array();
     
       for (i = 0; i < n-1; i++)
        {
        	points[i].selectable=true;
        	points[i].fill='red';
        	text=new fabric.Text('№ '+points[i].id, {left: points[i].left+10, top: points[i].top, fontSize: 14, fontFamily: 'Century Gothic'});
        	points[i].text=text;
        	points[i].text.selectable=false;
        	canvas.add(points[i].text);

        }
      document.removeEventListener('click', DrawPoint);
      document.removeEventListener('mousemove', DrawLine);
      document.removeEventListener('dblclick', StopLine);

      canvas.renderAll();


     function fix_point (p)
     {

     if (p.line1)
     {
       p.line1.set({ 'x1': p.left, 'y1': p.top });
       if (p.line1.type==1)
         {
         p.line1.line1.set({ 'x1': p.left, 'y1': p.top+3 });
         p.line1.line2.set({ 'x1': p.left, 'y1': p.top-3 });
           }
         else
         {
          p.line1.line1.set({ 'x1': p.left+3, 'y1': p.top });
          p.line1.line2.set({ 'x1': p.left-3, 'y1': p.top });
             }
      }
     if (p.line2)
    {  p.line2.set({ 'x2': p.left, 'y2': p.top });
        if (p.line2.type==1)
         {
         p.line2.line1.set({ 'x2': p.left, 'y2': p.top+3 });
         p.line2.line2.set({ 'x2': p.left, 'y2': p.top-3 });
           }
         else
         {
          p.line2.line1.set({ 'x2': p.left+3, 'y2': p.top });
          p.line2.line2.set({ 'x2': p.left-3, 'y2': p.top });
             }
       }
     return p;
     }



    function reorder(points, id)
    {
      
       points[id].fill='green';
       var x2;
       var y2;
       var m;
       var delta;
     	for (var k=id; k<points.length-2; k++)
    	{
    	 points[k+1].fill='yellow';
    	 if (points[k].line2)
    	  {
    	  	if (points[k].line2.type==1)
    	  	 {	if (points[k+1].top!=points[k].top)
    	  	 	   {x2=points[k+1].left;
    	  	 	    y2=points[k].top;
    	  	 	     }
    	  	 	 else
    	  	 	 {  delta=points[k].left-points[k].x;
    	  	 	 	 	x2=points[k+1].left+delta;
    	  	 	 	 	y2=points[k+1].top;

    	  	 	 }

              }
    	    if (points[k].line2.type==2)
    	    {
    	    
    	    	if (points[k+1].left!=points[k].left)
    	  	 	   {x2=points[k].left;
    	  	 	    y2=points[k+1].top;
    	  	 	     }
    	  	 	 else
    	  	 	 { 	delta=points[k].top-points[k].y;
    	  	 	 	 	x2=points[k+1].left;
    	  	 	 	 	y2=points[k+1].top+delta;

    	  	 	 }
    	  	 }
             if (points[k].line2.type==3)
              {
              if ((points[k].line1)&&(points[k].line1.type==1))
              	  {
              	  	delta=points[k].left-points[k].x;
              	  	x2=points[k+1].left+delta;
              	  	y2=points[k+1].top;

              	  }

                if ((points[k].line1)&&(points[k].line1.type==2))
              	  {
              	  	delta=points[k].top-points[k].y;
              	  	x2=points[k+1].left;
              	  	y2=points[k+1].top+delta;

              	  }

              }

          
           if (x2<0) x2=0;
           if (y2<0) y2=0;
           if (x2>500) x2=500;
           if (y2>500) y2=500;
           points[k+1].left=x2;
           points[k+1].top=y2;
           points[k].setCoords();
           canvas.renderAll();

    	  }

    	}


        for (var k=id; k<points.length-1; k++)
        {
         points[k].x=points[k].left;
         points[k].y=points[k].top;
         points[k].text.left=points[k].left+10;
         points[k].text.top=points[k].top;
         points[k]=fix_point(points[k]);
        
        }
      return points;
    }


    canvas.on('object:moving', function(e) {
    var p = e.target;
    var x2;
    var y2;
    var type;


    if (p.line1) type=p.line1.type;
    else type=p.line2.type;

    if (type==1)
      {
      	x2=p.left;
      	y2=p.y;
      }
    if (type==2)
      {
      	x2=p.x;
      	y2=p.top;
      }
    if (type==3)
      {
       	var delta=Math.sqrt((p.top-p.y)*(p.top-p.y)+(p.left-p.x)*(p.left-p.x));
       	if (p.left>p.x)
       	x2=p.x+delta;
       	 else x2=p.x-delta;
       	if (p.top<p.y)
          	y2=p.y-delta;
          	else y2=p.y+delta;
       }

     p.left=x2;
     p.top=y2;
     p=fix_point(p);
     points=reorder(points,p.id);

    });



     canvas.renderAll();

     }

     function Drawing ()
     {

     canvas.defaultCursor='crosshair';
     document.addEventListener('click', DrawPoint, false);
     document.addEventListener('mousemove', DrawLine, false);
     document.addEventListener('dblclick', StopLine, false);


       }
<script src="http://www.fabricjs.com/lib/fabric.js"></script>
  
<div style="display: block; max-width: 100%; height: 100%; overflow: hidden; padding: 40px; background-color: #808080; color: #FFF">
      Please, click DRAW to put some points. Doubleclick - stop drawing. Then click EDIT <br><br>
   <div style="display: block; width: 700px; height: 50px; margin: 0 auto">
      <button id="draw">Draw</button>
      <button id="edit">Edit</button>
      
   </div>

   
    <div style="display: block; width: 500px; height: 500px; margin: 0 auto; background-color: #FFF">
     <canvas id="c" width=500 height=500>