简体   繁体   English

当光标离开div区域时元素停止拖动

[英]Element stop dragging when cursor leaves div area react

i've been trying to implement a draggable div in react, basically i would use the mouse to click and drag the element around or even the finger if i'm on mobile. 我一直在尝试在react中实现可拖动的div,基本上,如果我在移动设备上,我会使用鼠标单击并拖动周围的元素,甚至甚至拖动手指。 Problem is that when i move the mouse too fast and cursor leaves div's area the element stops been dragged. 问题是,当我将鼠标移得太快并且光标离开div的区域时,该元素停止了拖动。 It's like i'm not updating div's position fast enough to stay in pace with cursor speed. 就像我没有足够快地更新div的位置以跟上光标速度。 Any idea how can i fix this? 任何想法我该如何解决?

Also i've been using top and left position to update the div's position, is there any advantages in using css translatex/y instead? 另外我一直在使用顶部和左侧位置来更新div的位置,而使用css translatex / y有什么好处吗? What would it differs? 有什么不同?

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'));

You can put the code on stackblitz and it would work so you could try. 您可以将代码放在stackblitz上,它可以工作,所以您可以尝试。 Any advice is more than welcome! 任何建议都值得欢迎!

Stackblitz link : https://stackblitz.com/edit/react-draggable-test-oezlsk Stackblitz链接: https ://stackblitz.com/edit/react-draggable-test-oezlsk

Ok, found out the problem. 好,找出问题所在。 I was assigning event onMouseUp onMouseMove to the div instead of at the father. 我将事件onMouseUp onMouseMove分配给div而不是父亲。 Furthermore the father didn't have proper height and width due to the root div which hadn't any dimension. 此外,由于根div没有任何尺寸,父亲没有适当的高度和宽度。

The updated and working code is the following 更新后的工作代码如下

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'));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM