fabri c. js 3.6 - Ограничивающая рамка для группы не обновляется при изменении сгруппированных объектов - PullRequest
1 голос
/ 05 августа 2020

Проблема, с которой я столкнулся с fabri c. js кажется простой, но я безуспешно искал решение, так что вот я.

Я создаю простую группу для рисования стрелки, состоящей из линейного объекта и повернутого треугольника, помещенного в его конечную точку. Это работает нормально, но когда я динамически обновляю ширину обводки линии и ширину / высоту треугольника, ограничивающая рамка группы не обновляется в соответствии с новыми размерами. Вот изображение результата:

image

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 fabri c. js. По-видимому, был способ обновить sh ограничивающий прямоугольник в более старых версиях, но ни один из кодов не работает с 3.6 - функции больше не существуют. Я пробовал несколько кладжей, чтобы исправить это, включая разгруппировку и перегруппировку объектов, пока безуспешно.

Кто-нибудь знает, как принудительно пересчитать ограничивающую рамку в этой ситуации? Спасибо за любую помощь.

1 Ответ

1 голос
/ 06 августа 2020

В Fabri cJS 3 лучший способ масштабирования группы объектов - это изменить значение scale всей группы:

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

I Предположим, что иногда требуется масштабировать только некоторые объекты внутри группы или масштабировать их с другой пропорцией. Я думаю, исторически было решено, что эту тяжелую операцию должен запускать разработчик. Для этого есть метод 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...