Set map borders to not cross inside the view area

六月ゝ 毕业季﹏ 提交于 2019-12-13 03:44:14

问题


I am trying to translate an old flash animation with animate. On the original flash animation the map image is draggable and zoomable but the map ´s borders always stick to the sides of the stage if you pan it or zoom it all the way.

On my test i grabbed some code that allows panning and zooming but the map crosses the stage boundaries if you pan all the way, in fact you can make the map dissapear of the stage.

I think there should be a way to draw like a secondary outer stage and not let the map image go beyond it.

This is the code I have.

var that = this;
var clickedX;
var clickedY;
var isDragging = false;
var friction = 0.85;
var speedX = 0;
var speedY = 0;
var mapOriginalX = this.map.x;
var mapOriginalY = this.map.y;
var mapNudge = 5;
var minScale = 0.25;
var maxScale = 3;

function onMouseWheel(e)
{
    var delta;

    if (e == window.event)
        delta = -10 / window.event.wheelDeltaY;
    else
        delta = e.detail / 30;

    var zoomFactor = delta; 
    scaleMap(zoomFactor);   
}

function mouseDown(e)
{
    clickedX = stage.mouseX;
    clickedY = stage.mouseY;
    isDragging = true;  
    console.log(stage.mouseX);
    console.log(stage.mouseY);

}

function stageMouseUp(e)
{
    isDragging = false;
}

function update(e)

{



if (isDragging)
{
    speedX = stage.mouseX - clickedX;
    speedY = stage.mouseY - clickedY;
}   

speedX *= friction;
speedY *= friction;

// saber el tamaño actual del mapa en este punto.
that.map.x += speedX;
that.map.y += speedY; 
console.log(that.map.y); 
console.log(that.map.x); 
clickedX = stage.mouseX;
clickedY = stage.mouseY;

    // 
}

function resetMap()
{
    that.map.x = mapOriginalX;
    that.map.y = mapOriginalY;
    that.map.scaleX = that.map.scaleY = 1;
}

function zoomMap(e)  //control visual
{  
    if (e.currentTarget == that.plusButton)
        scaleMap(-0.1);
    if (e.currentTarget == that.minusButton)
        scaleMap(0.1);
}

function moveMap(e) //control visual
{
    if (e.currentTarget == that.upButton)
        speedY -= mapNudge;
    else if (e.currentTarget == that.rightButton)
        speedX += mapNudge;
    else if (e.currentTarget == that.downButton)
        speedY += mapNudge;
    else if (e.currentTarget == that.leftButton)
        speedX -= mapNudge;
}

function scaleMap(amount)
{

    var map = that.map; // we will scale de map so this goes first.

    map.scaleX -= amount;  // same as map.scaleX = map.scaleX - amount
    map.scaleY = map.scaleX; 

    if (map.scaleX < minScale)
        map.scaleX = map.scaleY = minScale;
    else if (map.scaleX > maxScale)
        map.scaleX = map.scaleY = maxScale;
}

// listeners
this.map.on("mousedown", mouseDown.bind(this));
this.resetButton.on("click", resetMap.bind(this));
this.plusButton.on("click", zoomMap.bind(this));
this.minusButton.on("click", zoomMap.bind(this));
this.upButton.on("click", moveMap.bind(this));
this.rightButton.on("click", moveMap.bind(this));
this.downButton.on("click", moveMap.bind(this));
this.leftButton.on("click", moveMap.bind(this));
stage.on("stagemouseup", stageMouseUp.bind(this));
document.getElementById('canvas').addEventListener('mousewheel', onMouseWheel.bind(this));
document.getElementById('canvas').addEventListener('DOMMouseScroll', onMouseWheel.bind(this));
createjs.Ticker.addEventListener("tick", update.bind(this));

resetMap();

回答1:


One trick I usually use is to create a "fence" procedure that checks bounds and corrects them. It will take some setup though.

To use this method, first set up these variables based on your own scene. Perhaps this is what you meant by defining a "second stage?"

var stageLeft = 0;
var stageRight = 500;
var stageTop = 0;
var stageBottom = 500;
this.map.setBounds(0,0,1462, 1047);  // Set the values to match your map
var mapBounds = this.map.getBounds();

Then, add this procedure, or a variation of it based on how your map coordinates are set.

// procedure to correct the map x/y to fit the stage
function fenceMap() {
    var map = that.map;
    var ptTopLeft = map.localToGlobal(mapBounds.x,mapBounds.y);
    var ptBotRight = map.localToGlobal(mapBounds.width,mapBounds.height);

    if ((ptBotRight.x - ptTopLeft.x) > (stageRight-stageLeft)) {
        if (ptTopLeft.x > stageLeft) {
            map.x -= ptTopLeft.x - stageLeft;
            speedX = 0;
        } else if (ptBotRight.x < stageRight) {
            map.x -= ptBotRight.x - stageRight;
            speedX = 0;
        }
    }
    if ((ptBotRight.y - ptTopLeft.y) > (stageBottom-stageTop)) {
        if (ptTopLeft.y > stageTop) {
            map.y -= ptTopLeft.y - stageTop;
            speedY = 0;
        } else if (ptBotRight.y < stageBottom) {
            map.y -= ptBotRight.y - stageBottom;
            speedY = 0;
        }
    }
}

Then, just add to the end of your update(), zoomMap(), moveMap(), and scaleMap() functions:

    fenceMap();


来源:https://stackoverflow.com/questions/50861515/set-map-borders-to-not-cross-inside-the-view-area

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!