2012-02-23 9 views
11

ho il seguente che non funziona correttamente:Fabric.js - Libera disegnare un rettangolo

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;  

    } 

} 

La logica di cui sopra è da un semplice sistema di disegno rettangolo che ho usato senza fabric.js quindi so che funziona , non solo con fabric.js.

Sembra che la matematica sia disattivata oppure sto impostando i parametri errati con i valori larghezza/altezza/x/y, poiché quando si disegna il rettangolo non segue il cursore correttamente.

Qualsiasi aiuto è molto apprezzato, grazie in anticipo :)

+0

non capisco il motivo per cui il tessuto non ha un evento come "selection: completed" che passa al gestore dei limiti di selezione, gestisce già questa logica internamente. Stavo cercando di ottenere lo stesso e ho finito per aggiungere questo evento al codice sorgente. – krulik

risposta

12

Sembra Fabric.js calcola tutto dall'origine. Quindi, "Top" e "Sinistra" sono un po 'fuorvianti. Controllare il seguente link: Canvas Coordinates Have Offset. Inoltre, ho modificato un po 'del codice:

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

Grazie per l'aiuto, sicuramente mi hai indirizzato nella giusta direzione. Ho modificato il codice in modo che la posizione in alto/a sinistra sia ricalcolata per rimanere sempre nella prima posizione cliccata in modo da poter trascinare un bel rettangolo. Qualcosa come: var x = Math.abs (w/2 + x) – jhdevuk

+0

@sirjamm cosa succede se si trascina il mouse a sinistra anziché a destra? in questa soluzione il rect crescerà ancora a destra anziché nella direzione del mouse – krulik

+0

@sirjamm dovresti fare qualcosa del tipo: Math.abs (w/2 + Math.min (x, mouse.x)) – krulik

0

La risposta sopra sembra essere deprecata. Ho modificato alcune cose sul codice qui sotto per risolverlo. E sulla funzione mouse pubblicitario aggiungo il se per rilevare l'oggetto attivo per evitare di creare un nuovo rettangolo quando l'utente sposta un oggetto selezionato.

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

Ma quando uso lo zoom per esempio xey nel mouse: giù cambierà la posizione –

18

Ho scritto un esempio per voi. Si prega di seguire il link qui sotto:

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

Per favore metti qui il tuo approccio invece di fornire solo un riferimento esterno. Se la risorsa esterna è sparita la risposta è inutile. –

+0

ma perché l'oggetto non è mobile anche dopo aver rimosso la selezione: proprietà false. –

+1

Se vuoi che l'oggetto sia mobile, devi aggiungere rect.setCoords(); nel gestore di eventi "mouse: up" –

0

Ecco il blog dettaglio con 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>