fabric.js 调整大小 canvas 以适合屏幕
fabric.js resize canvas to fit screen
我目前正在使用 ionic 和 cordova 在移动设备(android 和 iPhone)上开发应用程序。我想编辑图片。我使用 fabric.js 库来做到这一点。 Fabric.js 将图像和其他项目转换为 canvas。然后我在 canvas(贴纸)上添加一些图像并将其导出为图像(dataURL)。所以 canvas 的大小非常重要,因为它是一个质量因素(导出基于小 canvas 的图像会导致质量不佳)。 canvas 大小约为 607*1080 像素(取决于拍摄照片的设备)。我想在不损失质量的情况下将其放入屏幕(如下所述,我无法在不损失质量的情况下调整 canvas 的大小)。
我尝试了 3 个想法,但没有一个奏效。
- 调整大小 canvas : 导致质量下降(导出的图像将具有 canvas 大小)
- 调整视口:cordova 不允许更改移动设备上的视口。有一个解决方法,但它会破坏我的设计(非常小的导航栏,较小的菜单,...)
- 使用 CSS3 缩放属性 : 它在桌面上的效果很好,但在移动设备上存在事件映射问题(我没有尝试 ios 但问题发生在 android Webview 上)。事件映射未缩放。 canvas 已缩小,但无法与 canvas 元素交互。如果 canvas 元素(贴纸)位于 x:100 y:100,当我将缩放 属性 设置为 0.5 时,该元素将位于 (50,50) 并且没有更多在(100,100)。有什么方法可以根据 android 网络视图的缩放 属性 更正事件映射?
我不知道是否还有其他方法可以做到这一点,但我被这个问题困扰了 3 天,我在论坛、fabricjs 文档和 google 上花了很多时间我找不到任何可行的解决方案或其他可以帮助我的东西。
编辑:下面有 2 个可行的解决方案。检查我的答案,看看如何使用 css.
1。使用 css 为 canvas 设置正确的分辨率:
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = 800;
canvas.height = 600;
css:
/* media query 1 */
#canvas{
width: 400px;
height: 250px;
}
/* media query 2 */
#canvas{
width: 200px;
height: 120px;
}
优点:
All the resolution is given by canvas width and height (800/600)
缺点:
Fit well for square canvases aspect ration (1:1), problems with output
for weird aspect ratios where you need to compute your css height
based,
original height / original width * new width = new height;
this is out of my league in css...
Read some time ago on fabric.js git issues section where, technique
(css resize) isn't recommended due to slowness and incorrect objects
transactions, this may be changed I know I tested and objects were
incorrect re-sized (random colored pixels, transactions shadows remain
in canvas , in other words a mess)
2。当您需要提交时,将您的 canvas 调整为精确尺寸(分辨率),然后生成图像
只需在 window 重新调整大小(响应式 canvas)时重新调整 canvas 的大小,当您需要导出到精确尺寸时,您需要重新调整 [=40] 的大小=] 精确像素分辨率,或创建另一个 canvas 隐藏。
此示例适用于 1:1 比率 canvas(您需要将宽高比应用于 canvas 和内部对象):
$(window).resize(function (){
if (canvas.width != $(".container").width()) {
var scaleMultiplier = $(".container").width() / canvas.width;
var objects = canvas.getObjects();
for (var i in objects) {
objects[i].scaleX = objects[i].scaleX * scaleMultiplier;
objects[i].scaleY = objects[i].scaleY * scaleMultiplier;
objects[i].left = objects[i].left * scaleMultiplier;
objects[i].top = objects[i].top * scaleMultiplier;
objects[i].setCoords();
}
canvas.setWidth(canvas.getWidth() * scaleMultiplier);
canvas.setHeight(canvas.getHeight() * scaleMultiplier);
canvas.renderAll();
canvas.calcOffset();
}
});
在提交导出 canvas 数据大小 canvas 到所需的分辨率,瞧:
function GetCanvasAtResoution(newWidth)
{
if (canvas.width != newWidth) {
var scaleMultiplier = newWidth / canvas.width;
var objects = canvas.getObjects();
for (var i in objects) {
objects[i].scaleX = objects[i].scaleX * scaleMultiplier;
objects[i].scaleY = objects[i].scaleY * scaleMultiplier;
objects[i].left = objects[i].left * scaleMultiplier;
objects[i].top = objects[i].top * scaleMultiplier;
objects[i].setCoords();
}
canvas.setWidth(canvas.getWidth() * scaleMultiplier);
canvas.setHeight(canvas.getHeight() * scaleMultiplier);
canvas.renderAll();
canvas.calcOffset();
}
return canvas.toDataURL();
}
);
与口粮不同没什么大不了的1:1你还需要计算多人游戏的身高比例,容易理解的比例:http://andrew.hedges.name/experiments/aspect_ratio/
我找到了一个无需复制 canvas 即可完成此操作的技巧。此解决方案非常接近 css zoom 属性 但事件处理正确。
这是显示 canvas 一半大小的示例:
-webkit-transform : scale(0.5);
-webkit-transform-origin : 0 0;
我目前正在使用 ionic 和 cordova 在移动设备(android 和 iPhone)上开发应用程序。我想编辑图片。我使用 fabric.js 库来做到这一点。 Fabric.js 将图像和其他项目转换为 canvas。然后我在 canvas(贴纸)上添加一些图像并将其导出为图像(dataURL)。所以 canvas 的大小非常重要,因为它是一个质量因素(导出基于小 canvas 的图像会导致质量不佳)。 canvas 大小约为 607*1080 像素(取决于拍摄照片的设备)。我想在不损失质量的情况下将其放入屏幕(如下所述,我无法在不损失质量的情况下调整 canvas 的大小)。
我尝试了 3 个想法,但没有一个奏效。
- 调整大小 canvas : 导致质量下降(导出的图像将具有 canvas 大小)
- 调整视口:cordova 不允许更改移动设备上的视口。有一个解决方法,但它会破坏我的设计(非常小的导航栏,较小的菜单,...)
- 使用 CSS3 缩放属性 : 它在桌面上的效果很好,但在移动设备上存在事件映射问题(我没有尝试 ios 但问题发生在 android Webview 上)。事件映射未缩放。 canvas 已缩小,但无法与 canvas 元素交互。如果 canvas 元素(贴纸)位于 x:100 y:100,当我将缩放 属性 设置为 0.5 时,该元素将位于 (50,50) 并且没有更多在(100,100)。有什么方法可以根据 android 网络视图的缩放 属性 更正事件映射?
我不知道是否还有其他方法可以做到这一点,但我被这个问题困扰了 3 天,我在论坛、fabricjs 文档和 google 上花了很多时间我找不到任何可行的解决方案或其他可以帮助我的东西。
编辑:下面有 2 个可行的解决方案。检查我的答案,看看如何使用 css.
1。使用 css 为 canvas 设置正确的分辨率:
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = 800;
canvas.height = 600;
css:
/* media query 1 */
#canvas{
width: 400px;
height: 250px;
}
/* media query 2 */
#canvas{
width: 200px;
height: 120px;
}
优点:
All the resolution is given by canvas width and height (800/600)
缺点:
Fit well for square canvases aspect ration (1:1), problems with output for weird aspect ratios where you need to compute your css height based,
original height / original width * new width = new height;
this is out of my league in css...
Read some time ago on fabric.js git issues section where, technique (css resize) isn't recommended due to slowness and incorrect objects transactions, this may be changed I know I tested and objects were incorrect re-sized (random colored pixels, transactions shadows remain in canvas , in other words a mess)
2。当您需要提交时,将您的 canvas 调整为精确尺寸(分辨率),然后生成图像
只需在 window 重新调整大小(响应式 canvas)时重新调整 canvas 的大小,当您需要导出到精确尺寸时,您需要重新调整 [=40] 的大小=] 精确像素分辨率,或创建另一个 canvas 隐藏。
此示例适用于 1:1 比率 canvas(您需要将宽高比应用于 canvas 和内部对象):
$(window).resize(function (){
if (canvas.width != $(".container").width()) {
var scaleMultiplier = $(".container").width() / canvas.width;
var objects = canvas.getObjects();
for (var i in objects) {
objects[i].scaleX = objects[i].scaleX * scaleMultiplier;
objects[i].scaleY = objects[i].scaleY * scaleMultiplier;
objects[i].left = objects[i].left * scaleMultiplier;
objects[i].top = objects[i].top * scaleMultiplier;
objects[i].setCoords();
}
canvas.setWidth(canvas.getWidth() * scaleMultiplier);
canvas.setHeight(canvas.getHeight() * scaleMultiplier);
canvas.renderAll();
canvas.calcOffset();
}
});
在提交导出 canvas 数据大小 canvas 到所需的分辨率,瞧:
function GetCanvasAtResoution(newWidth)
{
if (canvas.width != newWidth) {
var scaleMultiplier = newWidth / canvas.width;
var objects = canvas.getObjects();
for (var i in objects) {
objects[i].scaleX = objects[i].scaleX * scaleMultiplier;
objects[i].scaleY = objects[i].scaleY * scaleMultiplier;
objects[i].left = objects[i].left * scaleMultiplier;
objects[i].top = objects[i].top * scaleMultiplier;
objects[i].setCoords();
}
canvas.setWidth(canvas.getWidth() * scaleMultiplier);
canvas.setHeight(canvas.getHeight() * scaleMultiplier);
canvas.renderAll();
canvas.calcOffset();
}
return canvas.toDataURL();
}
);
与口粮不同没什么大不了的1:1你还需要计算多人游戏的身高比例,容易理解的比例:http://andrew.hedges.name/experiments/aspect_ratio/
我找到了一个无需复制 canvas 即可完成此操作的技巧。此解决方案非常接近 css zoom 属性 但事件处理正确。
这是显示 canvas 一半大小的示例:
-webkit-transform : scale(0.5);
-webkit-transform-origin : 0 0;