fzz*_*gic 7 javascript fabricjs
编辑:这个问题的范围有所改变.请参阅下面的更新.
我一直在为fabric.js做一些撤销/重做(见小提琴).虽然相当天真,但它大部分都在工作(用于添加/移除/移动或调整单个对象的大小或添加/删除对象组),但不适用于移动或调整对象组.在小提琴中,注意onObjectSelected()函数的控制台输出.
要查看我的意思,请在小提琴画布上绘制一些对象,然后单独移动或调整它们.撤消/重做按预期工作.但是,当选择并移动组时,我看不到如何检索组内对象的更新位置,这意味着撤消/重做无法恢复正确的值.
// onObjectSelected function quoted here to satisfy stackoverflow
// question requirements. See full jsfiddle for context.
for (i in canvas.getObjects()) {
if (canvas.item(i).active === true ) {
console.log(canvas.item(i));
selectedObject.push({
"itemNum" : i,
"svdObject" : fabric.util.object.clone(canvas.item(i))
});
}
}
Run Code Online (Sandbox Code Playgroud)
原因似乎是当作为一组移动或调整大小时,对象位置/比例不会更新.我尝试了各种各样的东西,包括为所有对象运行setCoords(),但这没有帮助.所以如果有人能够发现我做错了什么,或者知道如何解决这个问题,我会很感激.
编辑:为了澄清,这只是一个普通的撤销/重做系统,当用户修改它们时,使用两个数组来存储画布上对象的属性.单击撤消或重做时,属性将应用于画布上的对象.我遇到的问题是,当选择对象组并随后进行修改时,我不知道如何捕获某些属性,例如组中对象的位置,因为组内对象的属性是由于某种原因将对象修改为组时未更新.
更新:我已经了解到,当对象位于用户选择的组中时,对象位置将相对于其所在的组进行记录,而不再是画布,这是有意义的.因此,当处理组中的对象时,将其左/顶部坐标添加到组左/顶部坐标以计算对象相对于画布的坐标.scaleX/Y应乘以group scaleX/Y.
更新:我已经管理过这样做我想要的东西(见新小提琴).我已经了解了fabric的'stateful'标志,stateProperties数组和hasStateChanged方法,这将简化事情.这些文档很少,到目前为止我还没有成功地在这个解决方案中使用它们.使用这些的使用技巧或示例代码将不胜感激.具体来说,我希望能够控制保存哪些属性,因为我不需要保存所有可更改的属性.
onObjectSelected目前看起来像这样:
function onObjectSelected() {
selectedObject = [];
for (i in canvas.getObjects()) {
if (canvas.item(i).active === true) {
// shft-ctrl-j to see item properties on click (chrome)
console.log(canvas.item(i));
// objects can be flipped, but not groups
var groupLeft = 0;
var groupTop = 0;
var groupScaleX = 1;
var groupScaleY = 1;
var groupAngle = 0;
// if it's a group, add group coords also
if (typeof canvas.item(i).group != "undefined") {
var groupLeft = canvas.item(i).group.left;
var groupTop = canvas.item(i).group.top;
var groupScaleX = canvas.item(i).group.scaleX;
var groupScaleY = canvas.item(i).group.scaleY;
var groupAngle = canvas.item(i).group.angle;
}
selectedObject.push({
"itemNum": i,
"left": canvas.item(i).left + groupLeft,
"top": canvas.item(i).top + groupTop,
"scaleX": canvas.item(i).scaleX * groupScaleX,
"scaleY": canvas.item(i).scaleY * groupScaleY,
"angle": canvas.item(i).angle + groupAngle,
"flipX": canvas.item(i).flipX,
"flipY": canvas.item(i).flipY
});
}
}
};
Run Code Online (Sandbox Code Playgroud)
Fabricjs 默认不支持自动缩放或定位。支持这一点的唯一方法是实现您自己的缩放/定位机制。我也尝试了很多东西,但这些线路目前效果最好。
所以基本上,请在你的js中添加这些函数:
function prepareRatio(o){
saveRatio(o);
o.on('modified', function(e){
saveRatio(o);
});
}
function restoreRatio(o){
o.set({
left: o._ratio._left * _cv.width,
top: o._ratio._top * _cv.height,
width: o._ratio._width * _cv.width,
height: o._ratio._height * _cv.height
});
o.setCoords();
}
function saveRatio(obj){
obj._ratio = {
_left: obj.left / _cv.width,
_top: obj.top / _cv.height,
_width: obj.width / _cv.width,
_height: obj.height / _cv.height
};
}
Run Code Online (Sandbox Code Playgroud)
我在这里使用了 2 个自定义变量,其中 _cv 是简化的结构,用于存储目标画布的宽度和高度,并且 _ratio 是每个对象(常量)的比率值。
当您创建对象或调整画布大小时,请明智地使用它们:
fabric.Image.fromURL('xxxx.png', function(img) {
img.set({
// TODO: give object width and height, left and top
});
// save ratio once you create an object
prepareRatio(img);
canvas.add(img);
// OPTIONAL: add your own codes
});
function redraw() {
// TODO: resize your canvas as you want
_cv = {
width: canvas.getWidth(),
height: canvas.getHeight()
};
canvas.forEachObject(function(obj) {
// restore ratio every time when you resize your canvas
restoreRatio(obj);
});
}
window.addEventListener('resize', redraw, false);
Run Code Online (Sandbox Code Playgroud)
这看起来有点长,但实际上非常简单明了的解决方案。我很确定这会立即在您身边发挥作用。希望这可以帮助。
| 归档时间: |
|
| 查看次数: |
2323 次 |
| 最近记录: |