javascript fabric.js 调整画布大小以适应屏幕
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30862356/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
fabric.js resize canvas to fit screen
提问by X4V1
I'm currently developping an application on mobile device (android and iPhone) with ionic and cordova. I would like to edit a picture. I use fabric.js library to do that. Fabric.js converts an image and other items into canvas. Then I add some image on the canvas (stickers) and export it as an image(dataURL). So the size of the canvas is really important because it is a quality factor (export an image based on small canvas will result in poor quality). The canvas size is about 607*1080 pixel (depending on the device that took the photo). I would like to fit it in the screen without losing quality (like explained below I can't resize the canvas without losing quality).
我目前正在使用ionic和cordova在移动设备(android和iPhone)上开发一个应用程序。我想编辑一张图片。我使用fabric.js 库来做到这一点。Fabric.js 将图像和其他项目转换为画布。然后我在画布上添加一些图像(贴纸)并将其导出为图像(dataURL)。所以画布的大小非常重要,因为它是一个质量因素(导出基于小画布的图像会导致质量不佳)。画布大小约为 607*1080 像素(取决于拍摄照片的设备)。我想在不降低质量的情况下将其放入屏幕(如下所述,我无法在不降低质量的情况下调整画布大小)。
I tried 3 ideas but no one has worked.
我尝试了 3 个想法,但没有一个成功。
- Resize canvas: result in quality lost (image exported will have canvas size)
- Adapt viewport: cordova doesn't allow to change the viewport on mobile device. There is a workaround but it will break my design (very small navbar, smaller menu, ...)
- Use CSS3 zoom properties: It works like a charm on desktop but there is an event mapping problem on mobile device (I didn't try on ios but the problem happend on android Webview). Event mapping is not zoomed. The canvas is zoomed out but it is impossible to interact with canvas elements. If a canvas element (sticker) is located at x:100 y:100, when I set zoom property to 0.5, the element will be location at (50,50) and no more at (100,100). Is there any way to correct the event mapping depending on zoom property of the android webview?
- 调整画布大小:导致质量丢失(导出的图像将具有画布大小)
- 调整视口:cordova 不允许更改移动设备上的视口。有一个解决方法,但它会破坏我的设计(非常小的导航栏,较小的菜单,......)
- 使用 CSS3 缩放属性:它在桌面上的作用就像一个魅力,但在移动设备上存在一个事件映射问题(我没有在 ios 上尝试,但问题发生在 android Webview 上)。事件映射未缩放。画布已缩小,但无法与画布元素进行交互。如果画布元素(贴纸)位于 x:100 y:100,当我将缩放属性设置为 0.5 时,该元素将位于 (50,50) 而不再位于 (100,100)。有没有办法根据android webview的缩放属性来纠正事件映射?
I don't know if there are other ways to do that but I'm stucked with this issue for 3 days and I've spend a lot of time on forums, fabricjs doc and google and I don't find any working solution or something else that can help me.
我不知道是否还有其他方法可以做到这一点,但我被这个问题困扰了 3 天,而且我在论坛、fabricjs 文档和谷歌上花了很多时间,但我没有找到任何可行的解决方案或其他可以帮助我的东西。
EDIT: There are 2 working solution below. Check my answer to see how to do that with css.
编辑:下面有 2 个工作解决方案。检查我的答案以了解如何使用 css 做到这一点。
回答by SilentTremor
1. Use css to set your right resolution for canvas:
1. 使用 css 为画布设置正确的分辨率:
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = 800;
canvas.height = 600;
css:
css:
/* media query 1 */
#canvas{
width: 400px;
height: 250px;
}
/* media query 2 */
#canvas{
width: 200px;
height: 120px;
}
pros:
优点:
All the resolution is given by canvas width and height (800/600)
所有分辨率由画布宽度和高度给出(800/600)
cons:
缺点:
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)
非常适合方形画布纵横比(1:1),奇怪纵横比的输出问题,您需要基于 css 高度计算,
original height / original width * new width = new height;
这超出了我的 CSS 联盟......
前段时间阅读fabric.js git问题部分,其中由于缓慢和不正确的对象事务,不建议使用技术(css调整大小),这可能会改变我知道我测试过并且对象重新调整大小不正确(随机彩色像素,交易阴影保留在画布中,换句话说,一团糟)
2. Re-size your canvas to exact dimension (resolution) when you need to submit, and then get the image generated
2.当你需要提交时,重新调整你的画布到精确的尺寸(分辨率),然后生成图像
Just re-size your canvas at window re-size (responsive canvas) and when you need to export to exact dimension you need to re size your canvas to exact pixel resolution, or create another canvas hidden.
只需在窗口重新调整大小(响应式画布)时重新调整画布大小,当您需要导出到精确尺寸时,您需要将画布调整为精确的像素分辨率,或创建另一个隐藏的画布。
this example is for 1:1 ration canvas (you need to apply aspect ratio to canvas and objects inside):
此示例适用于 1:1 比例画布(您需要将纵横比应用于画布和里面的对象):
$(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();
}
});
At submit export canvas data re-size canvas to desired resolution, voila:
在提交导出画布数据时,将画布大小调整为所需的分辨率,瞧:
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();
}
);
It's not a big deal with the rations different then 1:1 you need to compute scale multiplayer for height as well, easy to understand ratio: http://andrew.hedges.name/experiments/aspect_ratio/
与 1:1 不同的配给并不是什么大问题,您还需要计算身高的比例多人游戏,易于理解的比例:http: //andrew.hedges.name/experiments/aspect_ratio/
回答by X4V1
I have found a trick to do that without having to copy the canvas. This solution is really close to css zoom property but events are handle correctly.
我找到了一种无需复制画布即可做到这一点的技巧。此解决方案非常接近 css zoom 属性,但事件处理正确。
This is an example to display the canvas half its size:
这是显示画布一半大小的示例:
-webkit-transform : scale(0.5);
-webkit-transform-origin : 0 0;