无法创建"zoom-in and center object"效果



我们(团队和我(发现了Konva,到目前为止它对我们帮助很大,非常感谢。然而,我们不知道如何创建一个缩放&中心效应。

我们在一个层中添加了几个对象,它本身也添加到一个阶段中,两者都被定义为:

let newStageArea = new Konva.Stage({
container: "mapContainer",
width: canvasWidth ,
height: canvasHeight,
x: 0,
y: 0,
draggable: true,
});
let newLayerArea = new Konva.Layer({
width: canvasWidth,
height: canvasHeight,
x: 0,
y: 0,
//since we parse object coordinates from an external source 
//that uses a centered origin we have to offset the layer
offset: {
x: -(canvasWidth / 2),
y: -(canvasHeight / 2),
},
});

我们现在正在实现一种方法,该方法允许在单击属于该层的对象时对其进行缩放,使其居中并完全可见。这就是我们所拥有的:

const handleAreaClick = (e) => {
e.evt.preventDefault();
let parkingSpace = e.target;
//Get middle of object no matter its shape
let parkingSpaceBox = parkingSpace.getClientRect({  
relativeTo: layerArea,
});
let parkingSpaceCenterX = parkingSpaceBox.x + parkingSpaceBox.width / 2;
let parkingSpaceCenterY = -1 * (parkingSpaceBox.y + parkingSpaceBox.height / 2);

//Zoom&center on object
const padding = 10;
const focusZoomScale = Math.min(
windowWidth / (parkingSpaceBox.width + padding * 2),
canvasHeight/ (parkingSpaceBox.height + padding * 2));

newLayerArea.setAttrs({
x: -parkingSpaceBox.x * focusZoomScale + padding * focusZoomScale,
y: parkingSpaceBox.y * focusZoomScale + padding * focusZoomScale,
scaleX: focusZoomScale,            
scaleY: focusZoomScale
})
}

无论我们如何更改x和y公式(正/负…(,层都不会移动到正确的位置,而是移动到对象的左侧和顶部。但是,对象中间的坐标是正确的。

非常感谢您花时间通读。

这里有一个在视口中缩放形状并使其居中的函数。

/* Function to scale & position the stage as needed to have 
** the target shape fill the viewport. 
** padding parameter is optional - if given this number 
** of pixels is used as padding around the target shape.
*/
function centerAndFitShape(shape, padding) {

// set padding if not provided.
padding = padding ? padding : 0; 

const 

// raw rect around shape, no padding applied.  
// Note: getClientRect gives size based on scaling, but 
// we want the unscaled size so use 'relativeTo: stage' param 
// to ensure consistent measurements.
shapeRectRaw = shape.getClientRect({relativeTo: stage}), 

// Add padding to make a larger rect - this is what we want to fill the view
shapeRect = {
x: shapeRectRaw.x - padding, 
y: shapeRectRaw.y - padding, 
width: shapeRectRaw.width + (2 * padding),
height: shapeRectRaw.height + (2 * padding)
},

// Get the space we can see in the web page = size of div containing stage 
// or stage size, whichever is the smaller
viewRect = {
width: stage.width() <  stage.container().offsetWidth ?  stage.width() : stage.container().offsetWidth, 
height: stage.height() < stage.container().offsetHeight ? stage.height() : stage.container().offsetHeight},        

// Get the ratios of target shape v's view space widths and heights
widthRatio = viewRect.width / shapeRect.width,
heightRatio = viewRect.height / shapeRect.height,

// decide on best scale to fit longest side of shape into view
scale = widthRatio > heightRatio  ? heightRatio : widthRatio,

// calculate the final adjustments needed to make 
// the shape centered in the view
centeringAjustment = {
x: (viewRect.width - shapeRect.width * scale)/2, 
y: (viewRect.height - shapeRect.height * scale)/2      
},

// and the final position is...
finalPosition = {
x: centeringAjustment.x + (-shapeRect.x * scale), 
y: centeringAjustment.y + (-shapeRect.y * scale)
};

// Apply the final position and scale to the stage.
stage.position(finalPosition);
stage.scale({x: scale, y: scale});

} 

这篇博客文章对这种方法进行了解释https://longviewcoder.com/2022/07/13/konva-making-a-shape-fill-the-view/

最新更新