javascript - example - fabricjs events
Pan y zoom Fabricjs (5)
¿Cómo puedo desplazarme y hacer zoom usando fabricjs? He intentado utilizar los métodos zoomToPoint y setZoom, pero no funcionan para la panorámica. Una vez que empiezo a usar diferentes puntos de acercamiento, empiezo a tener problemas.
$(''#zoomIn'').click(function(){
canvas.setZoom(canvas.getZoom() * 1.1 ) ;
}) ;
$(''#zoomOut'').click(function(){
canvas.setZoom(canvas.getZoom() / 1.1 ) ;
}) ;
$(''#goRight'').click(function(){
//Need to implement
}) ;
$(''#goLeft'').click(function(){
//Need to implement
}) ;
Resuelto usando:
relativePan () absolutePan ()
[Actualizar]
$(''#goRight'').click(function(){
var units = 10 ;
var delta = new fabric.Point(units,0) ;
canvas.relativePan(delta) ;
}) ;
$(''#goLeft'').click(function(){
var units = 10 ;
var delta = new fabric.Point(-units,0) ;
canvas.relativePan(delta) ;
}) ;
$(''#goUp'').click(function(){
var units = 10 ;
var delta = new fabric.Point(0,-units) ;
canvas.relativePan(delta) ;
}) ;
$(''#goDown'').click(function(){
var units = 10 ;
var delta = new fabric.Point(0,units) ;
canvas.relativePan(delta) ;
});
Sé que ya está respondida, pero tuve que hacer una panorámica del mouse, así que adapté el violín de la respuesta aceptada para hacerlo. Lo publico aquí para cualquiera que tenga que hacer algo como esto. Esta es solo la idea principal:
var panning = false;
canvas.on(''mouse:up'', function (e) {
panning = false;
});
canvas.on(''mouse:down'', function (e) {
panning = true;
});
canvas.on(''mouse:move'', function (e) {
if (panning && e && e.e) {
var units = 10;
var delta = new fabric.Point(e.e.movementX, e.e.movementY);
canvas.relativePan(delta);
}
});
Aquí está el violín: http://jsfiddle.net/gncabrera/hkee5L6d/5/
Si solo desea desplazar el lienzo en la pantalla y no cambiar la posición de los elementos, puede usar esta solución .
La idea es tener un contenedor de tamaño fijo con CSS de overflow: hidden
que tiene un lienzo gastado dentro de él. la bandeja moverá el lienzo dentro del contenedor para que el usuario vea diferentes áreas del lienzo gastado cada vez.
Aquí está mi solución para el zoom de lienzo (usando la rueda del mouse) y la panorámica (usando las teclas izquierda / arriba / derecha / abajo o la tecla Mayús + ratón hacia abajo + movimiento del mouse).
https://jsfiddle.net/milanhlinak/7s4w0uLy/8/
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="lib/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="lib/fabric.min.js"></script>
</head>
<body>
<canvas id="canvas" style="border: 1px solid #cccccc"></canvas>
<script>
var Direction = {
LEFT: 0,
UP: 1,
RIGHT: 2,
DOWN: 3
};
var zoomLevel = 0;
var zoomLevelMin = 0;
var zoomLevelMax = 3;
var shiftKeyDown = false;
var mouseDownPoint = null;
var canvas = new fabric.Canvas(''canvas'', {
width: 500,
height: 500,
selectionKey: ''ctrlKey''
});
canvas.add(new fabric.Rect({
left: 100,
top: 100,
width: 50,
height: 50,
fill: ''#faa''
}));
canvas.add(new fabric.Rect({
left: 300,
top: 300,
width: 50,
height: 50,
fill: ''#afa''
}));
canvas.on(''mouse:down'', function (options) {
var pointer = canvas.getPointer(options.e, true);
mouseDownPoint = new fabric.Point(pointer.x, pointer.y);
});
canvas.on(''mouse:up'', function (options) {
mouseDownPoint = null;
});
canvas.on(''mouse:move'', function (options) {
if (shiftKeyDown && mouseDownPoint) {
var pointer = canvas.getPointer(options.e, true);
var mouseMovePoint = new fabric.Point(pointer.x, pointer.y);
canvas.relativePan(mouseMovePoint.subtract(mouseDownPoint));
mouseDownPoint = mouseMovePoint;
keepPositionInBounds(canvas);
}
});
fabric.util.addListener(document.body, ''keydown'', function (options) {
if (options.repeat) {
return;
}
var key = options.which || options.keyCode; // key detection
if (key == 16) { // handle Shift key
canvas.defaultCursor = ''move'';
canvas.selection = false;
shiftKeyDown = true;
} else if (key === 37) { // handle Left key
move(Direction.LEFT);
} else if (key === 38) { // handle Up key
move(Direction.UP);
} else if (key === 39) { // handle Right key
move(Direction.RIGHT);
} else if (key === 40) { // handle Down key
move(Direction.DOWN);
}
});
fabric.util.addListener(document.body, ''keyup'', function (options) {
var key = options.which || options.keyCode; // key detection
if (key == 16) { // handle Shift key
canvas.defaultCursor = ''default'';
canvas.selection = true;
shiftKeyDown = false;
}
});
jQuery(''.canvas-container'').on(''mousewheel'', function (options) {
var delta = options.originalEvent.wheelDelta;
if (delta != 0) {
var pointer = canvas.getPointer(options.e, true);
var point = new fabric.Point(pointer.x, pointer.y);
if (delta > 0) {
zoomIn(point);
} else if (delta < 0) {
zoomOut(point);
}
}
});
function move(direction) {
switch (direction) {
case Direction.LEFT:
canvas.relativePan(new fabric.Point(-10 * canvas.getZoom(), 0));
break;
case Direction.UP:
canvas.relativePan(new fabric.Point(0, -10 * canvas.getZoom()));
break;
case Direction.RIGHT:
canvas.relativePan(new fabric.Point(10 * canvas.getZoom(), 0));
break;
case Direction.DOWN:
canvas.relativePan(new fabric.Point(0, 10 * canvas.getZoom()));
break;
}
keepPositionInBounds(canvas);
}
function zoomIn(point) {
if (zoomLevel < zoomLevelMax) {
zoomLevel++;
canvas.zoomToPoint(point, Math.pow(2, zoomLevel));
keepPositionInBounds(canvas);
}
}
function zoomOut(point) {
if (zoomLevel > zoomLevelMin) {
zoomLevel--;
canvas.zoomToPoint(point, Math.pow(2, zoomLevel));
keepPositionInBounds(canvas);
}
}
function keepPositionInBounds() {
var zoom = canvas.getZoom();
var xMin = (2 - zoom) * canvas.getWidth() / 2;
var xMax = zoom * canvas.getWidth() / 2;
var yMin = (2 - zoom) * canvas.getHeight() / 2;
var yMax = zoom * canvas.getHeight() / 2;
var point = new fabric.Point(canvas.getWidth() / 2, canvas.getHeight() / 2);
var center = fabric.util.transformPoint(point, canvas.viewportTransform);
var clampedCenterX = clamp(center.x, xMin, xMax);
var clampedCenterY = clamp(center.y, yMin, yMax);
var diffX = clampedCenterX - center.x;
var diffY = clampedCenterY - center.y;
if (diffX != 0 || diffY != 0) {
canvas.relativePan(new fabric.Point(diffX, diffY));
}
}
function clamp(value, min, max) {
return Math.max(min, Math.min(value, max));
}
</script>
</body>
</html>
Tengo un ejemplo en Github usando fabric.js Toma de panorámica de la lona y zoom: https://sabatinomasala.github.io/fabric-clipping-demo/
El código responsable del comportamiento de paneo es el siguiente: https://github.com/SabatinoMasala/fabric-clipping-demo/blob/master/src/classes/Panning.js
Es una extensión simple en fabric.Canvas.prototype
, que le permite alternar ''modo de arrastre'' en el lienzo de la siguiente manera:
canvas.toggleDragMode(true); // Start panning
canvas.toggleDragMode(false); // Stop panning
Eche un vistazo al siguiente fragmento, la documentación está disponible en todo el código.
const STATE_IDLE = ''idle'';
const STATE_PANNING = ''panning'';
fabric.Canvas.prototype.toggleDragMode = function(dragMode) {
// Remember the previous X and Y coordinates for delta calculations
let lastClientX;
let lastClientY;
// Keep track of the state
let state = STATE_IDLE;
// We''re entering dragmode
if (dragMode) {
// Discard any active object
this.discardActiveObject();
// Set the cursor to ''move''
this.defaultCursor = ''move'';
// Loop over all objects and disable events / selectable. We remember its value in a temp variable stored on each object
this.forEachObject(function(object) {
object.prevEvented = object.evented;
object.prevSelectable = object.selectable;
object.evented = false;
object.selectable = false;
});
// Remove selection ability on the canvas
this.selection = false;
// When MouseUp fires, we set the state to idle
this.on(''mouse:up'', function(e) {
state = STATE_IDLE;
});
// When MouseDown fires, we set the state to panning
this.on(''mouse:down'', (e) => {
state = STATE_PANNING;
lastClientX = e.e.clientX;
lastClientY = e.e.clientY;
});
// When the mouse moves, and we''re panning (mouse down), we continue
this.on(''mouse:move'', (e) => {
if (state === STATE_PANNING && e && e.e) {
// let delta = new fabric.Point(e.e.movementX, e.e.movementY); // No Safari support for movementX and movementY
// For cross-browser compatibility, I had to manually keep track of the delta
// Calculate deltas
let deltaX = 0;
let deltaY = 0;
if (lastClientX) {
deltaX = e.e.clientX - lastClientX;
}
if (lastClientY) {
deltaY = e.e.clientY - lastClientY;
}
// Update the last X and Y values
lastClientX = e.e.clientX;
lastClientY = e.e.clientY;
let delta = new fabric.Point(deltaX, deltaY);
this.relativePan(delta);
this.trigger(''moved'');
}
});
} else {
// When we exit dragmode, we restore the previous values on all objects
this.forEachObject(function(object) {
object.evented = (object.prevEvented !== undefined) ? object.prevEvented : object.evented;
object.selectable = (object.prevSelectable !== undefined) ? object.prevSelectable : object.selectable;
});
// Reset the cursor
this.defaultCursor = ''default'';
// Remove the event listeners
this.off(''mouse:up'');
this.off(''mouse:down'');
this.off(''mouse:move'');
// Restore selection ability on the canvas
this.selection = true;
}
};
// Create the canvas
let canvas = new fabric.Canvas(''fabric'')
canvas.backgroundColor = ''#f1f1f1'';
// Add a couple of rects
let rect = new fabric.Rect({
width: 100,
height: 100,
fill: ''#f00''
});
canvas.add(rect)
rect = new fabric.Rect({
width: 200,
height: 200,
top: 200,
left: 200,
fill: ''#f00''
});
canvas.add(rect)
// Handle dragmode change
let dragMode = false;
$(''#dragmode'').change(_ => {
dragMode = !dragMode;
canvas.toggleDragMode(dragMode);
});
<div>
<label for="dragmode">
Enable panning
<input type="checkbox" id="dragmode" name="dragmode" />
</label>
</div>
<canvas width="300" height="300" id="fabric"></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.15/fabric.min.js"></script>