我正在尝试制作一个可以在游戏中用作小 map 的全景 Canvas 。我将舞台设置为可拖动,以便玩家可以用鼠标四处移动,以及在舞台的各个层上移动单个对象。但是,我不想将舞台拖到周围的空白区域。换句话说,我只想允许在放大时进行平移,所以您永远不会遇到该空白。为了限制舞台,我设置了dragBoundFunc:

        dragBoundFunc: function(pos) {
            return {
                x: (pos.x < 0 ? 0 : pos.x > width ? width : pos.x),
                y: (pos.y < 0 ? 0 : pos.y > height ? height : pos.y)
            };
        }

(完整的JSF中间示例:http://jsfiddle.net/4Brry/)

我遇到两个问题:
  • 首先, Canvas 仍然可以向上和向左移动。
  • 其次,更令人讨厌的是,当我们开始缩放时,约束开始出现异常。
    缩放时,约束不会考虑到这一事实。那么,如果我们添加位移台呢?
            dragBoundFunc: function(pos) {
            return {
                x: ((ui.stage.getOffset().x+pos.x) < 0 ? 0 : pos.x > width ? width : pos.x),
                y: ((ui.stage.getOffset().y+pos.y) < 0 ? 0 : pos.y > height ? height : pos.y)
            };
        }
    

    (完整的JSF中间示例:http://jsfiddle.net/2fLCd/)

  • 这样好多了,但是现在当您走得太远时, View 会“回弹”。如果它只是停止沿不允许的方向移动,那就更好了。

    有人知道我该如何解决这些问题?

    最佳答案

    好的,我将Zynga Scroller功能与KineticJS框架集成在一起,以获得所需的东西。

    Code in action

    让我们看一下代码,它是我在网上找到并写自己的东西的混合物。

    首先,我们使用KineticJS生成 Canvas :

    var width = 700;
    var height = 700;
    var stage = new Kinetic.Stage({
        container: 'container',
        width: width,
        height: height
    });
    
    var layer = new Kinetic.Layer({});
    stage.add(layer);
    
    /* I skipped some circle generation code. */
    

    然后,我们定义一些在图层上拖放某些东西时触发的事件。我们将使用它们来填充一个名为somethingIsBeingDraggedInKinetic的全局变量。我们将在Zynga Scroller的平移代码中使用此变量,以便在拖动KineticJS形状时不会移动整个舞台。
    var somethingIsBeingDraggedInKinetic = false;
    layer.on('dragstart', function(evt) {
        // get the thing that is being dragged
        var thing = evt.targetNode;
        if( thing )
            somethingIsBeingDraggedInKinetic = true;
      });
    
    layer.on('dragend', function(evt) {
        // get the thing that is being dragged
        var thing = evt.targetNode;
        if( thing )
            somethingIsBeingDraggedInKinetic = false;
      });
    

    接下来是Zynga Scroller初始化代码。 Zynga Scroller代码处理输入和转换,然后将三个值传递给呈现函数:topleftzoom。这些值非常适合传递给KineticJS框架:
    // Canvas renderer
    var render = function(left, top, zoom) {
    
        // Constrain the stage from going too far to the right
        if( (left + (width / zoom)) > width )
            left = width - (width / zoom );
    
        // Constrain the stage from going too far to the left
        if( (top + (height / zoom)) > height )
            top = height - (height / zoom );
    
        stage.setOffset(left, top);
        stage.setScale(zoom);
        stage.draw();
    };
    
    // Initialize Scroller
    this.scroller = new Scroller(render, {
        zooming: true,
        animating: false,
        bouncing: false,
        locking: false,
        minZoom: 1
    });
    

    之后,我们需要正确放置Zynga Scroller。我承认这部分对我来说有点黑魔法。我从“asset / ui.js”文件复制了其余代码。
    var container = document.getElementById("container");
    var rect = container.getBoundingClientRect();
    scroller.setPosition(rect.left + container.clientLeft, rect.top + container.clientTop);
    scroller.setDimensions(700, 700, width, height);
    

    最后,我也复制了平移代码,并添加了一些代码来检查KineticJS框架是否在移动某些东西:
    var mousedown = false;
    
    container.addEventListener("mousedown", function(e) {
        if (e.target.tagName.match(/input|textarea|select/i)) {
            return;
        }
    
        scroller.doTouchStart([{
            pageX: e.pageX,
            pageY: e.pageY
        }], e.timeStamp);
    
        mousedown = true;
    }, false);
    
    document.addEventListener("mousemove", function(e) {
        if (somethingIsBeingDraggedInKinetic)
            return;
    
        if (!mousedown) {
            return;
        }
    
        scroller.doTouchMove([{
            pageX: e.pageX,
            pageY: e.pageY
        }], e.timeStamp);
    
        mousedown = true;
    }, false);
    
    document.addEventListener("mouseup", function(e) {
        if (!mousedown) {
            return;
        }
    
        scroller.doTouchEnd(e.timeStamp);
    
        mousedown = false;
    }, false);
    

    哦,还有缩放处理程序。
    container.addEventListener(navigator.userAgent.indexOf("Firefox") > -1 ? "DOMMouseScroll" :  "mousewheel", function(e) {
        scroller.doMouseZoom(e.detail ? (e.detail * -120) : e.wheelDelta, e.timeStamp, e.pageX, e.pageY);
    }, false);
    

    这是可缩放 map 的完美基础!

    10-04 16:47