我只是想加载三个矩形图像,并希望它们彼此水平对齐。我认为在fabric.Image.fromURL
方法中设置left属性可以完成此操作,但树图像会堆叠在一起。即使我包括selectable:true,图像也不可选。我错误地使用fabric.Image.fromURL
吗?
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<!-- Get version 1.1.0 of Fabric.js from CDN -->
<script src="js/fabric.js"></script>
<!-- Get the highest 1.X version of jQuery from CDN. Required for ready() function. -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
$(function () {
var canvas = new fabric.Canvas('canvas', {
backgroundColor: 'black',
selectionColor: 'blue',
selectionLineWidth: 0
// ...
});
debugger;
var tiles = [
"images/Green.png",
"images/Red.png",
"images/Yellow.png"
];
var offset = [
"0",
"200",
"400"
];
debugger;
for (i = 0; i < tiles.length; i++) {
fabric.Image.fromURL(tiles[i], function (img) {
img.scale(1.0).set({
left: offset[i],
top: 0,
selectable:true,
});
canvas.add(img).setActiveObject(img);
});
}
function handleDragStart(e) {
[].forEach.call(images, 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('#images img.img_dragging');
console.log('event: ', e);
var newImage = new fabric.Image(img, {
width: img.width,
height: img.height,
// Set the center of the new object based on the event coordinates relative
// to the canvas container.
left: e.layerX,
top: e.layerY
});
canvas.add(newImage);
return false;
}
function handleDragEnd(e) {
// this/e.target is the source node.
[].forEach.call(images, function (img) {
img.classList.remove('img_dragging');
});
}
// Bind the event listeners for the image elements
var images = document.querySelectorAll('#images img');
[].forEach.call(images, function (img) {
img.addEventListener('dragstart', handleDragStart, false);
img.addEventListener('dragend', handleDragEnd, false);
});
// Bind the event listeners for the canvas
var canvasContainer = document.getElementById('canvas-container');
canvasContainer.addEventListener('dragenter', handleDragEnter, false);
canvasContainer.addEventListener('dragover', handleDragOver, false);
canvasContainer.addEventListener('dragleave', handleDragLeave, false);
canvasContainer.addEventListener('drop', handleDrop, false);
});
</script>
</head>
<body>
<div id="canvas-container">
<canvas id="canvas" width="600" height="200"></canvas>
</div>
<div id="images">
<img draggable="true" src="images/Red.png" width="50" height="50"></img>
<img draggable="true" src="images/Yellow.png" width="50" height="50"></img>
<img draggable="true" src="images/Green.png" width="50" height="50"></img>
</div>
</body>
</html>
答案 0 :(得分:1)
fabric.Image.fromURL
回调与执行for
循环之间存在竞争条件,导致图像无法显示。
如果您在回调中打印i
和offset[i]
:
fabric.Image.fromURL(tiles[i], function (img) {
console.log(i, offset[i]);
...
});
您会注意到所有关闭回调中i
为3
且offset[i]
为undefined
。
这是因为每个回调都保留对i
变量的同一实例的引用,并在执行时使用其最新值。 for循环遍历其循环,每次递增i
,在任何回调执行之前,i
的最终值为3
。当您的回调执行时,他们会尝试将left:
值设置为offset[3]
,这是未定义的,并且结构会回退到0
。
<强>解决方案强>
ES6之前的变量javascript(与大多数语言不同)仅限于声明它们的函数,代码块不会影响范围。
将图像构建逻辑放入其自己的函数中,在每个循环周期中将当前值i
作为参数传递。这会将值放入新范围,并保留该值。
另外,请不要忘记var
前面的i
关键字。否则,您将影响全局命名空间,您需要不惜一切代价避免它。
以下是您的代码应该是什么样的:
for (var i = 0; i < tiles.length; i++) {
buildImage(i);
}
// creates a new scope for the passed in value of i when called:
function buildImage(i) {
fabric.Image.fromURL(tiles[i], function (img) {
img.scale(1.0).set({
left: offset[i],
top: 0,
selectable: true,
});
canvas.add(img).setActiveObject(img);
});
}
最后,您可能需要考虑设置图片的originX
和originY
属性,如下所示:
originX: 'left',
originY: 'top'
默认情况下,在放置图像时,结构将使用图像的中心作为原点,并且图像不会完全显示在画布上。
<强>更新强>
这是fully working example。它取决于结构,需要放在你的js /文件夹中。