2013-05-06 1 views
4

게임에서 미니 맵으로 사용할 팬 및 줌 캔버스를 만들려고합니다. 무대를 드래그 할 수 있도록 설정 했으므로 플레이어는 마우스로 움직일 수 있으며 무대의 레이어에서 개별 개체를 이동할 수도 있습니다. 그러나 나는 무대를 주변의 공백으로 끌고 싶지 않다. 다른 말로하면 확대 된 상태에서 패닝 만 허용하여 공백이 발생하지 않도록합니다. 나는 두 가지 문제가 발생하고있어Kinetic.js : 드래그 가능한 스테이지가 경계에서 벗어나는 것을 방지합니다.

:

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

(http://jsfiddle.net/4Brry/ 전체 JSFiddle 예 :) : 시도하고 단계를 제한하기 위해, 나는 dragBoundFunc을 설정 한 우선

  • 을 캔버스 여전히 위쪽으로 그리고 왼쪽으로 움직일 수 있습니다.
  • 두 번째로 더 괴롭 으면서 줌을 시작하면 구속이 잘못 될 수 있습니다. 확대/축소시 제약 조건은이 사실을 고려하지 않습니다. 스테이지 오프셋을 추가하면 어떻습니까?

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

이 훨씬 더,하지만 당신은 너무 멀리 갈 때 이제보기 "다시 스냅". 그것이 금지 된 방향으로 움직이는 것을 멈 추면 더 좋을 것입니다.

누구든지 이러한 문제를 해결할 수 있습니다.

+0

"스테이지를 제약합니다"란 무엇입니까? 스테이지의 알레 디가 창과 같이 너비와 높이를 갖고 있다면? – lavrton

+0

JSFiddles를 확인하면 원에서 주변의 공백으로 이동할 수 있습니다. 확대하는 동안 패닝 만 허용하므로 공백이 발생하지 않습니다. – Beerdude26

+0

이 jsfiddles로 장난을 치고 난 후에, 나는 당신이 확대 할 때 실제로 무대의 위치를 ​​바꾸는 것이 아니라, 단지 규모라고 생각합니다. 따라서 x, y 좌표는 실제로 변경되지 않습니다. 당신이 원하는 것은 스케일링 후에 그 x, y를 계산하고 드래그 함수에서 0보다 커지지 않게하는 것입니다. – SoluableNonagon

답변

1

좋아, 내가 원하는 것을 얻기 위해 Zynga Scroller 기능을 KineticJS 프레임 워크와 통합했다. 내가 온라인으로 발견하고 자신을 쓴 것들의 융합이 코드에서

Code in action

하자 단계 모양.

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. */ 

그런 다음, 우리가 불 끌어 층에 뭔가를 포기하면 어떤 이벤트를 정의 :

첫째, 우리는 KineticJS를 사용하여 캔버스를 생성합니다. 이를 사용하여 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, leftzoom을 전달합니다. 이러한 값은 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); 

확대/축소 가능지도의 기초로 완벽합니다.

+0

iPad의 '핀치'이벤트에서이 기능을 사용할 수 있습니까? – LoneWOLFs

관련 문제