Konva - сцена, сосредоточенная на увеличении - PullRequest
0 голосов
/ 16 мая 2018

Я использую Konva для панорамирования и масштабирования сцены, содержащей изображение и другие элементы. Я установил draggable в true, и я использую touchmove и touchend, чтобы установить масштаб сцены. Тем не менее, сцена масштабируется от верхнего левого угла вместо точки защемления. Если я пытаюсь отрегулировать положение сцены, основываясь на центре прижима, положение сцены, кажется, прыгает вокруг, потому что перетаскивание, кажется, также устанавливает положение. Есть ли хороший способ установить положение сцены в крайнем случае при масштабировании?

1 Ответ

0 голосов
/ 01 июня 2018

Вот что я сделал для своей игры. По сути, вам нужно установить положение сцены в обработчике событий touchMove на вычисленное смещение относительно фокальной точки, устанавливаемой в начале масштабирования.

function getDistance(p1, p2) {
    return Math.sqrt(Math.pow((p2.x - p1.x), 2) + Math.pow((p2.y - p1.y),2));
}

function getMapPointFromPoint(windowX,windowY) {
    if (windowX === undefined) {
        //inverse the coordinates and account for stage position
        var mapX = Math.floor((-(stage.getX()) + (window.innerWidth*mapOffset)) / zoomLevel);
        var mapY = Math.floor((-(stage.getY()) + (window.innerHeight/2)) / zoomLevel);
        return({x: mapX, y: mapY});
    } else {
        var mapX = Math.floor((-(stage.getX()) + windowX) / zoomLevel);
        var mapY = Math.floor((-(stage.getY()) + windowY) / zoomLevel);
        return({x: mapX, y: mapY});     
    }   
}

function setFocalPoint(mapX,mapY) {
    if (mapX === undefined) {
    // reverse the zoom to figure out the map coordinates at center of screen
        var focalPoint = getMapPointFromPoint();
        focalMapX = focalPoint.x;
        focalMapY = focalPoint.y;
    } else {
        focalMapX = mapX;
        focalMapY = mapY;
    }
}

function scrollToMapPoint(x,y) {
    stage.setPosition({x: Math.floor((window.innerWidth*mapOffset) - (x * zoomLevel)) , y: Math.floor((window.innerHeight/2) - (y * zoomLevel)) });
    cullView();
    stage.draw();
}

stage.getContent().addEventListener('touchstart', function(evt) {
    var touch1 = evt.touches[0];
    var touch2 = evt.touches[1];

    touchInitPoint.x = touch1.clientX;
    touchInitPoint.y = touch1.clientY;
    if (touch1 && touch2) {
        if (!pinching) {
            setFocalPoint();
            pinching = true;
            cacheON();
        }
    }
});

stage.getContent().addEventListener('touchmove', function(evt) {
    var touch1 = evt.touches[0];
    var touch2 = evt.touches[1];

    if (touch1 && touch2) {
        var dist = getDistance({
            x: touch1.clientX,
            y: touch1.clientY
        }, {
            x: touch2.clientX,
            y: touch2.clientY
        });

        if (!lastDist) {
            lastDist = dist;
        }

        var scale = stage.getScaleX() * dist / lastDist;
        if (scale < 0.2) {
            scale = 0.2;
        } else if (scale > 2) {
            scale = 2;
        }

        stage.scaleX(scale);
        stage.scaleY(scale);
        zoomLevel = scale;
        scrollToMapPoint(focalMapX,focalMapY);
        stage.draw();
        lastDist = dist;
    } else {
        if (pinching) {
        //if losing contact with one touch, assume we start over on distance
            lastDist = 0;
        }
    }

}, false);

stage.getContent().addEventListener('touchend', function(evt) {
    var touch1 = evt.touches[0];
    var touch2 = evt.touches[1];

    if (pinching && (touch1 || touch2)) {
        //wait until both gone
        return;
    } else {
        if (pinching) {
            lastDist = 0;
            scrollToMapPoint(focalMapX,focalMapY);
            if (pinchTimer) {
                clearTimeout(pinchTimer);
            }
            pinchTimer = setTimeout(function () {
                pinching = false;
                cacheOFF();
            },1000);                    
        }
    }
}, false);
...