我试图制作一个构造函数并且遇到一些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并加点。以双击结束。然后按编辑 - 您将看到所有点红色和编号。尝试改变水平或垂直线的某些点。然后看看画布!绿色和红色点可供选择。
在他们的新地方绘制黄点,但可以选择点击他们的旧地方 - 空白空间!但如果我发现那个空的空间 - 我也可以编辑这一点......
我无法理解这是什么? :)))))
我如何解决它?...
答案 0 :(得分:1)
fabricjs中的常见错误是修改对象top
和left
而不使用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>