在 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:为啥图像大小调整得这么差?