fabric.js 3.6-更改分组对象后,分组的边界框不会更新 [英] fabric.js 3.6 - Bounding box for group doesn't update when grouped objects are changed

查看:118
本文介绍了fabric.js 3.6-更改分组对象后,分组的边界框不会更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

fabric.js存在的问题似乎很简单,但是我一直在寻找一个没有运气的解决方案,所以我在这里.

The problem I'm having with fabric.js seems simple, but I've been searching for a solution without any luck, so here I am.

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

I create a simple group to draw an arrow, consisting of a line object and a rotated triangle placed at its end point. This works fine, but when I dynamically update the stroke width of the line and the width/height of the triangle, the group's bounding box doesn't update to match the new dimensions. Here's an image of the result:

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

Here's a live demo. Just drag the slider to change the stroke width and triangle size and you'll see the issue.

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中使用-该功能不再存在.我已经尝试了一些解决方法,包括取消组合和重新组合对象,到目前为止还没有任何运气.

I'm using version 3.6 of fabric.js. Apparently there was a way to refresh the bounding box in older versions, but none of the code works with 3.6 - the functions no longer exist. I've tried several kludges to fix it, including ungrouping and regrouping the objects, without any luck so far.

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

Does anyone know how to force a recalculation of the bounding box in this situation? Thanks for any help.

推荐答案

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

In FabricJS 3 the best way to scale a group of objects is to change the scale value of the whole group:

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

我假设有时只需要缩放组中的某些对象或以不同的比例缩放它们.从历史上看,我认为需要由开发人员来触发这种繁重的操作.有一种方法可以做到 addWithUpdate ,并且无需传递反对.

I assume that sometimes it is required to scale only some objects inside a group or scale them with a different proportion. I think historically it was decided that this heavy operation needs to be triggered by the developer. There is a method for doing that addWithUpdate and it can be called without passing an object to it.

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>

这篇关于fabric.js 3.6-更改分组对象后,分组的边界框不会更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆