如何使用 FabricJS 在画布上启用居中缩放?

1. 什么是FabricJS?

FabricJS是一个用于制作交互式Web应用程序的JavaScript图形库,它使开发人员能够在画布上绘制形状、文本和图像,并对这些元素进行缩放、旋转、拖放等操作。它是一个功能强大的库,它提供了许多功能,如事件处理、动画、过滤器等功能,因此非常适合快速构建高质量的Web应用程序。

2. 在画布上启用居中缩放

居中缩放是一种非常方便的功能,当用户缩放画布时,它会自动将焦点移动到画布的中心位置。这对于用户来说非常方便,因为它使得他们可以快速定位画布的任何部分,而不需要手动移动。下面是如何在FabricJS中启用居中缩放。

2.1 需要用到的变量

在我们开始编写代码之前,我们需要定义一些变量。这些变量将帮助我们在实现居中缩放功能时使我们的代码更具可读性。

var canvas = new fabric.Canvas('canvas');

var scaleFactor = 1.2;

var zoom = 1;

var canvasAspectRatio = canvas.width / canvas.height;

var originalCanvasWidth = canvas.width;

var originalCanvasHeight = canvas.height;

canvas:我们要在其上应用缩放的画布。

scaleFactor: 缩放的因子。

zoom:当前缩放级别。

canvasAspectRatio:画布的初始宽高比。

originalCanvasWidth:画布的原始宽度。

originalCanvasHeight:画布的原始高度。

2.2 监听鼠标滚动事件

要启用居中缩放,我们需要监听鼠标滚动事件。这将允许我们在用户滚动鼠标时动态地更改画布的缩放级别。

canvas.on('mouse:wheel', function(opt) {

var delta = opt.e.deltaY;

var zoomOut = delta > 0;

var zoomIn = delta < 0;

if (zoomIn) {

zoom = zoom * scaleFactor;

zoomToPoint(opt, scaleFactor);

} else if (zoomOut) {

zoom = zoom / scaleFactor;

zoomToPoint(opt, 1 / scaleFactor);

}

});

现在我们已经设置了鼠标滚动事件,下一步是在事件处理程序中编写我们的缩放逻辑。

2.3 计算新的画布宽度和高度

我们需要根据缩放级别和画布的宽高比来计算新的画布宽度和高度。

function calculateCanvasDimensions(scale) {

return {

width: originalCanvasWidth * scale,

height: originalCanvasHeight * scale

}

}

直接把画布的宽高赋值给变量是不好的,因为它们会受到缩放因子的影响。所以我们在事件处理程序中,在每次缩放之后计算新的画布宽度和高度。

在缩放之后,我们需要更新画布的宽度和高度,以确保画布的大小正确地反映出当前的缩放级别。

function setCanvasDimensions(scale) {

var dimensions = calculateCanvasDimensions(scale);

canvas.setDimensions(dimensions, {

backstoreOnly: true

});

}

我们可以使用setDimensions方法来更新画布的大小。我们将newDimensions选项对象设置为backstoreOnlytrue ,这将使画布的虚拟大小保持不变。

2.4 缩放到指定点

缩放到指定点是我们实现居中缩放的最重要的部分之一。当我们缩放画布时,我们不仅要缩放画布,还要确保缩放点(鼠标指针位置)在新的画布上保持不变。下面是代码实现。

function zoomToPoint(opt, scale) {

var zoomBefore = zoom;

var point = {

x: opt.e.offsetX,

y: opt.e.offsetY

};

zoom = scale;

var zoomFactor = zoom / zoomBefore;

var canvasOffset = canvas._offset;

var zoomPoint = new fabric.Point(point.x - canvasOffset.left, point.y - canvasOffset.top);

var newZoomPoint = fabric.util.transformPoint(zoomPoint, fabric.util.multiplyTransformMatrices(

canvas.viewportTransform,

fabric.util.invertTransform(canvas.viewportTransform)

));

var dx = point.x - newZoomPoint.x;

var dy = point.y - newZoomPoint.y;

var translatePoint = new fabric.Point(dx, dy);

canvas.relativePan(translatePoint);

setCanvasDimensions(zoom);

}

这里的函数非常复杂,所以我们需要仔细解释它的每个部分。

首先,我们需要记录缩放前的缩放级别和缩放点的位置。

然后,我们更新我们的zoom变量以反映当前的缩放级别。

接下来,我们需要计算缩放点在当前缩放级别下的坐标。这里我们使用了fabricPoint类的transformPoint方法。

现在我们需要计算缩放点和新缩放点之间的距离,并使用它来移动画布中心以确保缩放点仍然位于画布上。

最后但并非最不重要的是我们需要设置新的画布大小来反映我们的新缩放级别。

现在我们已经实现了缩放功能。我们只需要在我们的鼠标滚轮事件处理程序中调用它就行了。

2.5 设置画布初始大小

最后一步是设置画布的初始大小。我们需要让画布从屏幕顶部到底部填满整个屏幕,并且需要正确地处理窗口大小调整事件。

function setCanvasSize() {

var canvasWrapper = document.getElementById('canvas-wrapper');

var width = canvasWrapper.offsetWidth;

var height = canvasWrapper.offsetHeight;

var canvasDimensions = {};

if (height * canvasAspectRatio >= width) {

canvasDimensions.width = width;

canvasDimensions.height = width / canvasAspectRatio;

} else {

canvasDimensions.width = height * canvasAspectRatio;

canvasDimensions.height = height;

}

canvas.setWidth(canvasDimensions.width);

canvas.setHeight(canvasDimensions.height);

zoomToPoint({

e: {

offsetX: canvasDimensions.width / 2,

offsetY: canvasDimensions.height / 2

}

}, 1);

originalCanvasWidth = canvasDimensions.width;

originalCanvasHeight = canvasDimensions.height;

setCanvasDimensions(zoom);

}

setCanvasSize();

window.addEventListener('resize', function() {

setCanvasSize();

});

这段代码还是比较长的,所以我们需要仔细解释它的每个部分。

首先,我们需要获取画布父元素的宽度和高度,并计算新画布的宽度和高度以填充整个屏幕。

接下来,我们需要将画布的宽度和高度设置为新计算的宽度和高度,并将缩放点设置为画布中心。

然后,我们需要更新原始宽度和高度的变量,以便我们可以正确地计算新的画布大小。

最后但并非最不重要的是,我们需要在窗口大小调整事件发生时重新调用setCanvasSize()函数,以便保证画布的大小始终正确。

3. 总结

本文中,我们学习了如何在画布上启用居中缩放。我们首先定义了一些变量,然后监听鼠标滚动事件,计算新的画布宽度和高度,缩放到指定点,然后设置画布初始大小。我们希望这篇文章对您有帮助,并且能够让您更快地使用FabricJS构建高质量的Web应用程序。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。