想问一下关于react实现面板拖曳的功能

想问一个最基本的react实现拖曳面板的实现~
有一个add的button,鼠标点击之后会弹出新面板,这个面板是通过绝对定位每次都定位在同一位置上的,想实现鼠标点击这个面板之后的拖曳效果,
我的实现思路大概就是监听onmousedown,onmousemove和onmouseup,然后用一个flag,先点击,获取到点击时的鼠标的坐标,将flag设为true,然后在mousemove的时候将每一次的位置给styleObj,最后mouseup的时候将flag设为false,

实现拖曳的效果貌似也不太对。。不太平滑,而且有时候方向是反的,可是我计算这个styleObj的left和top属性值应该没错(move的clientX-点击时得到的clientX+原始的left值)。

var index=0;
class Panel extends React.Component{
  constructor (props){
    super(props);
    this.state={
      styleObj:{
        top: 100,
        left:100
      },
      mouseXY:{
        //这个获取的是每一次点击panel时的鼠标的坐标
        x: 0,
        y: 0
      },
      isTouch:false
    };
   this.handleMouseDown = this.handleMouseDown.bind(this);
   this.handleMouseMove = this.handleMouseMove.bind(this);
   this.handleMouseUp = this.handleMouseUp
  }
  handleMouseDown(e){
    //获取当前鼠标按下的位置,并把它放到stat里面去,并且要设置一个flag,使得只有触发了点击,才会 
    console.log(e.clientX);
    this.setState(
      {
      isTouch:!this.state.isTouch,
      mouseXY:{
        x:e.clientX,
        y:e.clientY
      }
      },function(){
        //callback,只有在上面改完才执行
        this.printInfo();
      }
    );
  }
  printInfo(){
    console.log(this.state.mouseXY.x); //输出此时的mouseXY的x
    console.log(this.state.isTouch); //输出true
  }
  handleMouseMove(e){
    //先判断是否已点击,然后再需要让这个panel的x,y随滑动的位置发生相应的改变
    if(this.state.isTouch){
      this.setState({
      styleObj:{
         left:this.state.styleObj.left+e.clientX-this.state.mouseXY.x,
         top:this.state.styleObj.top+e.clientY-this.state.mouseXY.y,
      }
     })
    }
 }
  handleMouseUp(e){
    this.setState({
      isTouch:!this.state.isTouch
    })
  }
  render(){
    return (
    <div className="box" style={this.state.styleObj} onMouseDown={this.handleMouseDown} onMouseMove={this.handleMouseMove} onMouseUp={this.handleMouseUp}></div>
    )
  }
}
class App extends React.Component{
 constructor(props){
   super(props);
   this.state={listitem:[]};
   this.handleClick = this.handleClick.bind(this);
 }
  handleClick() {
    index++;
    this.setState({
      listitem :this.state.listitem.concat(<Panel key={index}>{index}</Panel>)
    });
 }
 render(){
  return (
   <div>
   <button onClick={this.handleClick}>
       Add
   </button>
   <div>
     {this.state.listitem}   
   </div>   
  </div>
 )
 }
}
ReactDOM.render(
  <App />,
  document.getElementById('root')
);

在第一条评论下面的是我修改之后不会有bug的,想问下这两者的区别是什么~因为貌似给left和top的数值都是一样的啊

阅读 2.5k
2 个回答
var index=0;
class Panel extends React.Component{
  constructor (props){
    super(props);
    this.state={
      styleObj:{
        top: 100,
        left:100
      },
      mouseXY:{
        //这个获取的是每一次点击panel时的鼠标在panel内的相对距离
        disX: 0,
        disY: 0
      },
      isTouch:false
    };
   this.handleMouseDown = this.handleMouseDown.bind(this);
   this.handleMouseMove = this.handleMouseMove.bind(this);
   this.handleMouseUp = this.handleMouseUp.bind(this);
  }
  handleMouseDown(e){
    //获取当前鼠标按下的位置,并把它放到stat里面去,并且要设置一个flag,使得只有触发了点击,才会 
    console.log(e.clientX);
    this.setState(
      {
      isTouch:!this.state.isTouch,
      mouseXY:{
        disX:e.clientX-this.state.styleObj.left,
        disY:e.clientY-this.state.styleObj.top
      }
      },function(){
        //callback,只有在上面改完才执行
        this.printInfo();
      }
    );
  }
  printInfo(){
    console.log(this.state.mouseXY.x); //输出此时的mouseXY的x
    console.log(this.state.isTouch); //输出true
  }
  handleMouseMove(e){
    //先判断是否已点击,然后再需要让这个panel的x,y随滑动的位置发生相应的改变
    const prevL=this.state.styleObj.left;
    const prevT=this.state.styleObj.top;
    // console.log('之前的'+prevL);
    // console.log(e.clientX+' '+this.state.mouseXY.x);
    if(this.state.isTouch){
      this.setState({
      styleObj:{
         left:e.clientX-this.state.mouseXY.disX,
         top:e.clientY-this.state.mouseXY.disY,
      }
     })
    }
 }
  handleMouseUp(e){
    this.setState({
      isTouch:!this.state.isTouch
    })
  }
  render(){
    return (
    <div className="box" style={this.state.styleObj} onMouseDown={this.handleMouseDown} onMouseMove={this.handleMouseMove} onMouseUp={this.handleMouseUp}></div>
    )
  }
}
class App extends React.Component{
 constructor(props){
   super(props);
   this.state={listitem:[]};
   this.handleClick = this.handleClick.bind(this);
 }
  handleClick() {
    index++;
    this.setState({
      listitem :this.state.listitem.concat(<Panel key={index}>{index}</Panel>)
    });
 }
 render(){
  return (
   <div>
   <button onClick={this.handleClick}>
       Add
   </button>
   <div>
     {this.state.listitem}   
   </div>   
  </div>
 )
 }
}
ReactDOM.render(
  <App />,
  document.getElementById('root')
);

如果是用在正式项目的话,蚂蚁金服出的动画解决方案了解一下,点击传送

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题