我一直在努力实现一个可拖动的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而不是父亲。此外,由于根部没有任何尺寸,父亲没有适当的高度和宽度。
更新和工作的代码如下
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'));