2012-02-23 55 views
11

tengo el siguiente que no funciona correctamente:Fabric.js - Dibujar un rectángulo gratuito

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 lógica anterior es de un sistema de dibujo simple rectángulo utilicé sin fabric.js por lo que sabemos que funciona , simplemente no con fabric.js

Parece que las matemáticas están desactivadas o estoy configurando los parámetros incorrectos con los valores de ancho/alto/x/y, ya que cuando dibuja el rectángulo no sigue el cursor correctamente.

Cualquier ayuda es muy apreciada, gracias de antemano :)

+0

No entiendo por qué la tela no tiene un evento como "selección: completado" que pasa a manejar los límites de selección, ya maneja esta lógica internamente. Estaba tratando de lograr lo mismo y terminé agregando este evento al código fuente. – krulik

Respuesta

12

Parece que Fabric.js calcula todo, desde el origen. Entonces, 'Arriba' e 'Izquierda' son un poco engañosos. Consulte el siguiente enlace: Canvas Coordinates Have Offset. Además, he cambiado un poco su código:

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

Gracias por la ayuda, definitivamente me pusieron en la dirección correcta. Modifiqué el código para que la posición superior/izquierda se vuelva a calcular para que siempre permanezca en la primera posición, haga clic para que pueda arrastrar un bonito rectángulo. Algo como: var x = Math.abs (w/2 + x) – jhdevuk

+0

@sirjamm ¿Qué ocurre si arrastra el mouse hacia la izquierda en lugar de hacia la derecha? en esta solución, el rect seguirá creciendo hacia la derecha en lugar de hacia la dirección del mouse – krulik

+0

@sirjamm, debería hacer algo como: Math.abs (w/2 + Math.min (x, mouse.x)) – krulik

0

La respuesta anterior parece estar en desuso. Cambié algunas cosas en el siguiente código para arreglar eso. Y en la función de mousedown agrego el if para detectar el objeto activo para evitar crear un nuevo rectángulo cuando el usuario mueva un objeto seleccionado.

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

Pero cuando uso el zoom, por ejemplo, la xey en el mouse: hacia abajo cambiará la posición –

18

He escrito un ejemplo para ti. Por favor, siga el siguiente enlace:

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

Por favor, ponga su enfoque aquí en lugar de solo proporcionar una referencia externa. Si el recurso externo se ha ido, la respuesta es inútil. –

+0

, pero ¿por qué el objeto no se puede mover incluso después de eliminar la selección: propiedad falsa. –

+1

Si desea que el objeto sea movible, debe agregar rect.setCoords(); en el controlador de eventos "mouse: up" –

0

Aquí es el blog detalle 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>

Cuestiones relacionadas