jquery 绑定 mousewheel,Fabric 实现滚轮缩放

给 canvas 绑定鼠标滚轮事件,以便滚轮实现画布缩放功能。

Fabric 有一个 canvas 的 mouse:wheel 事件; jquery 也有,这里先用 jquery。

webpack 项目引入 jquery,可以在文件中直接 import

 

不过有个问题就是哪个文件要用,就要在当前文件引入,所以使用一个一劳永逸的办法

在 webpack.config.js 中引入:

 

jquery 有了,下面绑定鼠标滚轮事件,百度了一下都说是绑定 'mousewheel' 事件

这个监听不能加载 canvas 上,而要加在 Fabric 自动生成的上层容器(.upper-canvas)中。

但是项目抛出了错误,可见百度出来的东西也不一定是经过测验的

 

后来看了下 jquery 里的事件 ,发现鼠标滚轮事件是 wheel,不是 mousewheel!

 

接下来在实现缩放方法

通过  event.originalEvent.deltaY 来判断滚轮是向上还是向下

验证之后会有如下代码:

 

抽取变量,做到灵活可配

 

if 判断后调用计算 scale 方法

 

先计算画布缩放尺寸

 

这里会有一个小瑕疵,计算精度的问题:

 

可以 toFixed 解决一下

 

这里抽取了一个  getScaleValue  的方法,用于获取当前缩放值 和 缩放比例,比例用于后续计算尺寸

 

画布计算好后,再进行包含对象的尺寸计算:分别计算缩放以及位置的值

 

逻辑清晰没问题,代码优化一下:

 

贴代码贴代码:

复制代码
// 滚轮监听
$(".upper-canvas").on('wheel', (e) => {
    if (e.originalEvent.deltaY > 0) {
        console.log('上', e.originalEvent.deltaY);
        this.calculateScale(this.canvas, this.scaleStep);
    } else {
        console.log('下', e.originalEvent.deltaY);
        this.calculateScale(this.canvas, -this.scaleStep);
    }
});


    /**
     * 缩放画布
     */
    calculateScale(canvas, num) {
        let scale;
        [ this.currentScale, scale ] = this.getScaleValue(this.currentScale, num);
        console.log(this.currentScale);
        this.canvas.setWidth(this.canvas.getWidth() * scale);
        this.canvas.setHeight(this.canvas.getHeight() * scale);
        // 计算包含对象的尺寸布局
        this.calculateEleScale(canvas, scale);
        this.canvas.renderAll();
    }

    /**
     * 获取缩放值与比例,增加限制最大最小
     */
    getScaleValue(currentScale, num) {
        let newScale = this.currentScale + num;
        // 处理计算精度瑕疵
        newScale = Number(newScale.toFixed(1));
        if (newScale < this.scaleMin || newScale > this.scaleMax) {
            // 越限直接返回当前比例
            return [ currentScale, 1 ];
        }
        // 处理比例关系
        return [ newScale, (this.currentScale + num) / this.currentScale ];
    }

    /**
     * 计算画布包含对象的缩放
     */
    calculateEleScale(canvas, scale) {
        let objects = canvas.getObjects();
        for (let i in objects) {
            let map = [ 'scaleX', 'scaleY', 'left', 'top' ];
            map.map((attr) => {
                objects[i][attr] *= scale;
            });
        }
    }
复制代码

 

记录:canvas 内部 滚轮事件,实现逻辑类似,效果一样

canvas.on({
    "mouse:wheel": (e) => {
        event.deltaY > 0;
    },
});

 

记录其他实现:

复制代码
        // 向中心缩放
        let zoom;
        canvas.on({
            // 鼠标滚动缩放
            "mouse:wheel": (e) => {
                zoom = (event.deltaY > 0 ? -0.1 : 0.1) + canvas.getZoom();
                zoom = Math.max(0.1, zoom); //最小为原来的1/10
                zoom = Math.min(3, zoom); //最大是原来的3倍
                let zoomPoint = new fabric.Point(400, 400); // 中心点
                canvas.zoomToPoint(zoomPoint, zoom);
            },
        });
复制代码
复制代码
        // 向左上角缩放
        canvas.on('mouse:wheel', function(opt) {
            let delta = opt.e.deltaY;
            let zoom = canvas.getZoom();
            zoom *= 0.999 ** delta;
            if (zoom > 20) zoom = 20;
            if (zoom < 0.01) zoom = 0.01;
            canvas.setZoom(zoom);
            opt.e.preventDefault();
            opt.e.stopPropagation();
        });
复制代码

 

posted @   名字不好起啊  阅读(585)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2020-04-14 python 处理 excel 基本操作
点击右上角即可分享
微信分享提示