Элемент перестает перетаскивать, когда курсор покидает область div реагирует - PullRequest
0 голосов
/ 11 апреля 2019

Я пытался реализовать перетаскиваемый 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, и он будет работать, чтобы вы могли попробовать. Любой совет приветствуется!

Ссылка на стек: https://stackblitz.com/edit/react-draggable-test-oezlsk

1 Ответ

0 голосов
/ 11 апреля 2019

Хорошо, обнаружил проблему.Я назначал событие 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'));
...