【问题标题】:Moving react-draggable to side of screen?将 react-draggable 移动到屏幕的一侧?
【发布时间】:2019-01-07 22:04:03
【问题描述】:

我有一个 react-draggable 组件,我希望它的行为类似于 assistive touch

我想在让动画工作之前,我只需要在用户放开拖动时将 x 位置设置为窗口的最左边或最右边,我尝试了以下操作:

import Draggable, { ControlPosition } from 'react-draggable'; // The default
import * as React from 'react';
import './style.less'

export default class FloatingScreenSpace extends React.Component<{}, {position:ControlPosition}> {
    state ={
        position: {x:90,y:0}
    }

    draggable: React.RefObject<Draggable> = React.createRef();

    onDragEnd = (e:MouseEvent)=>{
        if(this.draggable.current){
            this.setState({
                position:{
                    x: 0,
                    y: e.clientY
                }
            })
        }
    }

    public render() {
        return <Draggable position={this.state.position} ref={this.draggable} onStop={this.onDragEnd}>
            <div className="floatingActionButton" style={{ width: '100px', height: '100px' }}></div>
        </Draggable>
    }
}

我认为在 setState 函数中将 x 位置设置为 0 会将其设置为屏幕的最左侧,但是这并没有发生。事实上,它似乎根本没有影响。

理想情况下,当用户放手时,我希望将按钮动画到屏幕最近的边缘(上、下、左、右)。

【问题讨论】:

  • 它是否在无条件下工作 if(this.draggable.current)
  • @xadm 拖动工作正常,我只是不知道如何在停止拖动后使其动画到屏幕边缘
  • 我很确定拖动是有效的 - onDragEnd 会发生什么 - 有什么反应吗? setState 被执行了吗?
  • @tweetypi 你能检查一下我的实现吗?另外,如果您有任何问题,请随时提出。
  • @JordanEnev 我试过了,看起来它可以工作,但没有动画到屏幕边缘,而是捕捉它

标签: reactjs drag-and-drop


【解决方案1】:

onStop 处理程序中实现辅助触摸行为听起来不错。

请检查我的实现并遵循 cmets:

const Draggable = ReactDraggable

class Example extends React.Component {
  constructor(props) {
    super(props)
    
    this.state = { position: { x:0, y:0 }}
  }

  onStop(event, data) {
    // Viewport (wrapper)
    const documentElement = document.documentElement
    const wrapperHeight = (window.innerHeight || documentElement.clientHeight)
    const wrapperWidth = (window.innerWidth || documentElement.clientWidth)
    
    // Draggable element center coordinates (x,y)
    // Here we assume that the Draggable Button (from the question)
    // is a rectangle. But we can easily change it with whatever 
    // figure we want and fine-tune the calculation.
    // Credits: https://stackoverflow.com/a/18932029/4312466
    const center = { 
      x: data.x + (data.node.clientWidth / 2),
      y: data.y + (data.node.clientHeight / 2)
    }
    
    // The margin from the draggable's center,
    // to the viewport sides (top, left, bottom, right)
    const margin = {
      top: center.y - 0,
      left: center.x - 0,
      bottom: wrapperHeight - center.y,
      right: wrapperWidth - center.x
    }
    
    // When we get the nearest viewport side (below), then we can 
    // use these metrics to calculate the new draggable sticky `position`
    const position = {
      top: { y: 0, x: data.x },
      left: { y: data.y, x: 0 },
      bottom: { y: (wrapperHeight - data.node.clientHeight), x: data.x },
      right:  { y: data.y, x: (wrapperWidth - data.node.clientWidth)}
    }
   
    // Knowing the draggable's margins to the viewport sides,
    // now we can sort them out and get the smaller one.
    // The smallest margin defines the nearest viewport side to draggable.
    const sorted = Object.keys(margin).sort((a,b) => margin[a]-margin[b])
    const nearestSide = sorted[0]
    
    this.setState({ position: position[nearestSide] })
  }

  render() {
    return <Draggable
      position={this.state.position}
      onStop={(event, data) => this.onStop(event, data)}
      >
       <div className='handle'>Drag</div>
      </Draggable>
  }
}

ReactDOM.render(
  <Example />,
  document.getElementById('container')
)
body { 
  overflow-x: hidden; 
  overflow-y: hidden;
  padding: 0;
  margin: 0;
}

.handle {
  width: 40px;
  height: 40px;
  line-height: 40px;
  background-color: #2662c1;
  color: #fff;
  cursor: move;
  text-align: center;
}

.handle:not(.react-draggable-dragging) {
  -webkit-transition: -webkit-transform 0.5s ease-out; /* Safari */
  transition: transform 0.5s ease-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/react-draggable@3.0.5/dist/react-draggable.js"></script>

<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>

【讨论】:

  • 我对这个包做了很多工作,直到我意识到实现“可放置”空间的概念需要做多少工作。不过,这是一个很棒的实现。
  • 听到这个消息我真的很高兴!谢谢?
猜你喜欢
  • 1970-01-01
  • 2012-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 2020-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多