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

X4V*_*4V1 9 javascript android canvas fabricjs cordova

我目前正在使用离子和cordova在移动设备(Android和iPhone)上开发应用程序.我想编辑一张图片.我使用fabric.js库来做到这一点.Fabric.js将图像和其他项目转换为画布.然后我在画布上添加一些图像(贴纸)并将其导出为图像(dataURL).因此画布的大小非常重要,因为它是一个品质因素(基于小画布导出图像会导致质量差).画布大小约为607*1080像素(取决于拍摄照片的设备).我想把它放在屏幕上而不会失去质量(如下所述,我不能在不损失质量的情况下调整画布大小).

我尝试了3个想法,但没有人有效.

  1. 调整画布大小:导致质量丢失(导出的图像将具有画布大小)
  2. 调整视口:cordova不允许更改移动设备上的视口.有一个解决方法,但它会破坏我的设计(非常小的导航栏,较小的菜单,......)
  3. 使用CSS3缩放属性:它就像桌面上的魅力一样,但在移动设备上有一个事件映射问题(我没有尝试使用ios,但问题发生在Android Webview上).事件映射未缩放.画布已缩小,但无法与画布元素进行交互.如果画布元素(标签)位于x:100 y:100,当我将zoom属性设置为0.5时,元素将位于(50,50)并且不再位于(100,100).有没有办法根据android webview的缩放属性更正事件映射?

我不知道是否有其他方法可以做到这一点,但我已经坚持了3天这个问题,我花了很多时间在论坛,fabricjs doc和谷歌上,我找不到任何有用的解决方案或者其他可以帮助我的东西.

编辑:下面有2个工作解决方案.检查我的答案,看看如何用css做到这一点.

Sil*_*mor 12

1.使用css为画布设置正确的分辨率:

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d");

canvas.width = 800;
canvas.height = 600;
Run Code Online (Sandbox Code Playgroud)

CSS:

/* media query 1 */
    #canvas{
       width: 400px;
       height: 250px; 
    }

/* media query 2 */
#canvas{
       width: 200px;
       height: 120px; 
    }
Run Code Online (Sandbox Code Playgroud)

优点:

所有分辨率均由画布宽度和高度(800/600)给出

缺点:

适合方形画布宽高比(1:1),输出奇怪宽高比的问题,你需要计算你的css高度,

original height / original width * new width = new height;
Run Code Online (Sandbox Code Playgroud)

这是我在CSS中的联盟...

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

2.在需要提交时,将画布重新调整为精确尺寸(分辨率),然后生成图像

只需在窗口重新调整大小(响应画布)时调整画布大小,当需要导出到精确尺寸时,需要将画布调整为精确像素分辨率,或者创建隐藏的另一个画布.

此示例适用于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();
        }
});
Run Code Online (Sandbox Code Playgroud)

在提交导出画布数据时,将画布重新调整为所需的分辨率,瞧:

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();
   }
   );
Run Code Online (Sandbox Code Playgroud)

对于不同于1:1的口粮来说,这不是一个大问题,你需要计算高度的多人游戏,易于理解的比例:http://andrew.hedges.name/experiments/aspect_ratio/


X4V*_*4V1 6

我找到了一个技巧,无需复制画布即可做到这一点。这个解决方案非常接近CSS缩放属性,但事件处理正确。

这是显示画布大小一半的示例:

-webkit-transform : scale(0.5);
-webkit-transform-origin : 0 0;
Run Code Online (Sandbox Code Playgroud)