编程语言
首页 > 编程语言> > javascript – Kinetic.js:防止可拖动的舞台走出界限

javascript – Kinetic.js:防止可拖动的舞台走出界限

作者:互联网

我正在尝试制作一个平移和缩放画布,用作游戏中的小地图.我已经将舞台设置为可拖动,因此玩家可以使用鼠标移动,以及在舞台的各个层上移动单个对象.但是,我不希望能够将舞台拖入周围的空白区域.换句话说,我只想在放大时允许平移,这样你就不会遇到那个空白区域.为了尝试约束舞台,我设置了一个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框架集成在一起,以获得我想要的东西.

Code in action

让我们看看代码,这是我在网上发现并自己写的东西的合并.

首先,我们使用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代码处理输入和转换,然后将三个值传递给渲染函数:top,left和zoom.这些值非常适合传递给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);

这是一个完美的可缩放地图的基础!

标签:javascript,animation,kineticjs
来源: https://codeday.me/bug/20190709/1409978.html