如何在Fabirc.js中的其他对象(包括所选对象)的顶部显示引导线?

问题描述 投票:0回答:1

我是 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 中显示包含所选对象的所有对象顶部的引导线?

enter image description here

如上图所示,当我选择绿色矩形对象时,它的辅助线显示在该对象下方,但显示在除自身之外的其他对象的顶部。我总是让所有参考线显示在所有对象的顶部。

reactjs canvas fabric
1个回答
0
投票

哦,我找到了解决方案。原因是默认情况下,所选对象显示在 Fabric.js 中所有其他对象的顶部。

为了解决这个问题,我需要通过设置preserveObjectStacking: true来保留所选对象的顺序。

在这种情况下,所有引导线和标记都显示在所选对象的顶部,因为它们是最后添加的。

它解决了我的问题。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.