【问题标题】:fabric.js custom size of rendered image via toDataUrl()通过 toDataUrl() 渲染图像的 fabric.js 自定义大小
【发布时间】:2019-11-12 22:39:58
【问题描述】:

我正在现有应用程序中实现一个白板,该应用程序针对大型触摸屏(NEC 显示器)进行了优化。画布本身位于一个可调整大小的小部件中,这意味着画布的可见部分可以从 400x500 像素到全屏大小不等。但是,只有视口得到调整,画布在背景中始终是全屏大小(并与小部件的左上角对齐),因此在更改小部件的大小时,对象的大小和比例不会失真。这意味着,当我通过canvas.toDataUrl('png') 渲染图像时,图像始终是相同的大小。

现在我们想添加一个功能,画布本身可以滚动,为了方便起见,我们可以说它的尺寸是 3x3 全屏,这意味着如果你需要更多的地方,你可以向左或向右滚动一个屏幕大小。上面或者下面。这并不难,但现在我们来回答我的问题:

是否可以调整渲染功能,使图像不是从整个画布大小渲染,而是从所有元素的“边界框”的大小渲染。只有选定的元素?这是一张图片来解释:

在这张图片中,黑色方块代表画布的实际大小(以及因此渲染的图像),但我正在寻找一种仅渲染红色方块的方法(假设所有元素加上 x 像素的填充)。

下面是一个非常老套的方法,但我不确定是否有更简单的方法:

  1. 创建一个不可见的“imageRenderCanvas”
  2. 在渲染时,计算最左上角和最右下角,计算这个“边界框”的大小 并在每边添加 2 x 填充并将此大小设置为 imageRenderCanvas
  3. 将(选定的)对象放在位置0+padding / 0+padding
  4. 将画布渲染为图像

还有其他方法吗?

【问题讨论】:

    标签: typescript canvas fabricjs


    【解决方案1】:

    对于任何感兴趣的人,我想出了以下解决方案。这基本上正是我上面所描绘的,但如果有更简单的方法仍然会很好奇。

    renderSelection() {
        const selectedObject = fabric.util.object.clone(this.canvas.getActiveObject());
        const defaultPadding = 100;
        this.dynamicCanvas = new fabric.Canvas('#dynamicCanvas', {
            preserveObjectStacking: true
        });
    
        if ( selectedObject.type !== 'activeSelection') {
            this.renderSingleSelectionDynamicCanvas(selectedObject, defaultPadding);
        } else {
            this.renderMultiSelectionCanvas(selectedObject, defaultPadding);
        }
    
        const renderedImage = this.dynamicCanvas.toDataURL('image/png');
    }
    
    renderSingleSelectionDynamicCanvas(selectedObject: any, defaultPadding: number) {
        const totalWidth = selectedObject.width * selectedObject.scaleX;
        const totalHeight = selectedObject.height * selectedObject.scaleY;
        this.dynamicCanvas.setWidth(totalWidth + 2 * defaultPadding);
        this.dynamicCanvas.setHeight(totalHeight + 2 * defaultPadding);
        selectedObject.set({
            left: defaultPadding,
            top: defaultPadding
        });
        this.dynamicCanvas.add(selectedObject);
        this.dynamicCanvas.renderAll();
    }
    
    renderMultiSelectionCanvas(multiSelectionObject: any, defaultPadding: number) {
        const clonedObjects: Array<any> = [];
        multiSelectionObject.forEachObject( obj => {
            clonedObjects.push(fabric.util.object.clone(obj));
        });
    
        const group = new fabric.Group(clonedObjects, {
            left: defaultPadding,
            top: defaultPadding,
            width: multiSelectionObject.width,
            height: multiSelectionObject.height,
            originX: multiSelectionObject.originX,
            originY: multiSelectionObject.originY,
            scaleX: multiSelectionObject.scaleX,
            scaleY: multiSelectionObject.scaleY
        });
        const totalWidth = multiSelectionObject.width + 2 * defaultPadding;
        const totalHeight = multiSelectionObject.height + 2 * defaultPadding;
        this.dynamicCanvas.setWidth(totalWidth);
        this.dynamicCanvas.setHeight(totalHeight);
        this.dynamicCanvas.add(group);
        this.dynamicCanvas.renderAll();
    }
    

    【讨论】:

    • 我正在考虑实现 'cropX,cropY' 来实现您想要的,但是您有实现的 jsfiddle 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-07
    • 2012-09-11
    • 2012-10-20
    • 2014-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多