我一直在尝试在 React 中实现可拖动的 div,基本上我会使用鼠标单击并拖动元素,如果我在移动设备上,甚至是手指。 问题是,当我移动鼠标太快并且光标离开 div 区域时,元素停止被拖动。这就像我没有足够快地更新 div 的位置以跟上光标速度。 知道我该如何解决这个问题吗?
此外,我一直在使用顶部和左侧位置来更新 div 的位置,使用 css translatex/y 有什么好处吗? 它有什么不同?
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
class App extends Component {
constructor() {
super();
this.state = {
pos: {
x:0,
y:0,
},
rel: {
x:0,
y:0
},
dragging : false
};
this.draggable = React.createRef()
}
onTouchStart = e => {
const touch = e.touches[0]
const posTop = this.draggable.current.offsetTop
const posLeft = this.draggable.current.offsetLeft
this.setState({
dragging: true,
rel: {
x: touch.clientX - posLeft,
y: touch.clientY - posLeft
}
})
e.stopPropagation()
}
onTouchMove = e => {
if (!this.state.dragging) return
const touch = e.touches[0]
this.setState({
pos: {
x: touch.clientX - this.state.rel.x,
y: touch.clientY - this.state.rel.y
}
})
e.stopPropagation()
e.preventDefault()
}
onTouchEnd = e => {
this.setState({dragging: false})
}
onMouseDown = (e) => {
// only left mouse button
if (e.button !== 0) return
const posTop = this.draggable.current.offsetTop
const posLeft = this.draggable.current.offsetLeft
console.log(e.pageX,': pagex ', e.pageY, ' : and pagey')
console.log(posTop, ': posTop', posLeft, ' : posY')
console.log('resultLeft :', e.pageX - posLeft, 'resultTop :', e.pageY - posTop)
this.setState({
dragging: true,
rel: {
x: e.pageX - posLeft,
y: e.pageY - posTop
}
})
e.stopPropagation()
e.preventDefault()
}
onMouseUp = (e) => {
this.setState({dragging: false})
e.stopPropagation()
e.preventDefault()
}
onMouseMove = (e) => {
if (!this.state.dragging) return
this.setState({
pos: {
x: e.pageX - this.state.rel.x,
y: e.pageY - this.state.rel.y
}
})
e.stopPropagation()
e.preventDefault()
}
render() {
return (
<div style={{position:'relative', backgroundColor:'green', height:'100%', width:'100%'}}>
<div style={{position:'absolute',backgroundColor:'red',
height: '100px', width:'100px',
left: this.state.pos.x + 'px', top: this.state.pos.y + 'px'}}
onTouchStart={this.onTouchStart}
onTouchMove={this.onMouseMove}
onTouchEnd={this.onTouchEnd}
onMouseDown={this.onMouseDown}
onTouchMove={this.onTouchMove}
onMouseMove={this.onMouseMove}
onMouseUp={this.onMouseUp}
ref={this.draggable}
> draggable div
</div>
</div>
);
}
}
render(<App />, document.getElementById('root'));
您可以将代码放在 stackblitz 上,它会起作用,因此您可以尝试。 我们非常欢迎任何建议!
Stackblitz 链接:https://stackblitz.com/edit/react-draggable-test-oezlsk
最佳答案
好的, 发现了问题。 我正在将事件 onMouseUp onMouseMove 分配给 div 而不是父亲。 此外,由于没有任何尺寸的根 div,父级没有适当的高度和宽度。
更新后的工作代码如下
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
class App extends Component {
constructor() {
super();
this.state = {
pos: {
x:0,
y:0,
},
rel: {
x:0,
y:0
},
dragging : false
};
this.draggable = React.createRef()
}
onTouchStart = e => {
const touch = e.touches[0]
const posTop = this.draggable.current.offsetTop
const posLeft = this.draggable.current.offsetLeft
this.setState({
dragging: true,
rel: {
x: touch.clientX - posLeft,
y: touch.clientY - posLeft
}
})
e.stopPropagation()
}
onTouchMove = e => {
if (!this.state.dragging) return
const touch = e.touches[0]
this.setState({
pos: {
x: touch.clientX - this.state.rel.x,
y: touch.clientY - this.state.rel.y
}
})
e.stopPropagation()
e.preventDefault()
}
onTouchEnd = e => {
this.setState({dragging: false})
}
onMouseDown = (e) => {
// only left mouse button
if (e.button !== 0) return
const posTop = this.draggable.current.offsetTop
const posLeft = this.draggable.current.offsetLeft
console.log(e.pageX,': pagex ', e.pageY, ' : and pagey')
console.log(posTop, ': posTop', posLeft, ' : posY')
console.log('resultLeft :', e.pageX - posLeft, 'resultTop :', e.pageY - posTop)
this.setState({
dragging: true,
rel: {
x: e.pageX - posLeft,
y: e.pageY - posTop
}
})
e.stopPropagation()
e.preventDefault()
}
onMouseUp = (e) => {
this.setState({dragging: false})
e.stopPropagation()
e.preventDefault()
}
onMouseMove = (e) => {
if (!this.state.dragging) return
this.setState({
pos: {
x: e.pageX - this.state.rel.x,
y: e.pageY - this.state.rel.y
}
})
e.stopPropagation()
e.preventDefault()
}
render() {
return (
<div onMouseUp={this.onMouseUp} onMouseMove={this.onMouseMove} style={{position:'relative', backgroundColor:'green', height:'120%', width:'120%'}}>
<div style={{position:'absolute',backgroundColor:'red',
height: '100px', width:'100px',
left: this.state.pos.x + 'px', top: this.state.pos.y + 'px'}}
onTouchStart={this.onTouchStart}
onTouchMove={this.onMouseMove}
onTouchEnd={this.onTouchEnd}
onMouseDown={this.onMouseDown}
onTouchMove={this.onTouchMove}
ref={this.draggable}
> draggable div
</div>
</div>
);
}
}
render(<App />, document.getElementById('root'));
关于javascript - 当光标离开 div 区域时元素停止拖动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55626880/