我是 Fabric.js 画布库的新手。
我正在尝试使用 Fabric.js 实现对象对齐功能,并且对齐功能现在工作得很好。
但我有一个问题。
当我对齐对象时,它会在两个对象之间绘制引导线。
在本例中,我想在 Fabric.js 中所有其他对象的顶部显示绘制的引导线。
但是效果不太好。
我提供我当前的代码。
const drawGuides = (obj) => {
const targets = canvas.getObjects().filter((o) => o.type !== "line" && o !== obj);
const objLeft = obj.left;
const objRight = obj.left + Math.round(obj.getScaledWidth());
const objCenterX = (objLeft + objRight) / 2.0;
const objTop = obj.top;
const objBottom = obj.top + Math.round(obj.getScaledHeight());
const objCenterY = (objTop + objBottom) / 2.0;
sides.forEach(side => {
let value;
let pointArray = [];
switch (side) {
case "top":
value = objTop;
pointArray = [objLeft, objRight, objCenterX];
break;
case "bottom":
value = objBottom;
pointArray = [objLeft, objRight, objCenterX];
break;
case "centerY":
value = objCenterY;
pointArray = [objLeft, objRight, objCenterX];
break;
case "left":
value = objLeft;
pointArray = [objTop, objBottom, objCenterY];
break;
case "right":
value = objRight;
pointArray = [objTop, objBottom, objCenterY];
break;
case "centerX":
value = objCenterX;
pointArray = [objTop, objBottom, objCenterY];
break;
}
for (const target of targets) {
const targetLeft = target.left;
const targetRight = target.left + Math.round(target.getScaledWidth());
const targetCenterX = (targetLeft + targetRight) / 2.0;
const targetTop = target.top;
const targetBottom = target.top + Math.round(target.getScaledHeight());
const targetCenterY = (targetTop + targetBottom) / 2.0;
switch (side) {
case "top":
case "bottom":
case "centerY":
if (inRange(value, targetTop) || inRange(value, targetBottom) || inRange(value, targetCenterY)) {
pointArray.push(targetLeft);
pointArray.push(targetRight);
pointArray.push(targetCenterX);
}
break;
case "left":
case "right":
case "centerX":
if (inRange(value, targetLeft) || inRange(value, targetRight) || inRange(value, targetCenterX)) {
pointArray.push(targetBottom);
pointArray.push(targetTop);
pointArray.push(targetCenterY);
}
break;
}
}
if (obj.guides[side] instanceof fabric.Line) {
// remove the line
canvas.remove(obj.guides[side]);
delete obj.guides[side];
}
if(obj.guidePoints[side] != null){
obj.guidePoints[side].forEach(mark=>{
canvas.remove(mark);
});
delete obj.guidePoints[side];
}
if(pointArray.length <= 3 ) return;
const sortedPointArray = pointArray.sort((a, b) => a - b);
let ln;
const lineProps = {
evented: true,
stroke: 'red',
selectable: false,
opacity: 1
};
let marks = [];
const markSize = 5;
switch (side) {
case "top":
case "bottom":
case "centerY":
ln = new fabric.Line(
[sortedPointArray[0], value, sortedPointArray[sortedPointArray.length - 1], value],
Object.assign(lineProps, {
stroke: 'blue'
})
);
sortedPointArray.forEach(point => {
marks.push(new fabric.Line([point - markSize, value - markSize, point + markSize, value + markSize],Object.assign(lineProps, { stroke: 'blue' })));
marks.push(new fabric.Line([point - markSize, value + markSize, point + markSize, value - markSize],Object.assign(lineProps, { stroke: 'blue' })));
});
break;
case "left":
case "right":
case "centerX":
ln = new fabric.Line(
[value, sortedPointArray[0], value, sortedPointArray[sortedPointArray.length - 1]],
Object.assign(lineProps, {
stroke: 'blue'
})
);
sortedPointArray.forEach(point => {
marks.push(new fabric.Line([value - markSize, point - markSize, value + markSize, point + markSize],Object.assign(lineProps, { stroke: 'blue' })));
marks.push(new fabric.Line([value - markSize, point + markSize, value + markSize, point - markSize],Object.assign(lineProps, { stroke: 'blue' })));
});
break;
}
obj.guides[side] = ln;
obj.guidePoints[side] = marks;
canvas.add(ln);
marks.forEach(mark => {canvas.add(mark);});
canvas.renderAll();
});
}
我尝试了很多,但引导线显示在所选对象下。
如何在 Fabric.js 中显示包含所选对象的所有对象顶部的引导线?
如上图所示,当我选择绿色矩形对象时,它的辅助线显示在该对象下方,但显示在除自身之外的其他对象的顶部。我总是让所有参考线显示在所有对象的顶部。
哦,我找到了解决方案。原因是默认情况下,所选对象显示在 Fabric.js 中所有其他对象的顶部。
为了解决这个问题,我需要通过设置preserveObjectStacking: true来保留所选对象的顺序。
在这种情况下,所有引导线和标记都显示在所选对象的顶部,因为它们是最后添加的。
它解决了我的问题。