【问题标题】:FabricJS Touch Pan/Zoom Entire CanvasFabricJS 触摸平移/缩放整个画布
【发布时间】:2017-12-20 00:05:45
【问题描述】:

我需要在 FabricJS 画布上启用触摸缩放/平移。有些库允许在图像上执行此行为(请参阅pinch-zoom-canvas)或通过鼠标单击事件(请参阅this Fiddle),但我似乎无法正确连接“触摸:手势”事件。

我已经构建了启用手势的库(所以 this FabricJS 演示对我来说在本地工作),但我不知道从哪里开始将手势与工作小提琴结合起来。

我尝试了这样的代码变体:

    canvas.on({
        'touch:gesture': function() {
            var text = document.createTextNode(' Gesture ');
            info.insertBefore(text, info.firstChild);
            // Handle zoom only if 2 fingers are touching the screen
            if (event.e.touches && event.e.touches.length == 2) {
                // Get event point
                var point = new fabric.Point(event.self.x, event.self.y);
                // Remember canvas scale at gesture start
                if (event.self.state == "start") {
                    zoomStartScale = self.canvas.getZoom();
                }
                // Calculate delta from start scale
                var delta = zoomStartScale * event.self.scale;
                // Zoom to pinch point
                self.canvas.zoomToPoint(point, delta);
            }

        },
        'touch:drag': function(e) {
            panning = true;
            var text = document.createTextNode(' Dragging ');
            info.insertBefore(text, info.firstChild);
            if (panning && e && e.e) {
                debugger;
                var units = 10;
                var delta = new fabric.Point(e.e.movementX, e.e.movementY);
                canvas.relativePan(delta);
            }
            panning = false;
        },
        'touch:longpress': function() {
            var text = document.createTextNode(' Longpress ');
            info.insertBefore(text, info.firstChild);
        }
    });

但是当我在 iPhone/iPad 上测试时,什么都没有发生。

【问题讨论】:

    标签: canvas fabricjs


    【解决方案1】:

    捏缩放是一个愚蠢的错误,我没有在函数参数中包含该事件。下面的代码适用于捏/缩放和点击/拖动。

        canvas.on({
            'touch:gesture': function(e) {
                if (e.e.touches && e.e.touches.length == 2) {
                    pausePanning = true;
                    var point = new fabric.Point(e.self.x, e.self.y);
                    if (e.self.state == "start") {
                        zoomStartScale = self.canvas.getZoom();
                    }
                    var delta = zoomStartScale * e.self.scale;
                    self.canvas.zoomToPoint(point, delta);
                    pausePanning = false;
                }
            },
            'object:selected': function() {
                pausePanning = true;
            },
            'selection:cleared': function() {
                pausePanning = false;
            },
            'touch:drag': function(e) {
                if (pausePanning == false && undefined != e.e.layerX && undefined != e.e.layerY) {
                    currentX = e.e.layerX;
                    currentY = e.e.layerY;
                    xChange = currentX - lastX;
                    yChange = currentY - lastY;
    
                    if( (Math.abs(currentX - lastX) <= 50) && (Math.abs(currentY - lastY) <= 50)) {
                        var delta = new fabric.Point(xChange, yChange);
                        canvas.relativePan(delta);
                    }
    
                    lastX = e.e.layerX;
                    lastY = e.e.layerY;
                }
            }
        });
    

    绝对~50px if/then 语句是为了避免拖离最后一点很远导致画布跳跃。还暂停了平移,以便能够独立移动对象。在github issues thread 中找到捏合/缩放代码。

    【讨论】:

    • 太棒了!对所有面料用户来说真的是一个很大的帮助!
    • 有一些问题:我试过这个答案,但我的canvas 没有收到touch:gesture,似乎只有对象收到touch:gesture?真的很想知道您的画布如何接收touch:gesture 事件,谢谢!顺便说一句,我正在使用 1.7.20(带有 build_with_gestures)。
    • 是否可以只缩放元素?如果我尝试放大画布背景,我想放大整个页面。
    • @Simone 您可能可以使用 'object:hover' 来更改对象的比例。我会创建一个单独的问题来概述您想要的功能
    【解决方案2】:

    让 Laurens 代码的平移部分在 Fabric 2.3.3 上工作时遇到了一些麻烦。所以如果有人遇到同样的问题,我想分享我的解决方案。

    我的问题是,我无法在智能手机上进行平移,即使它可以在电脑上运行。经过一些调试后,我发现我可以通过将e.e.layerX 替换为e.self.x(并将e.e.layerY 替换为e.self.y)来解决它。

    以下是修改后的完整代码:

    canvas.on({
        'touch:gesture': function(e) {
            if (e.e.touches && e.e.touches.length == 2) {
                pausePanning = true;
                var point = new fabric.Point(e.self.x, e.self.y);
                if (e.self.state == "start") {
                    zoomStartScale = canvas.getZoom();
                }
                var delta = zoomStartScale * e.self.scale;
                canvas.zoomToPoint(point, delta);
                pausePanning = false;
            }
        },
        'object:selected': function() {
            pausePanning = true;
        },
        'selection:cleared': function() {
            pausePanning = false;
        },
        'touch:drag': function(e) {
            if (pausePanning == false && undefined != e.self.x && undefined != e.self.x) {
                currentX = e.self.x;
                currentY = e.self.y;
                xChange = currentX - lastX;
                yChange = currentY - lastY;
    
                if( (Math.abs(currentX - lastX) <= 50) && (Math.abs(currentY - lastY) <= 50)) {
                    var delta = new fabric.Point(xChange, yChange);
                    canvas.relativePan(delta);
                }
    
                lastX = e.self.x;
                lastY = e.self.y;
            }
        }
    });}
    

    【讨论】:

    • 谢谢你!!!我也有问题让画布平移工作,这解决了它。
    【解决方案3】:

    我能够通过 mouse:wheel 事件实现多点触控平移和缩放。

    当进行捏合缩放时 - most browsers 通常也会发出 ctrl 按钮来区分滚动操作与否。

    然后,我利用 Fabric 事件的 DeltaX 和 DeltaY 属性来缩放或平移,类似于他们提供的 sample 代码。

    如果你不使用 React,我在下面调用 setState 的每个地方都应该是函数外部的变量。

        this.canvas.on("mouse:wheel", opt => {
          if (!this.canvas.viewportTransform) {
            return;
          }
    
          var evt: any = opt.e;
          if (evt.ctrlKey === true) {
            var evt: any = opt.e;
            var deltaY = evt.deltaY;
            var zoom = this.canvas.getZoom();
            zoom = zoom - deltaY / 100;
            if (zoom > 20) zoom = 20;
            if (zoom < 0.01) zoom = 0.01;
            this.canvas.zoomToPoint(
              new fabric.Point(evt.offsetX, evt.offsetY),
              zoom
            );
          } else {
            console.log("Scrolling!!");
    
            //inverted scrolling enabled. Remove the -1 multiplier to disable
    
            this.canvas.viewportTransform[4] += (evt.deltaX)*-1; 
            this.canvas.viewportTransform[5] += (evt.deltaY)*-1;
            this.canvas.requestRenderAll();
            this.setState({ lastPosX: evt.clientX });
            this.setState({ lastPosY: evt.clientY });
          }
          opt.e.preventDefault();
          opt.e.stopPropagation();
        });
    

    【讨论】:

      猜你喜欢
      • 2015-08-08
      • 2016-08-26
      • 2015-01-15
      • 1970-01-01
      • 2018-05-13
      • 1970-01-01
      • 2017-05-30
      • 2015-05-05
      • 1970-01-01
      相关资源
      最近更新 更多