2012-02-23 97 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>