簡體   English   中英

Kinetic.js:防止可拖動的舞台離開邊界

[英]Kinetic.js: Prevent draggable stage from going off-boundaries

我正在嘗試制作一個平移和縮放畫布,用作游戲中的小地圖。 我已經將舞台設置為可拖動,因此玩家可以使用鼠標移動,以及在舞台的各個層上移動單個對象。 但是,我不希望能夠將舞台拖入周圍的空白區域。 換句話說,我只想在放大時允許平移,這樣你就不會遇到那個空白區域。 為了嘗試約束舞台,我設置了一個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)
            };
        }

(完整的JSFiddle示例: http//jsfiddle.net/4Brry/

我遇到兩個問題:

  • 首先,畫布仍然能夠向上和向左移動。
  • 其次,更令人討厭的是,當我們開始縮放時,約束開始行為不端。 縮放時,約束不會考慮這一事實。 那么,如果我們添加階段偏移怎么辦?

      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) }; } 

    (完整的JSFiddle示例: http//jsfiddle.net/2fLCd/

這樣做要好得多,但現在當你走得太遠時,視圖會“快速恢復”。 如果它只是停止在不允許的方向上移動會更好。

有誰知道如何解決這些問題?

好的,我將Zynga Scroller功能與KineticJS框架集成在一起,以獲得我想要的東西。

代碼在行動

讓我們看看代碼,這是我在網上發現並自己寫的東西的合並。

首先,我們使用KineticJS生成畫布:

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);

這是一個完美的可縮放地圖的基礎!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM