我正在 Konva 中开发地图(绿色矩形)和在其上绘制的路径(黑线):
地图具有固定尺寸,而路径是从 API 调用中获取的。
我希望能够使用鼠标滚动或单击我创建的按钮 + o 来缩放地图。
我按照这个示例如何对滚动进行 react-konva 缩放以实现缩放,但是当我滚动时,按钮也会改变它们的位置,见下图。
我想将按钮固定在地图的底部。
这是我的一段代码,我定义了一些自定义组件为Map、Ground、WholePath、GroundButtons和Button:
export const Map = ( props ) => {
const [mouseScale, setMouseScale] = useState(1);
const [x0, setX0] = useState(0);
const [y0, setY0] = useState(0);
const scaleBy = 1.02;
const handleWheel = (e) => {
const group = e.target.getStage();
e.evt.preventDefault();
const mousePointTo = {
x: group.getPointerPosition().x / mouseScale - group.x() / mouseScale,
y: group.getPointerPosition().y / mouseScale - group.y() / mouseScale
};
const newScale = e.evt.deltaY < 0 ? mouseScale * scaleBy : mouseScale / scaleBy;
setMouseScale(newScale);
setX0(-(mousePointTo.x - group.getPointerPosition().x / newScale) * newScale );
setY0(-(mousePointTo.y - group.getPointerPosition().y / newScale) * newScale );
};
const SimulateMouseWheel = (e, BtnType, mScale = scaleBy) => {
const newScale = BtnType > 0 ? mouseScale * mScale : mouseScale / mScale;
setMouseScale(newScale);
};
const onClickPlus = (e) => {
SimulateMouseWheel(e, +1, 1.08);
};
const onClickMinus = (e) => {
SimulateMouseWheel(e, -1, 1.08);
};
return (
<Stage
width={800}
height={400}
draggable={true}
onWheel={handleWheel}
scaleX={mouseScale}
scaleY={mouseScale}
x={x0}
y={y0}
>
<Layer>
<Ground pitch={props.pitch}/>
<WholePath path={props.path}/>
</Layer>
<Layer>
<GroundButtons reference={props.reference} onClickMinus={onClickMinus} onClickPlus={onClickPlus} />
</Layer>
</Stage>
)
}
const GroundButtons = ( props ) => {
return (
<Group>
<Button xText={10} yText={5} text={"+"} x={790} y={360} side={30} onClick={props.onClickPlus}/>
<Button xText={12} yText={5} text={"-"} x={790} y={360} side={30} onClick={props.onClickMinus}/>
</Group>
)
}
const Button = props => {
return (
<Group x={props.x} y={props.y} onClick={props.onClick}>
<Rect
width={props.side}
height={props.side}
fill='#f2f1f0'
stroke='#777'
strokeWidth={1}
/>
<Text
x={props.xText}
y={props.yText}
fontSize={20}
text={props.text}
stroke='#777'
align="center"
strokeWidth={1}
/>
</Group>
)
}
这是我实施的解决方案: 感谢 Ondolin 的回答。
export const Map = ( props ) => {
const [mouseScale, setMouseScale] = useState(1);
const [x0, setX0] = useState(0);
const [y0, setY0] = useState(0);
const scaleBy = 1.02;
const handleWheel = (e) => {
const group = e.target.getStage();
e.evt.preventDefault();
const mousePointTo = {
x: group.getPointerPosition().x / mouseScale - group.x() / mouseScale,
y: group.getPointerPosition().y / mouseScale - group.y() / mouseScale
};
const newScale = e.evt.deltaY < 0 ? mouseScale * scaleBy : mouseScale / scaleBy;
setMouseScale(newScale);
setX0(-(mousePointTo.x - group.getPointerPosition().x / newScale) * newScale );
setY0(-(mousePointTo.y - group.getPointerPosition().y / newScale) * newScale );
};
const SimulateMouseWheel = (e, BtnType, mScale = scaleBy) => {
const newScale = BtnType > 0 ? mouseScale * mScale : mouseScale / mScale;
setMouseScale(newScale);
};
const onClickPlus = (e) => {
SimulateMouseWheel(e, +1, 1.08);
};
const onClickMinus = (e) => {
SimulateMouseWheel(e, -1, 1.08);
};
return (
<div>
<Stage
width={800}
height={400}
draggable={true}
onWheel={handleWheel}
scaleX={mouseScale}
scaleY={mouseScale}
x={x0}
y={y0}
>
<Layer>
<Ground pitch={props.pitch}/>
<WholePath path={props.path}/>
</Layer>
<Layer>
<GroundButtons reference={props.reference} onClickMinus={onClickMinus} onClickPlus={onClickPlus} />
</Layer>
</Stage>
<button className="ground_controls" onClick={onClickPlus}><i className="fa fa-plus" aria-hidden="true"></i></button>
<button className="ground_controls" onClick={onClickMinus}><i className="fa fa-minus" aria-hidden="true"></i></button>
</div>
)
}