Fabri cJS Многоугольный объект смещен - PullRequest
0 голосов
/ 25 февраля 2020

Я работаю над интерфейсом, который состоит из нескольких объектов. Я пытаюсь справиться со сценарием, где изменяются размеры холста / интерфейса. Все смещения правильно адресованы, но есть два упрямых объекта, которые отказываются корректно смещаться / отображаться (рис. 1). Перед изменением размера интерфейса все объекты расположены правильно (рисунок 2).

Оба рассматриваемых объекта относятся к типу polygon, тогда как остальные не имеют ничего общего. Это заставляет меня подозревать, что, возможно, для полигонов требуется какой-то дополнительный шаг.

Я проверил все смещения и координаты точек, и все значения правильно назначены, но он все еще смещен, и при выборе он обрезается.

Существуют тысячи строк кода, в которых обрабатываются эти объекты, поэтому невозможно поделиться ими всем. Тем не менее, на основании описания и скриншотов есть что-нибудь очевидное, что выделяется?

Рисунок 1 Figure 1

Рисунок 2 image 2

1 Ответ

0 голосов
/ 25 февраля 2020

Это похоже на проблему отсечения. Похоже, вам нужно пересчитать позицию CanvasRenderingContext, используя метод translate. Я могу поделиться с вами своей функцией отсечения, которая учитывает все эти факторы и над которой я сейчас работаю. Я использую эту функцию обрезки только на изображениях, но я предполагаю, что она должна работать аналогичным образом и на полигонах, на методе http://fabricjs.com/docs/fabric.Polygon.html#clipTo.

 export class ObjectClippingService {
    private _zoomRateService: X.ZoomRateService
    private _window: any

    constructor(zoomRateService: X.ZoomRateService, window: ng.IWindowService) {
        this._zoomRateService = zoomRateService
        this._window = window
    }

    public clipping(ctx, target, isOriginalSize?: boolean) {
        var rectObj
        var left
        var top
        var angle
        var zoomRate = this._zoomRateService.dynamicZoomRate

        if (!!isOriginalSize) {
            zoomRate = 1
        }

        ctx.save()
        ctx.setTransform(1, 0, 0, 1, 0, 0)

        if (this.isGroupImageFrame(target)) {
            rectObj = target.getObjects('rect')[0]
            left = (target.left + rectObj.left + target.width * target.scaleX / 2) * zoomRate
            top = (target.top + rectObj.top + target.height * target.scaleY / 2) * zoomRate
        } else {
            left = target.left * zoomRate
            top = target.top * zoomRate
        }

        angle = target.angle * Math.PI / 180
        console.log('Rotating the clipping by: ' + angle)
        ctx.translate(left, top)
        ctx.rotate(angle)

        this.clipTheImage(target, ctx, zoomRate)
        ctx.restore()
    }

    private isGroupImageFrame(target): boolean {
        return target.fixedItem === 'image' && target.type === 'group' && !target.isFrame && target.newGroupType !== 'circle'
    }

    private rectFrame(target, ctx, zoomRate) {
        var rectObj = !!this.isGroupImageFrame(target) ? target.getObjects("rect")[0] : target

        const clippingRectWidth = rectObj.width * zoomRate * rectObj.scaleX
        const clippingRectHeight = rectObj.height * zoomRate * rectObj.scaleY

        ctx.rect(0, 0, clippingRectWidth, clippingRectHeight)
    }

    private circleFrame(target, ctx, zoomRate) {
        var width = target.width * zoomRate * target.scaleX / 2

        ctx.arc(width, width, width, 0, Math.PI * 2, false)
    }

    private clipTheImage(target, ctx, zoomRate) {
        if (target.newGroupType == 'rect') this.rectFrame(target, ctx, zoomRate)
        if (target.newGroupType === 'circle') this.circleFrame(target, ctx, zoomRate)
    }
}

Я вызываю сервис внутри метода clipTo:

fabric.Image.fromURL(src, function (img: any) {
    img.set({
        ...,
        clipTo: (ctx) => {
            return X._objectClippingService.clipping(ctx, customTarget);
        }
    });
})
...