我有一个反应可拖动的组件,我想表现得像 assistive touch 我想在让动画工作之前我只需要在用户放开拖动时将x位置设置为窗口的左侧或右侧,我尝试了以下操作: import Draggable, { ControlPos
我想在让动画工作之前我只需要在用户放开拖动时将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,它会将它设置到屏幕的最左侧,但是没有发生.事实上它似乎没有任何影响.
理想情况下,当用户放开时,我想将按钮设置为屏幕最近边缘(顶部,底部,左侧,右侧)的动画.
在onStop处理程序中实现辅助触摸行为听起来是一个很好的方法.请检查我的实施并遵循评论:
const Draggable = ReactDraggable class Example extends React.Component { constructor(props) { super(props) this.state = { position: { x:0, y:0 }} } onStop(event, data) { // Draggable element bounding const bounding = data.node.getBoundingClientRect() // 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="http://img.558idc.com/uploadfile/allimg/210610/23361V949-2.jpg"></script> <div id="container"> <!-- This element's contents will be replaced with your component. --> </div>