在 FabricJS 中调整窗口大小时如何始终将剪切区域居中?

Posted

技术标签:

【中文标题】在 FabricJS 中调整窗口大小时如何始终将剪切区域居中?【英文标题】:How to alway center clipped area while resize window in FabricJS? 【发布时间】:2019-03-06 16:43:10 【问题描述】:

请帮我解决这个问题。 我有一个画布区域总是填满屏幕大小,背景是灰色的。 以及大小为 300 x 300 的矩形剪辑路径 - >如何在调整窗口大小时使此剪辑路径始终显示在画布中心? (并且剪辑路径视图中的所有元素仍然保持它们的相对位置)

实际:

预期:

这是我的问题:https://jsfiddle.net/thobn24h/uqwoy7d3/13/

var canvasObject = document.getElementById("editorCanvas");
  // set canvas equal size with div
  $(canvasObject).width($("#canvasContainer").width());
  $(canvasObject).height($("#canvasContainer").height());
 
 canvas = new fabric.Canvas('editorCanvas', 
    backgroundColor: 'white',
    selectionLineWidth: 2,
    width: $("#canvasContainer").width(),
    height: $("#canvasContainer").height()
  );

  canvas.controlsAboveOverlay = true;

  // Add canvas clip path
  var clipPath = new fabric.Rect( 
      left: 50,
      top: 50,
      width: 300,
      height: 300 );

  canvas.clipPath = clipPath;

  // create a rectangle object
  var rect = new fabric.Rect(
    left: 100,
    top: 100,
    fill: 'red',
    width: 150,
    height: 150
  );

  rect.set(
    transparentCorners: false,
    rotatingPointOffset: 40,
    cornerColor: 'black',
    cornerStrokeColor: 'black',
    borderColor: 'black',
    cornerSize: 12,
    padding: 10,
    cornerStyle: 'circle',
    borderDashArray: [3, 3]
  );

  // "add" rectangle onto canvas
  canvas.add(rect);

  var text = new fabric.Text('hello world',  left: 100, top: 100 );
  canvas.add(text);

  // Tracking resize windows event
  window.addEventListener('resize', resizeCanvas, false);
#canvasContainer 
            width: 100%;
            height: 100vh;
            background-color: gray;
        
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.0/fabric.js"></script>


<div id="canvasContainer">
  <canvas id="editorCanvas"></canvas>
</div>

<script>

  function resizeCanvas() 

    canvas.setDimensions(
    	width: $("#canvasContainer").width(),
    	height: $("#canvasContainer").height()
  	);

	
 </script>

提前谢谢你!

【问题讨论】:

【参考方案1】:

在您的function resizeCanvas 中,您需要相对于宽度移动所有项目。

这里是代码:我确实删除了一些不需要重现此问题的代码。

var canvasObject = document.getElementById("editorCanvas");
$(canvasObject).width($("#canvasContainer").width());
$(canvasObject).height($("#canvasContainer").height());

canvas = new fabric.Canvas('editorCanvas', 
  backgroundColor: 'white',
  selectionLineWidth: 2,
  width: $("#canvasContainer").width(),
  height: $("#canvasContainer").height()
);

canvas.controlsAboveOverlay = true;

function resizeCanvas() 
  var w = $("#canvasContainer").width();
  var h = $("#canvasContainer").height();
  canvas.setDimensions( width: w, height: h );
  
  clipPath.left = w/2 - clipPath.width/2;  
  rect.left = clipPath.left + 50;  
  text.left = clipPath.left + 50;  



// Add canvas clip path
var clipPath = new fabric.Rect(left: 50, top: 50, width: 300, height: 300);
canvas.clipPath = clipPath;

// create a rectangle object
var rect = new fabric.Rect(
  left: 100, top: 100, fill: 'red', width: 150, height: 150
);
canvas.add(rect);

var text = new fabric.Text('hello world', left: 100, top: 100);
canvas.add(text);

// Tracking resize windows event
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas()
#canvasContainer 
  background-color: gray;
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.0/fabric.js"></script>

<div id="canvasContainer">
  <canvas id="editorCanvas"></canvas>
</div>

【讨论】:

感谢 Helder Sepulveda,这是一个很好的解决方案,但我发现在 FabricJs 中有一个 "viewportTransform :Array" [查看画布文档](fabricjs.com/docs/fabric.StaticCanvas.html#viewportTransform) &这个关于在画布中移动所有对象的演示(按下 ALT 并移动鼠标):http://fabricjs.com/fabric-intro-part-5#pan_zoom,但我不确定如何在 Fabric 中使用 viewPort。你能告诉我更多关于 viewPort 或者我们可以在哪里使用 viewportTransform 来解决这个问题吗? 抱歉@ThoBuiNgoc,但我看不到viewportTransform 与您在此问题中要求在调整窗口大小时保持元素居中的关系【参考方案2】:

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

var canvasWidth = 300;
var canvasHeight = 300;
canvas.width = canvasWidth;
canvas.height = canvasHeight;

var redRectWidth = 150;
var redRectHeight = 150;

// Tracking resize windows event
var $window = $(window);
$window.resize(function()
  var windowWidth = $window.width();
  var windowHeight = $window.height();
  
  var redRectLeft = canvasWidth/2 - redRectWidth/2;
  var redRectTop = canvasHeight/2 - redRectHeight/2;
  //clear the canvas to draw again
  ctx.clearRect(0, 0, canvasWidth, canvasHeight);
  ctx.save();
  //draw red square
  ctx.fillStyle = "red";
  ctx.fillRect(redRectLeft,redRectTop,redRectWidth,redRectHeight);
  //write black text
  ctx.fillStyle = "black";
  ctx.textAlign = "center";
  ctx.font="20px Arial";
  ctx.fillText("Hello World",redRectLeft + redRectWidth/2,redRectTop + redRectHeight/2);
  //restore default style of canvas
  ctx.restore();
  
).trigger("resize");
#canvasContainer 
  width: 100%;
  height: 100vh;
  background-color: gray;
  /*this will center the canvas in the middle*/
  display: flex;
  justify-content: center;
  align-items: center;

#editorCanvas
  background-color: white;
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.0/fabric.js"></script>


<div id="canvasContainer">
  <canvas id="editorCanvas"></canvas>
</div>

【讨论】:

嗨 Stakvino,我希望所有元素都与剪辑路径一起移动。您还有其他更好的建议吗(在这种情况下,我有一个正方形和一个文本)?

以上是关于在 FabricJS 中调整窗口大小时如何始终将剪切区域居中?的主要内容,如果未能解决你的问题,请参考以下文章

Fabricjs HTML5 Canvas:为啥图像大小调整得这么差?

Fabric js:使用鼠标调整大小时增加字体大小而不是仅仅缩放

JavaScript:如何调整div.card的大小

使用tkinter.pack()始终使小部件居中

Qt - 拖动标题栏时防止窗口调整大小

在 Tailwind 中调整窗口大小时如何避免 div 混乱?