当前位置: > > > Fabric.js - 画布视图viewport的自适应(内容自动缩放并居中)

Fabric.js - 画布视图viewport的自适应(内容自动缩放并居中)

Fabric.js 开发时,可能会遇到要显示的完整视图尺寸超过了 canvas 大小的情况。比如下面样例,我们生成 20 个方块,每个方块的位置都是随机的。由于 canvas 大小固定,可能就会造成有些方块落在显示区域外,看不到。

碰到这种情况,一方面我们要提供个画布拖拽和缩放的功能,具体可以参考我之前的文章:Fabric.js - 实现鼠标拖动画布、滚轮缩放画布的功能。另一方面最好让整个视图一开始就自动缩放,让 canvas 刚好能显示下全部的内容。

一、让视图自动缩放以适应 Canvas(Canvas 固定大小)

1,实现原理

  • 首先我们遍历所有的对象,获取所有对象左上角坐标的最小值,以及所有对象右下角坐标的最大值。
  • 接着根据上面的值以及 Canvas 的宽高,计算出缩放比例以及平移的距离,并对 Canvas 的视图(Viewport)进行平移和缩放操作。

2,样例代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script src="fabric.js"></script>
    <script src="jquery-3.1.1.js"></script>
    <script>
      var canvas;

      $(function() {
        canvas = new fabric.Canvas('canvas',{backgroundColor: '#D6F8FF'});
        //创建随机的方块
        for(var i=0; i<20; i++){
          var left = (Math.random() - 0.5) * 600;
          var top = (Math.random() - 0.5) * 600;
          var rect = new fabric.Rect({top: top, left: left, width: 70, height: 70, fill: 'orange'});
          canvas.add(rect);
        }

        //缩放移动视图,使其适应Canvas大小
        zoomToFitCanvas();
      });

      //缩放移动视图,使其适应Canvas大小
      function zoomToFitCanvas() {
        //遍历所有对对象,获取最小坐标,最大坐标
        var objects = canvas.getObjects();
        if(objects.length > 0 ){
          var rect = objects[0].getBoundingRect();
          var minX = rect.left;
          var minY = rect.top;
          var maxX = rect.left + rect.width;
          var maxY = rect.top + rect.height;
          for(var i = 1; i<objects.length; i++){
            rect = objects[i].getBoundingRect();
            minX = Math.min(minX, rect.left);
            minY= Math.min(minY, rect.top);
            maxX = Math.max(maxX, rect.left + rect.width);
            maxY= Math.max(maxY, rect.top + rect.height);
          }
        }

        //计算平移坐标
        var panX = (maxX - minX - canvas.width)/2 + minX;
        var panY = (maxY - minY - canvas.height)/2 + minY;
        //开始平移
        canvas.absolutePan({x:panX, y:panY});

        //计算缩放比例
        var zoom = Math.min(canvas.width/(maxX - minX), canvas.height/(maxY - minY));
        //计算缩放中心
        var zoomPoint = new fabric.Point(canvas.width / 2 , canvas.height / 2);
        //开始缩放
        canvas.zoomToPoint(zoomPoint, zoom);
      }
    </script>
  </head>
  <body>
      <canvas id="canvas" width="400" height="250"></canvas>
  </body>
</html>


3,效果图

可以看到 20 个方块完全显示出来,而且这些内容在画布里居中显示。

二、让视图自动缩放以适应屏幕(Canvas 也自适应屏幕大小)

1,实现原理

  • 我们通过监听浏览器窗口的 resize 事件,动态改变 Canvas 的尺寸,从而让 Canvas 大小随着浏览器的大小改变而改变。
  • Canvas 尺寸改变后,其内部视图自动缩放的实现原理同上面是一样的。

2,样例代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      html, body {
        height: 100%;
        width: 100%;
      }
      canvas {
        display: block;
      }
    </style>
    <script src="fabric.js"></script>
    <script src="jquery-3.1.1.js"></script>
    <script>
      var canvas;

      var timer;

      $(function() {
        canvas = new fabric.Canvas('canvas',{backgroundColor: '#D6F8FF'});
        //创建随机的方块
        for(var i=0; i<20; i++){
          var left = (Math.random() - 0.5) * 600;
          var top = (Math.random() - 0.5) * 600;
          var rect = new fabric.Rect({top: top, left: left, width: 70, height: 70, fill: 'orange'});
          canvas.add(rect);
        }

        //添加窗口尺寸改变响应监听
        $(window).resize(resizeCanvas);

        //页面加载后先设置一下canvas大小
        resizeCanvas();
      });

      //窗口尺寸改变响应(修改canvas大小)
      function resizeCanvas() {
        canvas.setWidth($(window).get(0).innerWidth);
        canvas.setHeight($(window).get(0).innerHeight);

        //缩放移动视图,使其适应Canvas大小
        zoomToFitCanvas();
      };

      //缩放移动视图,使其适应Canvas大小
      function zoomToFitCanvas() {
        //先还原缩放比例与位置
        canvas.setZoom(1);
        canvas.absolutePan({x:0, y:0});

        //遍历所有对对象,获取最小坐标,最大坐标
        var objects = canvas.getObjects();
        if(objects.length > 0 ){
          var rect = objects[0].getBoundingRect();
          var minX = rect.left;
          var minY = rect.top;
          var maxX = rect.left + rect.width;
          var maxY = rect.top + rect.height;
          for(var i = 1; i<objects.length; i++){
            rect = objects[i].getBoundingRect();
            minX = Math.min(minX, rect.left);
            minY= Math.min(minY, rect.top);
            maxX = Math.max(maxX, rect.left + rect.width);
            maxY= Math.max(maxY, rect.top + rect.height);
          }
        }

        //计算平移坐标
        var panX = (maxX - minX - canvas.width)/2 + minX;
        var panY = (maxY - minY - canvas.height)/2 + minY;
        //开始平移
        canvas.absolutePan({x:panX, y:panY});

        //计算缩放比例
        var zoom = Math.min(canvas.width/(maxX - minX), canvas.height/(maxY - minY));
        //计算缩放中心
        var zoomPoint = new fabric.Point(canvas.width / 2 , canvas.height / 2);
        //开始缩放
        canvas.zoomToPoint(zoomPoint, zoom);
      }
    </script>
  </head>
  <body>
      <canvas id="canvas" width="400" height="250"></canvas>
  </body>
</html>


3,效果图

  • 不管我们如何改变浏览器大小,Canvas 始终占满整个屏幕。
  • 同时随着 Canvas 的改变,内部视图也会随之缩放并居中,让方块都能全部显示出来。
评论0