fabric.js调整画布以适合屏幕 [英] fabric.js resize canvas to fit screen

查看:3135
本文介绍了fabric.js调整画布以适合屏幕的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我试过3个想法,但没有人


  1. 调整画布大小:导致画质损失>
  2. 调整视口:cordova不允许在移动设备上更改视口。有一个解决方法,但它会打破我的设计(非常小的导航栏,更小的菜单,...)

  3. 使用CSS3缩放属性:但在移动设备上有一个事件映射问题(我没有尝试在ios,但问题发生在Android Webview)。事件映射不缩放。画布被缩小,但是不可能与画布元素交互。如果canvas元素(贴纸)位于x:100 y:100,当我将zoom属性设置为0.5时,元素将位于(50,50),而不再位于(100,100)。是否有任何方法根据android webview的缩放属性来更正事件映射?

我不知道是否有其他方法来做,但我被困住了这个问题3天,我花了很多时间在论坛,fabricjs doc和谷歌,我没有找到任何工作的解决方案或其他可以帮助我。 p>

编辑:下面有两个工作解决方案。检查我的答案,看看如何使用css。

解决方案

使用css为canvas设置正确的分辨率:



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

canvas.width = 800;
canvas.height = 600;

css:

 code> / *媒体查询1 * / 
#canvas {
width:400px;
height:250px;
}

/ *媒体查询2 * /
#canvas {
width:200px;
height:120px;
}

优点:



< >

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


cons:


适合正方形画布的长宽比(1:1),输出问题
适用于需要计算css height
based,

 原始高度/原始宽度*新宽度=新高度; 

这是我在css中的联赛...



阅读一段时间以前在fabric.js git问题部分在哪里,技术
(css resize)不推荐,因为慢和不正确的对象
事务,这可以改变我知道我测试和对象是
不正确的重新调整大小(随机彩色像素,交易阴影在画布中保持
,换句话说乱七八糟)




2。当您需要提交时,请重新调整您的画布的大小,以获得生成的图像



只需在窗口大小重新调整画布大小响应画布),当您需要导出到精确的维度时,您需要重新调整画布大小以确保像素分辨率,或创建另一个画布隐藏。



此示例是1 :1个比例画布(您需要将长宽比应用于画布和其中的对象):

  $(window).resize (){
if(canvas.width!= $(。container)。width()){
var scaleMultiplier = $(。
var objects = canvas.getObjects();
for(var i in objects){
objects [i] .scaleX = objects [i] .scaleX * scaleMultiplier;
[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();
}
});

在提交时,将画布数据重新调整大小到所需的分辨率,瞧:

  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/


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).

I tried 3 ideas but no one has worked.

  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. 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). 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?

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.

EDIT: There are 2 working solution below. Check my answer to see how to do that with css.

解决方案

1. Use css to set your right resolution for 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; 
    }

pros:

All the resolution is given by canvas width and height (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)

2. Re-size your canvas to exact dimension (resolution) when you need to submit, and then get the image generated

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):

$(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/

这篇关于fabric.js调整画布以适合屏幕的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆