Comment puis-je effectuer un panoramique et un zoom à l'aide de fabricjs? J'ai essayé d'utiliser les méthodes zoomToPoint et setZoom mais elles ne fonctionnent pas en panoramique. Une fois que je commence à utiliser différents points de zoom, je commence à avoir des problèmes.
$('#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
}) ;
Résolu en utilisant:
relativePan () absolutePan ()
[Mettre à jour]
$('#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) ;
});
Je sais que la réponse est déjà faite, mais je devais faire un panoramique avec la souris, alors j’ai adapté le violon de la réponse acceptée pour le faire. Je le poste ici pour quiconque doit faire quelque chose comme ça. C'est juste l'idée principale:
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);
}
});
Voici le violon: http://jsfiddle.net/gncabrera/hkee5L6d/5/
Voici ma solution pour le zoom sur toile (avec la molette de la souris) et le panoramique (avec les touches gauche/haut/droite/bas ou la touche Maj + souris gauche/gauche + déplacement de la souris).
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>
J'ai un exemple sur Github en utilisant fabric.js Panoramique et zoom sur toile: https://sabatinomasala.github.io/fabric-clipping-demo/
Le code responsable du comportement de panoramique est le suivant: https://github.com/SabatinoMasala/fabric-clipping-demo/blob/master/src/classes/Panning.js
C'est une simple extension sur le fabric.Canvas.prototype
, qui vous permet d'activer le mode "glisser" de la manière suivante:
canvas.toggleDragMode(true); // Start panning
canvas.toggleDragMode(false); // Stop panning
Jetez un coup d'œil à l'extrait de code suivant. La documentation est disponible dans le code.
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>
Si vous souhaitez simplement déplacer le canevas à l’affichage sans changer la position des éléments, vous pouvez utiliser cette solution .
L'idée est d'avoir un conteneur de taille fixe avec le css de overflow: hidden
qui contient un canevas étendu. le panoramique déplacera la toile à l'intérieur du conteneur afin que l'utilisateur voie chaque fois différentes zones de la toile utilisée.