2012-02-23 98 views
11

我有一个不能正常工作的情况如下:Fabric.js - 免费绘制一个矩形

var canvas = new fabric.Canvas('canvas'); 


canvas.observe('mouse:down', function(e) { mousedown(e); }); 
canvas.observe('mouse:move', function(e) { mousemove(e); }); 
canvas.observe('mouse:up', function(e) { mouseup(e); }); 


var started = false; 


var x = 0; 
var y = 0; 


/* Mousedown */ 
function mousedown(e) { 

    var mouse = canvas.getPointer(e.memo.e); 

    started = true; 

    x = mouse.x; 
    y = mouse.y;  

    var square = new fabric.Rect({ 

     width: 1, 
     height: 1, 
     left: mouse.x, 
     top: mouse.y, 
     fill: '#000' 

    }); 


    canvas.add(square); 
    canvas.renderAll(); 
    canvas.setActiveObject(square); 

} 


/* Mousemove */ 
function mousemove(e) { 

    if(!started) { 

     return false; 

    } 

    var mouse = canvas.getPointer(e.memo.e); 

    var x = Math.min(mouse.x, x), 
    y = Math.min(mouse.y, y), 
    w = Math.abs(mouse.x - x), 
    h = Math.abs(mouse.y - y); 

    if (!w || !h) { 

     return false; 

    } 

    var square = canvas.getActiveObject(); 

    square.set('top', y).set('left', x).set('width', w).set('height', h); 

    canvas.renderAll(); 

} 


/* Mouseup */ 
function mouseup(e) { 

    if(started) { 

     started = false;  

    } 

} 

以上的逻辑是我没有fabric.js用一个简单的矩形绘图系统,所以我知道它的工作原理,而不是fabric.js。

看来数学关闭或我与宽度/高度设置不正确的PARAMS/x/y值,当您绘制矩形不正确跟随光标为。

任何帮助非常感谢,谢谢提前:)

+0

我不明白为什么面料没有像“选择:完成”这样的事件传递给处理选择范围,它已经在内部处理这个逻辑。我试图达到相同的目的,并最终将此事件添加到源代码。 – krulik 2012-03-10 09:02:22

回答

12

貌似Fabric.js计算一切从原点。所以,'顶部'和'左'有点误导。检查以下链接:Canvas Coordinates Have Offset。此外,我已更改了一些代码:

var canvas = new fabric.Canvas('canvas'); 
canvas.observe('mouse:down', function(e) { mousedown(e); }); 
canvas.observe('mouse:move', function(e) { mousemove(e); }); 
canvas.observe('mouse:up', function(e) { mouseup(e); }); 

var started = false; 
var x = 0; 
var y = 0; 

/* Mousedown */ 
function mousedown(e) { 
    var mouse = canvas.getPointer(e.memo.e); 
    started = true; 
    x = mouse.x; 
    y = mouse.y; 

    var square = new fabric.Rect({ 
     width: 0, 
     height: 0, 
     left: x, 
     top: y, 
     fill: '#000' 
    }); 

    canvas.add(square); 
    canvas.renderAll(); 
    canvas.setActiveObject(square); 

} 


/* Mousemove */ 
function mousemove(e) { 
    if(!started) { 
     return false; 
    } 

    var mouse = canvas.getPointer(e.memo.e); 

    var w = Math.abs(mouse.x - x), 
    h = Math.abs(mouse.y - y); 

    if (!w || !h) { 
     return false; 
    } 

    var square = canvas.getActiveObject(); 
    square.set('width', w).set('height', h); 
    canvas.renderAll(); 
} 

/* Mouseup */ 
function mouseup(e) { 
    if(started) { 
     started = false; 
    } 

    var square = canvas.getActiveObject(); 

    canvas.add(square); 
    canvas.renderAll(); 
} 
+0

谢谢你的帮助,你明确地把我放在正确的方向。我修改了代码,以便重新计算顶部/左侧位置,始终保持在第一个点击位置,以便您可以拖出一个漂亮的矩形。类似于:var x = Math.abs(w/2 + x) – jhdevuk 2012-02-24 16:54:49

+0

@sirjamm如果将鼠标拖动到左侧而不是右侧,该怎么办?在此解决方案的矩形仍然将增长到右侧,而不是鼠标方向 – krulik 2012-03-10 09:21:43

+0

@sirjamm你应该这样做:Math.abs(W/2 + Math.min(X,mouse.x)) – krulik 2012-03-10 09:30:22

0

上面的答案似乎已被弃用。我在下面的代码中改变了一些东西来解决这个问题。在mousedown函数中,我添加if来检测活动对象,以避免在用户移动选定对象时创建新的矩形。

var canvas = new fabric.Canvas('canvas'); 

canvas.on('mouse:down', function(options) { 
     if(canvas.getActiveObject()){ 
     return false; 
     } 

     started = true; 
     x = options.e.clientX; 
     y = options.e.clientY; 

     var square = new fabric.Rect({ 
      width: 0, 
      height: 0, 
      left: x, 
      top: y, 
      fill: '#000' 
     }); 

     canvas.add(square); 
     canvas.setActiveObject(square); 
    }); 

    canvas.on('mouse:move', function(options) { 
    if(!started) { 
     return false; 
    } 

    var w = Math.abs(options.e.clientX - x), 
    h = Math.abs(options.e.clientY - y); 

    if (!w || !h) { 
     return false; 
    } 

    var square = canvas.getActiveObject(); 
    square.set('width', w).set('height', h); 
    }); 

    canvas.on('mouse:up', function(options) { 
    if(started) { 
     started = false; 
    } 

    var square = canvas.getActiveObject(); 

    canvas.add(square); 
    }); 
+0

但是,当我使用放大例如在鼠标的x和y:向下将改变位置 – 2015-06-16 11:43:52

18

我已经为你写了一个例子。请点击以下链接:

http://jsfiddle.net/a7mad24/aPLq5/

var canvas = new fabric.Canvas('canvas', { selection: false }); 

var rect, isDown, origX, origY; 

canvas.on('mouse:down', function(o){ 
    isDown = true; 
    var pointer = canvas.getPointer(o.e); 
    origX = pointer.x; 
    origY = pointer.y; 
    var pointer = canvas.getPointer(o.e); 
    rect = new fabric.Rect({ 
     left: origX, 
     top: origY, 
     originX: 'left', 
     originY: 'top', 
     width: pointer.x-origX, 
     height: pointer.y-origY, 
     angle: 0, 
     fill: 'rgba(255,0,0,0.5)', 
     transparentCorners: false 
    }); 
    canvas.add(rect); 
}); 

canvas.on('mouse:move', function(o){ 
    if (!isDown) return; 
    var pointer = canvas.getPointer(o.e); 

    if(origX>pointer.x){ 
     rect.set({ left: Math.abs(pointer.x) }); 
    } 
    if(origY>pointer.y){ 
     rect.set({ top: Math.abs(pointer.y) }); 
    } 

    rect.set({ width: Math.abs(origX - pointer.x) }); 
    rect.set({ height: Math.abs(origY - pointer.y) }); 


    canvas.renderAll(); 
}); 

canvas.on('mouse:up', function(o){ 
    isDown = false; 
}); 
+0

请把你的方法在这里,而不是只提供一个外部参考。如果外部资源没有了,答案就没用了。 – 2014-07-24 16:41:07

+0

但是为什么即使在删除选项之后对象仍然不可移动:false属性。 – 2015-09-22 09:02:49

+1

如果你希望对象是可移动的,你应该添加rect.setCoords();在“mouse:up”事件处理程序中 – 2016-07-10 06:35:00

0

下面是详细的博客用的jsfiddle - https://blog.thirdrocktechkno.com/drawing-a-square-or-rectangle-over-html5-canvas-using-fabricjs-f48beeedb4d3

var Rectangle = (function() { 
 
    function Rectangle(canvas) { 
 
     var inst=this; 
 
     this.canvas = canvas; 
 
     this.className= 'Rectangle'; 
 
     this.isDrawing = false; 
 
     this.bindEvents(); 
 
    } 
 

 
\t Rectangle.prototype.bindEvents = function() { 
 
    var inst = this; 
 
    inst.canvas.on('mouse:down', function(o) { 
 
     inst.onMouseDown(o); 
 
    }); 
 
    inst.canvas.on('mouse:move', function(o) { 
 
     inst.onMouseMove(o); 
 
    }); 
 
    inst.canvas.on('mouse:up', function(o) { 
 
     inst.onMouseUp(o); 
 
    }); 
 
    inst.canvas.on('object:moving', function(o) { 
 
     inst.disable(); 
 
    }) 
 
    } 
 
    Rectangle.prototype.onMouseUp = function (o) { 
 
     var inst = this; 
 
     inst.disable(); 
 
    }; 
 

 
    Rectangle.prototype.onMouseMove = function (o) { 
 
     var inst = this; 
 
     
 

 
     if(!inst.isEnable()){ return; } 
 
     
 
     var pointer = inst.canvas.getPointer(o.e); 
 
     var activeObj = inst.canvas.getActiveObject(); 
 

 
     activeObj.stroke= 'red', 
 
     activeObj.strokeWidth= 5; 
 
     activeObj.fill = 'transparent'; 
 

 
     if(origX > pointer.x){ 
 
      activeObj.set({ left: Math.abs(pointer.x) }); 
 
     } 
 
     if(origY > pointer.y){ 
 
      activeObj.set({ top: Math.abs(pointer.y) }); 
 
     } 
 

 
     activeObj.set({ width: Math.abs(origX - pointer.x) }); 
 
     activeObj.set({ height: Math.abs(origY - pointer.y) }); 
 

 
     activeObj.setCoords(); 
 
     inst.canvas.renderAll(); 
 

 
    }; 
 

 
    Rectangle.prototype.onMouseDown = function (o) { 
 
     var inst = this; 
 
     inst.enable(); 
 

 
     var pointer = inst.canvas.getPointer(o.e); 
 
     origX = pointer.x; 
 
     origY = pointer.y; 
 

 
    \t var rect = new fabric.Rect({ 
 
      left: origX, 
 
      top: origY, 
 
      originX: 'left', 
 
      originY: 'top', 
 
      width: pointer.x-origX, 
 
      height: pointer.y-origY, 
 
      angle: 0, 
 
      transparentCorners: false, 
 
      hasBorders: false, 
 
      hasControls: false 
 
     }); 
 

 
    \t inst.canvas.add(rect).setActiveObject(rect); 
 
    }; 
 

 
    Rectangle.prototype.isEnable = function(){ 
 
     return this.isDrawing; 
 
    } 
 

 
    Rectangle.prototype.enable = function(){ 
 
     this.isDrawing = true; 
 
    } 
 

 
    Rectangle.prototype.disable = function(){ 
 
     this.isDrawing = false; 
 
    } 
 

 
    return Rectangle; 
 
}()); 
 

 

 

 
var canvas = new fabric.Canvas('canvas'); 
 
var rect = new Rectangle(canvas);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.17/fabric.min.js"></script> 
 
Please draw rectangle here 
 

 
<div id="canvasContainer"> 
 
    <canvas id="canvas" width="400" height="400" style="border: solid 1px"></canvas> 
 
</div>