typescript - 通过 toDataUrl() 渲染图像的 fabric.js 自定义大小
问题描述
我正在现有应用程序中实现白板,该应用程序针对大型触摸屏(NEC 显示器)进行了优化。画布本身位于一个可调整大小的小部件中,这意味着画布的可见部分可以从 400x500 像素到全屏大小不等。但是,只有视口得到调整,画布在背景中始终是全屏大小(并与小部件的左上角对齐),因此在更改小部件的大小时,对象的大小和比例不会失真。这意味着,当我通过 渲染图像时canvas.toDataUrl('png')
,图像总是相同的大小。
现在我们想添加一个功能,画布本身可以滚动,为了方便起见,我们可以说它的尺寸是 3x3 全屏,这意味着如果你需要更多的地方,你可以向左或向右滚动一个屏幕大小。上面或者下面。这并不难,但现在我们来回答我的问题:
是否可以调整渲染功能,以便图像不是从整个画布大小渲染,而是从所有元素的“边界框”的大小渲染。只有选定的元素?这是一张图片来解释:
在这张图片中,黑色方块代表画布的实际大小(以及因此渲染的图像),但我正在寻找一种只渲染红色方块的方法(假设所有元素加上 x 像素的填充)。
一个非常hacky的方法如下,但我不确定是否有更简单的方法:
- 创建一个不可见的“imageRenderCanvas”
- 在渲染时,计算最上角和最左角以及最右和最底角,计算这个“边界框”的大小并在每边添加 2 x 填充并将这个大小设置为 imageRenderCanvas
- 将(选定的)对象放在位置
0+padding / 0+padding
- 将画布渲染为图像
有没有其他方法可以做到这一点?
解决方案
对于任何感兴趣的人,我提出了以下解决方案。这基本上正是我上面所描绘的,但如果有更简单的方法仍然会很好奇。
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();
}
推荐阅读
- sybase - “无法打开缓冲区文件”sybase isql 错误
- xml - 尝试使用 XQuery 对两个 XML 文件执行笛卡尔积
- unity3d - 如何在 Sourcetree 中通过身份验证和提交?
- php - 如何在 laravel 中删除基于 admin_id 的博客?
- google-apps-script - 谷歌应用脚本修改。例外:这些行超出范围
- google-apps-script - GMAIL API 谷歌 AppScript
- python - Converting list of lists with tuple into data frame?
- aws-lambda - AWS“sam deploy”功能超时。堆栈保持“REVIEW_IN_PROGRESS”状态
- git - 在 git 存储库中交换两个文件内容的最简单方法是什么
- c# - 如何在 selenium c# 中创建自定义显式等待函数,传入 WebElements 而不是 By