如何为 Fabric.js 启用响应式设计

Posted

技术标签:

【中文标题】如何为 Fabric.js 启用响应式设计【英文标题】:How to enable responsive design for Fabric.js 【发布时间】:2014-03-22 18:44:50 【问题描述】:

有没有办法让 Fabric.js 画布使用浏览器调整大小以在任何设备上启用相同的结果?我说的是响应式设计。

有人有代码示例吗?

【问题讨论】:

【参考方案1】:

这个jsFiddle 是一个有效的解决方案。它的灵感来自这个 github issue。

这些是必需的:

一个 div 围绕由 fabric 控制的画布。

<div class="fabric-canvas-wrapper">
    <canvas id="theCanvas"></canvas>
</div>

还有一个窗口调整大小处理程序,触发新画布尺寸和缩放的计算和设置。

window.onresize = resizeCanvas() 
    const outerCanvasContainer = document.getElementById('fabric-canvas-wrapper');

    const ratio          = canvas.getWidth() / canvas.getHeight();
    const containerWidth = outerCanvasContainer.clientWidth;
    const scale          = containerWidth / canvas.getWidth();
    const zoom           = canvas.getZoom() * scale;

    canvas.setDimensions(width: containerWidth, height: containerWidth / ratio);
    canvas.setViewportTransform([zoom, 0, 0, zoom, 0, 0]);

就是这样。它似乎工作得很好。如果此解决方案有任何问题,请告诉我。

我在 3.6.2 版本中使用过 fabric.js。

【讨论】:

感谢这个 sn-p。只是,我认为你不需要声明containerHeight(从未使用过) 谢谢@Zooly。解决了这个问题。 这对我有用,但在任何点击事件之后。任何解决方案@robsch? @SarathMohandas 你有什么问题?小提琴对你有用吗? @robsch 这对我来说是有角度的,但是在点击事件之后,布局就会出现。【参考方案2】:

基本上你需要获取设备屏幕的宽度和高度。之后只需在您的 javascript 中相应地调整画布的大小。示例:

var width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
var height = (window.innerHeight > 0) ? window.innerHeight : screen.height;
var canvas = document.getElementById("canvas");
canvas.width = width;
canvas.height = height;

虽然您的屏幕可能具有不同的分辨率,但在这种情况下,我通常会计算您的原始宽度和设备的宽度比,然后根据该值相应地调整宽度和高度。示例:

var originalWidth = 960;  //Example value
var width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
var widthRatio = originalWidth / width;
canvas.width *= widthRatio;
canvas.height *= widthRatio;

这通常适用于我在任何设备上,希望这会有所帮助。

【讨论】:

你的回答听起来很有道理。不幸的是,它在我的示例中不起作用。请使用您的代码和不使用您的代码查看我的 jsfiddles。有:jsfiddle.net/J9mUh/1 没有:jsfiddle.net/gcollect/Nyf5Y/2 我做错了什么? 从我读到的有关 FabricJS 的内容中,您需要通过 setWidth 和 setHeight 方法设置画布宽度和高度。试试看,让我知道它是否有效。 谢谢。现在可以了。画布调整大小。见jsfiddle.net/gcollect/Hx75y/2 无论如何,我的基本问题是,我需要画布的全部内容来表现响应。所有对象都需要根据新窗口设置重新渲染。有任何想法吗?不管怎样,我给你一个 +1 的解决方案 您可以设置画布的 onBeforeScaleRotate 以对其内容进行处理。但是 Joao 回答了您实际提出的问题...如果您想知道其他问题,您应该检查一下并提出一个新问题... 会不会出现您无权访问窗口对象的情况?【参考方案3】:

我知道这已经有一段时间了,但我找到了一种使用缩放功能更简单的方法。

此代码在窗口调整大小完成时触发。它允许我根据新尺寸确定调整画布中所有内容所需的缩放系数。

function rescale_canvas_if_needed()

	var optimal_dimensions = get_optimal_canvas_dimensions();
	var scaleFactor=optimal_dimensions[0]/wpd.canvas_w;
	if(scaleFactor != 1) 
		wpd_editor.canvas.setWidth(optimal_dimensions[0]);
		wpd_editor.canvas.setHeight(optimal_dimensions[1]);
		wpd_editor.canvas.setZoom(scaleFactor);
		wpd_editor.canvas.calcOffset();
		wpd_editor.canvas.renderAll();
  


$( window ).resize(function() 
	clearTimeout(resizeId);
	resizeId = setTimeout(handle_resize, 500);
 );
 
 function handle_resize()
 
	$(".canvas-container").hide();
	rescale_canvas_if_needed();
	$(".canvas-container").show();               
	 
 

【讨论】:

这看起来会很好...但是get_optimal_canvas_dimensions 是做什么的?代码 sn-ps 也不起作用:( 您好,抱歉回复晚了,我刚收到通知。该功能是检查画布显示区域中的可用空间并相应地调整画布本身大小的地雷之一。 [code]function get_optimal_canvas_dimensions() var available_width = $("#wpc-editor-container").outerWidth(); var canvas_w = 0; var canvas_h = 0; if (wpd.canvas_w > available_width) canvas_w = available_width; canvas_h = (canvas_w * wpd.canvas_h) / wpd.canvas_w; 其他 canvas_w = wpd.canvas_w; canvas_h = wpd.canvas_h; 返回 [canvas_w, canvas_h]; [代码] 谢谢!最后我散列了我自己对该函数的实现,但感谢更新:) 请提供完整代码。 get_optimal_canvas_dimensions 有未定义的变量。【参考方案4】:

我认为这是我需要的答案https://***.com/a/29445765/1815624

它看起来如此接近,但经过一些调整后,我得到了我想要的东西

你想要的画布大小应该设置为宽度/高度var optimal_dimensions = [1000,1000];

这还需要进行更多更改来处理高度,因此当用户将手机旋转到横向时,它可能会变得太大而无法在屏幕上看到所有内容 对于这个演示,新编辑的代码的宽度和高度将是 1000 像素

更新:添加了高度和宽度检测以缩放到窗口...

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas"  ></canvas>

    

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.0.0/fabric.min.js"></script>
   <script>
  var canvas = new fabric.Canvas('canvas');
  canvas.add(new fabric.Circle( radius: 30, fill: '#f55', top: 100, left: 100 ));

  canvas.item(0).set(
    borderColor: 'gray',
    cornerColor: 'black',
    cornerSize: 12,
    transparentCorners: true
  );
  canvas.setActiveObject(canvas.item(0));
  canvas.renderAll();

 
function rescale_canvas_if_needed()
    var optimal_dimensions = [400,400];
    var scaleFactorX=window.innerWidth/optimal_dimensions[0];
    var scaleFactorY=window.innerHeight/optimal_dimensions[1];
    if(scaleFactorX <  scaleFactorY && scaleFactorX < 1) 
        canvas.setWidth(optimal_dimensions[0] *scaleFactorX);
        canvas.setHeight(optimal_dimensions[1] *scaleFactorX);
        canvas.setZoom(scaleFactorX);
     else if(scaleFactorX >  scaleFactorY && scaleFactorY < 1)
        canvas.setWidth(optimal_dimensions[0] *scaleFactorY);
        canvas.setHeight(optimal_dimensions[1] *scaleFactorY);
        canvas.setZoom(scaleFactorY);
    else 
        canvas.setWidth(optimal_dimensions[0] );
        canvas.setHeight(optimal_dimensions[1] );
        canvas.setZoom(1);
    

    canvas.calcOffset();
    canvas.renderAll();


 
function handle_resize()
    $(".canvas-container").hide();
    rescale_canvas_if_needed();
    $(".canvas-container").show();               
     

var resizeId = null;
$(function() 
    $(window).resize(function() 
        if(resizeId != null)
        clearTimeout(resizeId);
        resizeId = setTimeout(handle_resize, 500);
     );
    console.log( "ready!" );
    /* auto size it right away... */
    resizeId = setTimeout(handle_resize, 500);
);
    </script>

希望这对某人有所帮助...美好的一天。

【讨论】:

【参考方案5】:

使用 jQuery 根据元素的大小调整画布大小。

window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() 
    canvas.setHeight(jQuery('#image').height());
    canvas.setWidth(jQuery('#image').width());
    canvas.renderAll();

resizeCanvas();

【讨论】:

以上是关于如何为 Fabric.js 启用响应式设计的主要内容,如果未能解决你的问题,请参考以下文章

如何为响应式网页设计准备 Inkscape SVG 文件?

如何为基于 wordpress 自定义主题的网站进行响应式设计?

专访 | 《学习响应式设计》作者Clarissa Peterson:响应式设计并不是万能的

在 Reactjs 中,如何为这个模板设置响应视图?

如何为所有设备制作响应式网站[关闭]

如何为手机创建响应式页脚