假设我在fabric.js画布上选择了多个对象,并且可以使用getActiveGroup获取这组对象。任何人都可以提供如何将组复制并粘贴到新组中的示例,其中:
(a)复制组中的每个对象都保留其与其他复制对象的相对位置
(b)复制的组作为一个整体位于某个指定的x,y位置
(c)在粘贴后,复制的组对象被选为一个组,但如果选择被清除,它们将被视为画布上的单个对象
我尝试过克隆并添加克隆组,如下所示:
canvas.getActiveGroup().clone(function(clone) {
clone.left = 100;
clone.top = 100;
canvas.add(clone);
canvas.deactivateAll();
canvas.setActiveGroup(clone).renderAll();
});
现在运行此代码后,克隆的组对象似乎可以添加,定位和选择,但只要我单击画布清除选择,克隆的组对象就会跳转到画布上的其他位置。此外,克隆的对象不能单独选择,并且选择位置与新对象位置不同步。无论如何我确定我错过了什么,但我不确定是什么。任何帮助表示赞赏。
答案 0 :(得分:1)
您应该尝试canvas.getActiveGroup().forEachObject(function(o)
组类型对象,然后克隆它们。
我通过克隆群组给你jsFiddle。
答案 1 :(得分:1)
有同样的问题,你的回答对我有很多帮助。
这是一个显示如何做的小提琴。
https://jsfiddle.net/Lcdrohk4/1/
canvasWrapper.addEventListener('keydown', function(e) {
//Copy paste function for canvas objects
//If ctrl is pressed, set ctrlDown to true
if (e.keyCode == 17) ctrlDown = true;
//Handle ctrl+c
if (ctrlDown && e.keyCode == 67) {
//reset array with copied objects
copiedObjects = [];
//Get the activeObject and the ActiveGroup
var activeObject = canvas.getActiveObject(),
activeGroup = canvas.getActiveGroup();
//If multiple items are selected the activeGroups will be true
if (activeGroup) {
//get the objects from the activegroup
var objectsInGroup = activeGroup.getObjects();
//Discard the activeGroup
canvas.discardActiveGroup();
//Push all items from the activeGroup into our array
objectsInGroup.forEach(function(object) {
copiedObjects.push(object);
});
} else if (activeObject) { //If one item is selected then acriveObject will be true
copiedObjects.push(activeObject); //push our selected item into the array
}
};
//handle ctrl+v
if (ctrlDown && e.keyCode == 86) {
var count = 0;
//Check if we have only one item we want to copy
if (copiedObjects.length == 1) {
//check if we can handle async cloning
if (fabric.util.getKlass(copiedObjects[0].type).async) {
copiedObjects[0].clone(function(clone) {
//Add our item
pasteOne(clone);
//Select our item
selectAll(1);
});
} else { //Sync cloning
//Add our item
pasteOne(copiedObjects[0].clone());
//Select our item
selectAll(1);
}
//Handle multiple item copying
} else if(copiedObjects.length > 1) {
for (var index = (copiedObjects.length - 1); index >= 0; index--) {
//check if we can handle async cloning
if (fabric.util.getKlass(copiedObjects[index].type).async) {
copiedObjects[index].clone(function(clone) {
//Add our item
pasteOne(clone);
count++;
//if we have added all our items we can now select them
if (count == copiedObjects.length) {
selectAll(copiedObjects.length);
}
});
}else{ //sync cloning
//Add our item
pasteOne(copiedObjects[index].clone());
count++;
//if we have added all our items we can now select them
if (count == copiedObjects.length) {
selectAll(copiedObjects.length);
}
}
}
}
}
//Delete selected items with the delete button
if(e.keyCode == 46){
var activeObject = canvas.getActiveObject(),
activeGroup = canvas.getActiveGroup();
if (activeGroup) {
var objectsInGroup = activeGroup.getObjects();
canvas.discardActiveGroup();
objectsInGroup.forEach(function(object) {
canvas.remove(object);
});
}
else if (activeObject) {
canvas.remove(activeObject);
}
}
}, false);
//Set ctrlDown to false when we release the ctrl key
canvasWrapper.addEventListener('keyup', function(e) {
if (e.keyCode == 17) ctrlDown = false;
});
//Add our item to the canvas
function pasteOne(clone) {
clone.left += 100; //add 100 to the left position
clone.top += 100; //add 100 to the top position
clone.set('canvas', canvas); //Set the canvas attribute to our canvas
clone.setCoords(); //Must call this when we cahnged our coordinates
canvas.add(clone); //Add the item
};
//Select all copied items. numberOfItems is the count of how many items where copied
function selectAll(numberOfItems) {
// Clear the selection
canvas.deactivateAll();
canvas.discardActiveGroup();
//new array for handling the newly pasted objects
var objs = new Array();
//get all objects in the canvas
var canvasObjects = canvas.getObjects();
//counter for keeping track how many items we have in "objs"
var count = 0;
//loop from the end of all items in the canvas
for (var index = (canvasObjects.length - 1); index >= 0; index--) {
//Push the item into objs and set the active state to true
if (count < numberOfItems) objs.push(canvasObjects[index].set('active', true));
count++;
}
//Create new fabric group with the copied objects
var group = new fabric.Group(objs, {
originX: 'center',
originY: 'center'
});
//set the group as the new active group
canvas.setActiveGroup(group.setCoords()).renderAll();
}
答案 2 :(得分:0)
感谢Nistor帮助我入手。我不得不做一些额外的工作来获得我想要的结果。这是我的粘贴功能(请注意,我使用的是Angular,但其他人可以根据需要进行调整)。在调用此函数之前,必须将对象复制到剪贴板数组。
// Handle a paste request
$scope.paste = function() {
// Make sure we have something in the clipboard
if ($scope.shared.clipboard.length == 0) {
return;
}
// Check if we have single or multiple objects on the clipboard
if ($scope.shared.clipboard.length == 1) {
$scope.shared.clipboard[0].clone(function(clone) {
pasteOne(clone);
$scope.select(clone);
});
} else {
var group = new fabric.Group();
for (var index = ($scope.shared.clipboard.length - 1); index >= 0; index--) {
$scope.shared.clipboard[index].clone(function(clone) {
pasteOne(clone);
group.addWithUpdate(clone);
// Clone is async so wait until all group objects are cloned before selecting
if (group.size() == $scope.shared.clipboard.length) {
group.setCoords();
$scope.select(group);
}
});
}
}
};
此函数保留每个粘贴对象的相对偏移量。粘贴位置可以设置为某个任意值:
// Paste a single clone onto the canvas
var pasteOne = function(clone) {
clone.left += $scope.shared.pastePosition.x;
clone.top += $scope.shared.pastePosition.y;
clone.setCoords();
$scope.canvas.add(clone);
};
此代码更新选择。请注意,要选择组中的组和单个对象,我需要为每个对象调用 object.set('active'),true)。 $ scope.isGroup(select)只是检查选择类型是否为“group”。
// Update the selection
$scope.select = function(select) {
// Clear the selection
$scope.canvas.deactivateAll();
$scope.canvas.discardActiveGroup();
// Handle group vs single object selections
if ($scope.isGroup(select)) {
$scope.canvas.setActiveGroup(select);
select.forEachObject(function(object) {
object.set('active', true);
});
} else {
$scope.canvas.setActiveObject(select);
}
// Refresh the canvas
$scope.canvas.renderAll();
}