Konva - 以捏缩放为中心的舞台

时间:2018-05-16 20:34:20

标签: konvajs

我使用Konva平移和缩放包含图像和其他元素的舞台。我将draggable设置为true,我使用touchmove和touchend来设置舞台比例。但是,舞台从左上角而不是缩点进行缩放。如果我尝试根据夹点中心调整舞台位置,舞台位置似乎会跳跃,因为可拖动似乎也在设置位置。有一种很好的方法可以在缩放时设置捏合时的舞台位置吗?

1 个答案:

答案 0 :(得分:0)

这就是我为游戏所做的事情。基本上你必须将touchMove事件处理程序的stagePosition设置为在缩放开始时设置的焦点的计算偏移量。

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