我一直在使用 fabricjs 来创建绘图工具。有一个大图像作为画布背景和平移功能。用户可以在画布上拖放对象。但是当我们平移画布时,没有选择画布上的对象放置。
要检查问题,请在视口下部拖放圆圈,然后将画布向上平移到一半,并检查放置在画布上的对象不可选择。即使您尝试将对象移动到视口之外,它也将无法选择。
var canvas = new fabric.Canvas('c', {
selection: false
});
canvas.perPixelTargetFind = true;
canvas.targetFindTolerance = 4;
fabric.Image.fromURL('https://image.ibb.co/gFtpp7/8c39a3193e05996911c0d9c1df001a80.jpg', function(img) {
var imgObj = img.set({
left: 0,
top: 0,
});
imgObj.scaleToWidth(canvas.width);
canvas.width = imgObj.width;
canvas.setBackgroundImage(imgObj, canvas.renderAll.bind(canvas));
});
var drawingPointer = {
status: false,
previousObj: false
};
function handleDragStart(e) {
var draggables = document.querySelectorAll('#manholes div.drag-obj');
[].forEach.call(draggables, function(img) {
img.classList.remove('img_dragging');
});
this.classList.add('img_dragging');
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault(); // Necessary. Allows us to drop.
}
e.dataTransfer.dropEffect = 'copy'; // See the section on the DataTransfer object.
// NOTE: comment above refers to the article (see top) -natchiketa
return false;
}
function handleDragEnter(e) {
// this / e.target is the current hover target.
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over'); // this / e.target is previous target element.
}
function handleDrop(e) {
// this / e.target is current target element.
if (e.stopPropagation) {
e.stopPropagation(); // stops the browser from redirecting.
}
var img = document.querySelector('#manholes div.drag-obj.img_dragging');
if (img.getAttribute('draggable') != "true") {
return;
}
img.setAttribute('draggable', false);
var objName = img.getAttribute('data-name');
var circle = new fabric.Circle({
radius: 28,
fill: '#00FFFF',
originX: 'center',
originY: 'center'
});
var pointer = canvas.getPointer(e)
var text = new fabric.Text(objName, {
fontSize: 13,
originX: 'center',
originY: 'center'
});
var group = new fabric.Group([circle, text], {
left: pointer.x - 28,
top: pointer.y - 28,
hasRotatingPoint: false,
dataName: objName,
});
group.setControlsVisibility({
mt: false,
ml: false,
mr: false,
mb: false
});
group.setCoords();
canvas.add(group);
return false;
}
function handleDragEnd(e) {
var draggables = document.querySelectorAll('#manholes div.drag-obj');
[].forEach.call(draggables, function(img) {
img.classList.remove('img_dragging');
});
}
if (Modernizr.draganddrop) {
var draggables = $('#manholes div.drag-obj');
[].forEach.call(draggables, function(img) {
img.addEventListener('dragstart', handleDragStart, false);
img.addEventListener('dragend', handleDragEnd, false);
});
// Bind the event listeners for the canvas
var canvasContainer = document.querySelector('.canvas-container');
canvasContainer.addEventListener('dragenter', handleDragEnter, false);
canvasContainer.addEventListener('dragover', handleDragOver, false);
canvasContainer.addEventListener('dragleave', handleDragLeave, false);
canvasContainer.addEventListener('drop', handleDrop, false);
} else {
// Replace with a fallback to a library solution.
alert("This browser doesn't support the HTML5 Drag and Drop API.");
}
var drawingPointer = {
status: false
};
function handleMouseMovement(o) {
if (drawingPointer.status == 'panning') {
//var delta = new fabric.Point(o.e.movementX, o.e.movementY);
//canvas.relativePan(delta);
var e = o.e,
imgH = this.backgroundImage.height,
imgW = this.backgroundImage.width;
var zoom = canvas.getZoom();
if (zoom < 0.4) {
this.viewportTransform[4] = 200 - imgW * zoom / 2;
this.viewportTransform[5] = 200 - imgH * zoom / 2;
} else {
this.viewportTransform[4] += e.clientX - this.lastPosX;
this.viewportTransform[5] += e.clientY - this.lastPosY;
if (this.viewportTransform[4] >= 0) {
this.viewportTransform[4] = 0;
} else if (this.viewportTransform[4] < canvas.getWidth() - imgW * zoom) {
this.viewportTransform[4] = canvas.getWidth() - imgW * zoom;
}
if (this.viewportTransform[5] >= 0) {
this.viewportTransform[5] = 0;
} else if (this.viewportTransform[5] < canvas.getHeight() - imgH * zoom) {
this.viewportTransform[5] = canvas.getHeight() - imgH * zoom;
}
}
this.requestRenderAll();
this.lastPosX = e.clientX;
this.lastPosY = e.clientY;
}
}
function handleMouseDown(o) {
if (!o.target && !drawingPointer.status) {
this.lastPosX = o.e.clientX;
this.lastPosY = o.e.clientY;
canvas.defaultCursor = 'url("https://image.ibb.co/g94jNS/icon_grab.png") 8 2 ,auto';
drawingPointer.status = 'panning';
}
}
function handleMouseUp(o) {
if (!o.target && drawingPointer.status == 'panning') {
drawingPointer.status = false;
canvas.defaultCursor = 'default';
}
}
canvas.on('mouse:move', handleMouseMovement);
canvas.on('mouse:down', handleMouseDown);
canvas.on('mouse:up', handleMouseUp);
.drag-obj {
width: 56px;
height: 56px;
display: inline;
margin: 5px;
border: 1px solid #CCCCCC;
float: left;
padding: 16px 5px;
text-align: center;
border-radius: 50%;
background-color: #CCCCCC;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<canvas id="c" width="400" height="400" style="border: 1px solid;margin: 10px;"></canvas>
<div class="row">
<div class="col-xs-10 col-xs-offset-1">
<h3>Drag and Drop Objects</h3>
<div class="drag-obj-container" id="manholes">
<div draggable="true" class="drag-obj" data-name="OV01">
OV01
</div>
<div draggable="true" class="drag-obj" data-name="OV02">
OV02
</div>
<div draggable="true" class="drag-obj" data-name="OV03">
OV03
</div>
</div>
</div>
</div>
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>