【问题标题】:fabric.js 3.6 - Bounding box for group doesn't update when grouped objects are changedfabric.js 3.6 - 更改分组对象时,组的边界框不会更新
【发布时间】:2020-11-25 03:10:23
【问题描述】:

fabric.js 遇到的问题似乎很简单,但我一直在寻找解决方案,但没有任何运气,所以我来了。

我创建了一个简单的组来绘制一个箭头,该组由一个线对象和一个放置在其端点的旋转三角形组成。这很好用,但是当我动态更新线条的笔触宽度和三角形的宽度/高度时,组的边界框不会更新以匹配新尺寸。这是结果的图像:

这是一个现场演示。只需拖动滑块更改笔触宽度和三角形大小,您就会看到问题。

let canvas = new fabric.Canvas(document.querySelector('canvas'), {
        backgroundColor: 'white'
    }),
    object,
    lineCoords = [100, 75, 250, 75],
    strokeWidth = parseFloat(document.querySelector('.strokewidth').value),
    createArrow = () => {
        return new fabric.Group(
            [
                new fabric.Line(lineCoords, {
                    left: lineCoords[0],
                    top: lineCoords[1],
                    stroke: 'red',
                    strokeWidth: strokeWidth,
                    strokeLineCap: "round",
                }),
                new fabric.Triangle({
                    width: strokeWidth + 22, 
                    height: strokeWidth + 22, 
                    fill: 'red', 
                    left: lineCoords[0] + 150 + strokeWidth + 22 + ((strokeWidth + 22) / 2) - 14, 
                    top: lineCoords[1] - (Math.floor((strokeWidth + 22) / 2)) + (Math.floor(strokeWidth / 2)),
                    angle: 90,
                })
            ],
            { objectCaching: false }
        )
    }

let arrow = createArrow()
canvas.add(arrow)
canvas.setActiveObject(arrow)
canvas.renderAll()

$('body').on('input change', '.strokewidth', e => {
    if (object = canvas.getActiveObject()) {
        let value = parseFloat(e.target.value),
            [ line, triangle ] = object.getObjects()

        line.set({
            strokeWidth: value
        })
        triangle.set({
            width: value + 22,
            height: value + 22,
            left: line.left + line.width + value + 22 + ((value + 22) / 2) - 14,
            top: line.top - (Math.floor((value + 22) / 2)) + (Math.floor(value / 2))
        })
        canvas.renderAll()
    }
})
body {
    background: #f0f0f0;
    padding: 0;
  margin: 0;
}
canvas {
    border: 1px solid lightgray;
}
div {
    margin: 0.5em 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.0/fabric.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<canvas width="400" height="150"></canvas>
<div>
    <input type="range" class="strokewidth" min="1" max="40" value="5">
</div>

我正在使用 3.6 版的 fabric.js。显然有一种方法可以在旧版本中刷新边界框,但没有任何代码适用于 3.6 - 这些功能不再存在。我已经尝试了几种方法来修复它,包括取消组合和重新组合对象,但到目前为止没有任何运气。

有谁知道在这种情况下如何强制重新计算边界框?感谢您的帮助。

【问题讨论】:

    标签: fabricjs bounding-box


    【解决方案1】:

    在 FabricJS 3 中,缩放一组对象的最佳方法是更改​​整个组的 scale 值:

    group.set({ scaleX: value, scaleY: value })

    我假设有时只需要缩放组内的某些对象或以不同的比例缩放它们。我认为从历史上看,这个繁重的操作需要由开发人员触发。有一种方法可以做到这一点addWithUpdate,并且可以在不向其传递对象的情况下调用它。

    let canvas = new fabric.Canvas(document.querySelector('canvas'), {
            backgroundColor: 'white'
        }),
        object,
        lineCoords = [100, 75, 250, 75],
        strokeWidth = parseFloat(document.querySelector('.strokewidth').value),
        createArrow = () => {
            return new fabric.Group(
                [
                    new fabric.Line(lineCoords, {
                        left: lineCoords[0],
                        top: lineCoords[1],
                        stroke: 'red',
                        strokeWidth: strokeWidth,
                        strokeLineCap: "round",
                    }),
                    new fabric.Triangle({
                        width: strokeWidth + 22, 
                        height: strokeWidth + 22, 
                        fill: 'red', 
                        left: lineCoords[0] + 150 + strokeWidth + 22 + ((strokeWidth + 22) / 2) - 14, 
                        top: lineCoords[1] - (Math.floor((strokeWidth + 22) / 2)) + (Math.floor(strokeWidth / 2)),
                        angle: 90,
                    })
                ],
                { objectCaching: false }
            )
        }
    
    let arrow = createArrow()
    canvas.add(arrow)
    canvas.setActiveObject(arrow)
    canvas.renderAll()
    
    $('body').on('input change', '.strokewidth', e => {
        if (object = canvas.getActiveObject()) {
            let value = parseFloat(e.target.value),
                [ line, triangle ] = object.getObjects()
    
            line.set({
                strokeWidth: value
            })
            triangle.set({
                width: value + 22,
                height: value + 22,
                left: line.left + line.width + value + 22 + ((value + 22) / 2) - 14,
                top: line.top - (Math.floor((value + 22) / 2)) + (Math.floor(value / 2))
            })
            
            canvas.renderAll()
            arrow.addWithUpdate()
        }
    })
    body {
        background: #f0f0f0;
        padding: 0;
      margin: 0;
    }
    canvas {
        border: 1px solid lightgray;
    }
    div {
        margin: 0.5em 10px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.0/fabric.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <canvas width="400" height="150"></canvas>
    <div>
        <input type="range" class="strokewidth" min="1" max="40" value="5">
    </div>

    【讨论】:

    • 谢谢!这完美地工作,并且只需要一行代码。我永远不会猜到在没有任何参数的情况下使用 addWithUpdate() 。你得到复选标记。
    猜你喜欢
    • 1970-01-01
    • 2016-05-27
    • 2018-01-15
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    相关资源
    最近更新 更多