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

标签 javascript css reactjs draggable

我一直在尝试在 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/

相关文章:

css - ASP.NET 内部样式不知从何而来

javascript - 每次单击 li 的一部分时,href 都不会加载链接。使用javascript使整个li可点击

javascript - JavaScript 代码中的函数或事件问题

javascript - 在 React-Boilerplate 中使用 Firebase 身份验证时,服务工作线程捕获对 Google 的 __/auth 请求

reactjs - 如何在 React 中创建可重用的自定义模态组件?

javascript - ExtJS 容器将现有内容设置为项目

javascript - 仅在需要时加载 JavaScript(点击时)

php - Facebook access_token 无效

javascript - Rails - 想要将文本字段/select_tags 灰显并仅通过复选框启用

html - React 中的自动完成 ="current-password"未显示填写表单