基于fabricjs搭建canvas画布 - 画布基础操作
画布基础操作
画布平移
fabricjs没有自带的画布平移功能,那我们如何实现呢?首先我们先来整理需求。
正常的平移就是按住鼠标拖动画布但需要注意的是如果画布上存在其他元素,比如我们前面上传的图片,鼠标如果按下时刚好处于这些元素上面我们是否需要依旧进行平移操作?如果这个时候我们需要做一些其他操作呢?换句话说就是鼠标处于画布空白位置时正常进行平移, 但如果处于元素上时则不进行平移操作。
接下来我们来监听鼠标的相关事件:mouse:down``mouse:move``mouse:up,来实现一个基础的元素拖动功能
canvas.on("mouse:down", (opt) => {
// 鼠标按下时触发
if (!opt.target) {
let evt = opt.e;
canvas.isDragging = true; // isDragging 是自定义的,开启移动状态
canvas.lastPosX = evt.clientX; // lastPosX 是自定义的
canvas.lastPosY = evt.clientY; // lastPosY 是自定义的
}
});
canvas.on("mouse:move", (opt) => {
// 鼠标移动时触发
if (canvas.isDragging) {
let evt = opt.e;
let vpt = canvas.viewportTransform; // 聚焦视图的转换
vpt[4] += evt.clientX - canvas.lastPosX;
vpt[5] += evt.clientY - canvas.lastPosY;
canvas.requestRenderAll(); // 重新渲染
canvas.lastPosX = evt.clientX;
canvas.lastPosY = evt.clientY;
}
});
canvas.on("mouse:up", (opt) => {
// 鼠标松开时触发
canvas.setViewportTransform(canvas.viewportTransform); // 设置此画布实例的视口转换
canvas.isDragging = false; // 关闭移动状态
});
画布缩放
缩放fabricjs本身提供了API来实现这个功能,但默认的功能不符合我们的操作习惯。首先他的缩放是以画布左上角为缩放点进行的缩放,同时也不能跟进鼠标的位置自动进行中心点切换。所以我们来进行一下改造。还是先是先梳理一下我们的需求:
- 缩放比例展示在工具栏。同时可以在工具栏手动输入更改
- 缩放默认以画布中心点作为缩放中心点
- 鼠标如果在画布上,缩放就以鼠标的位置作为中心点进行缩放
输入缩放
输入框我们简单使用input的绑定来获取值
<input type="range" :min="zoom.min * 100" :max="zoom.max * 100" v-model="zoomVal"/>
拿到zoomVal之后我们需要把值实时更新到canvas画布中,fabricjs中canvas对象提供了setZoom方法用来设置缩放比例
stage.canvas.setZoom(Number(zoomVal) / 100);
调用后我们发现,画布确实缩放了,但缩放的中心点却是画布的左上角, 这与我们的预期不符, 此时我们希望的默认是以画布中心点进行缩放。
查询发现canvas还有一个相关的apizoomToPoint,我们可以通过设置坐标来达到预期的效果。
const handleZoomChange = (val) => {
if (typeof val === "number") {
zoom.value.val = Number(val.toFixed(2));
// stage.canvas.setZoom(Number(val) / 100); // 左上角为中心点
stage.canvas.zoomToPoint(
{
x: innerWidth / 2,
y: innerHeight / 2,
},
zoom.value.val
); // 画布中心为中心点
}
};
这就实现了画布随着我们输入框输入值变化而变化。接下来我们如何实现在画布上进行缩放呢?同时还需要保持输入框展示的值跟随画布缩放而变化
画布缩放
要实现画布上的缩放, 我们首先需要监听鼠标的滚轮变化情况,为canvas绑定wheel事件- mouse:wheel。事件返回opt会包含fabric提供的一些数据,包括鼠标event数据
canvas.on("mouse:wheel", (opt) => {})
通过event我们可以获取到鼠标的位置信息,基于上面提到的canvas.zoomToPoint来设置缩放。基本流程如下
let zoom = canvas.getZoom(); // 获取画布当前缩放值
// 控制缩放范围在 0.01~20 的区间内
zoom *= 0.999 ** delta;
if (zoom > max) zoom = max;
if (zoom < min) zoom = min;
// 设置画布缩放比例
// 参数1:将画布的所放点设置成鼠标当前位置
// 参数2:传入缩放值
canvas.zoomToPoint(
{
x: opt.e.offsetX, // 鼠标x轴坐标
y: opt.e.offsetY, // 鼠标y轴坐标
},
zoom // 最后要缩放的值
);
这就实现了鼠标在画布上的缩放, 我们只需要把此处的zoom赋值给input的zoomVal就可以直接实现数据的双向展示。