fabric.js通过toDataUrl()自定义渲染图像的大小

时间:2019-07-02 09:53:47

标签: typescript canvas fabricjs

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

现在,我们要添加一个功能,使画布本身可以滚动,为简便起见,其尺寸为3x3全屏,这意味着如果您需要更多位置,则可以向左或向右滚动一个屏幕大小。上还是下。这并不困难,但是现在我们来问我一个问题:

是否可以调整渲染功能,以便不从整个画布大小渲染图像,而是从所有元素的“边界框”大小开始渲染。仅选择元素?这是一张要说明的图片:

enter image description here

在此图片中,黑色正方形代表画布的原始尺寸(因此将渲染图像),但是我正在寻找一种仅渲染红色正方形的方法(可以说所有元素加上x像素的填充) )。

以下是一种真正的黑客方式,但我不确定是否有更简单的方法:

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

还有其他方法吗?

1 个答案:

答案 0 :(得分:0)

对于感兴趣的人,我想出了以下解决方案。这基本上就是我上面所概述的内容,但是如果有更简单的方法,仍然会感到好奇。

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();
}