简体   繁体   English

fabric.js调整画布大小以适应屏幕

[英]fabric.js resize canvas to fit screen

I'm currently developping an application on mobile device (android and iPhone) with ionic and cordova. 我目前正在使用离子和cordova在移动设备(Android和iPhone)上开发应用程序。 I would like to edit a picture. 我想编辑一张图片。 I use fabric.js library to do that. 我使用fabric.js库来做到这一点。 Fabric.js converts an image and other items into canvas. Fabric.js将图像和其他项目转换为画布。 Then I add some image on the canvas (stickers) and export it as an image(dataURL). 然后我在画布上添加一些图像(贴纸)并将其导出为图像(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). 画布大小约为607 * 1080像素(取决于拍摄照片的设备)。 I would like to fit it in the screen without losing quality (like explained below I can't resize the canvas without losing quality). 我想把它放在屏幕上而不会失去质量(如下所述,我不能在不损失质量的情况下调整画布大小)。

I tried 3 ideas but no one has worked. 我尝试了3个想法,但没有人有效。

  1. Resize canvas : result in quality lost (image exported will have canvas size) 调整画布大小 :导致质量丢失(导出的图像将具有画布大小)
  2. Adapt viewport : cordova doesn't allow to change the viewport on mobile device. 调整视口 :cordova不允许更改移动设备上的视口。 There is a workaround but it will break my design (very small navbar, smaller menu, ...) 有一个解决方法,但它会破坏我的设计(非常小的导航栏,较小的菜单,......)
  3. 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). 使用CSS3缩放属性 :它就像桌面上的魅力一样,但在移动设备上有一个事件映射问题(我没有尝试使用ios,但问题发生在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). 如果画布元素(标签)位于x:100 y:100,当我将zoom属性设置为0.5时,元素将位于(50,50)并且不再位于(100,100)。 Is there any way to correct the event mapping depending on zoom property of the android webview? 有没有办法根据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 doc和谷歌上,我找不到任何有用的解决方案或者其他可以帮助我的东西。

EDIT: There are 2 working solution below. 编辑: 下面有2个工作解决方案。 Check my answer to see how to do that with css. 检查我的答案,看看如何用css做到这一点。

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, 适合方形画布宽高比(1:1),输出奇怪宽高比的问题,你需要计算你的css高度,

 original height / original width * new width = new height; 

this is out of my league in css... 这是我在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) 前段时间读过fabric.js git问题部分,其中,由于速度慢和不正确的对象事务,不建议使用技术(css resize),这可能会改变我知道我测试过并且对象重新调整大小(随机彩色像素,交易阴影保留在画布上,换句话说是乱七八糟的)

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/

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM