reactjs - 反应 konva 在舞台上放大时保持一层固定
问题描述
我正在 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>
)
}
解决方案
我强烈建议您不要使用在画布(舞台)上绘制的按钮。您应该使用标准的 HTML 按钮。您可以使用 css(绝对位置)将它们放置在舞台顶部。
如果你这样做,对你有很多好处。例如,您可以更轻松更好地设计它。此外,它更高效,也解决了这个问题的问题。
推荐阅读
- ajax - 在 wordpress 4.9.8 上通过 ajax 获取简码内容失败
- angular - Observable 不断解决
- android - Android Oreo 服务 - 应用程序在后台时不会触发位置更改事件
- delphi - Datasnap - 使用 TFDGUIxWaitCursor 时如何修复链接器错误?
- python - 查找层次区域图像
- c# - 如何使用模式 MVP(Passive) 在 Windows 窗体中为用户控件定义正确的架构?
- c# - 如何从字符串中识别 IATA 或 ICAO 代码
- android - textView 动态更改为更短的文本而不是 ellipsize
- android - 警报对话框信息按钮
- r - 如何导入乌尔都语数据集