如何限制在反应三个光纤MapControls平移距离



我使用React Three Fiberdrei。我想知道如何限制MapControls的最大平移距离。网上有一些关于如何用普通three.js存档它的解决方案,但没有使用dreir3fMapControlsOrbitControls

我试过了,但是一旦我达到极限,相机就会奇怪地出现故障。

function Controls() {
const { camera } = useThree();
useFrame(() => {
camera.position.x = THREE.MathUtils.clamp(camera.position.x, -90, 90)
camera.position.y = THREE.MathUtils.clamp(camera.position.y, -90, 90)
})

return (
<MapControls />
)
}

谢谢你的帮助

亚历山大

基于这个答案,一个解决方案是创建一个自定义的'Controls'组件,如下所示:

const Controls = () => {
const { camera } = useThree()
const controlsRef = useRef()    
useEffect(() => {
controlsRef.current.addEventListener('change', function () {
if (this.target.y < -10) {
this.target.y = -10
camera.position.y = -10
} else if (this.target.y > 10) {
this.target.y = 10
camera.position.y = 10
}
})
}, [])
return (
<MapControls ref={controlsRef} enableZoom={false} enableRotate={false} />
)
}

可以用作Canvas组件的子组件。

<Canvas>
<Controls />
</Canvas>

我的解决方案是基于上面的答案

const { camera, size } = useThree();
const limitPanningDistance = useCallback(
(e?: THREE.Event) => {
// 704.5 102
// 1056.75 320
// Returns the drag container width and height
const [w, h] = [1920, 1080]
const pan = (w * camera.zoom - size.width) / 2 / camera.zoom;
const vertical = (h * camera.zoom - size.height) / 2 / camera.zoom;
// console.log('pan vertical', pan, vertical);
const maxX = pan;
const minX = -pan;
const maxY = vertical;
const minY = -vertical;
const x = e?.target.target.x;
const y = e?.target.target.y;
if (x < minX || x > maxX) {
e?.target.target.setX(x < minX ? minX : maxX);
camera.position.setX(x < minX ? minX : maxX);
}
if (y < minY || y > maxY) {
e?.target.target.setY(y < minY ? minY : maxY);
camera.position.setY(y < minY ? minY : maxY);
}
},
[camera.zoom, size]
);
<MapControls
enableRotate={false}
minZoom={1}
maxZoom={2}
onChange={(e) => {
// console.log(e?.target);
limitPanningDistance(e);
}}
makeDefault
/>

这是我使用MapControlsonChange属性的解决方案。

控制组件:

import React, { useRef } from 'react'
import { MapControls } from '@react-three/drei'
import { useThree } from '@react-three/fiber'
const Controls = () => {
const { camera } = useThree()
const cameraLastPosition = useRef({
x: camera.position.x,
y: camera.position.y,
})
return (
<MapControls
onChange={(e) => {
const maxX = 90
const minX = -90
const maxY = 90
const minY = -90
const x = e?.target.target.x
const y = e?.target.target.y
if (x < minX || x > maxX) {
e?.target.target.setX(x < minX ? minX : maxX)
camera.position.setX(cameraLastPosition.current.x)
}
if (y < minY || y > maxY) {
e?.target.target.setY(y < minY ? minY : maxY)
camera.position.setY(cameraLastPosition.current.y)
}
cameraLastPosition.current.x = camera.position.x
cameraLastPosition.current.y = camera.position.y
}}
/>
)
}
export default Controls

导入该组件并在Canvas:

中使用它
<Canvas>
<Controls />
</Canvas>

最新更新