react实现pc端页面拖拽

拖拽 = 鼠标按下 + 鼠标移动 + 鼠标弹上

这样就完成了一个拖拽任务,想实现拖拽,自然实现上面的3个动作,便可以模拟拖拽效果,对应JavaScript中的语法就是需要实现这3个动作:

onmousedown , onmousemove , onmouseup

import React, { useEffect, useState } from 'react';
import './window.less';

export default function Page() {
  let [act, setact] = useState(-1);
  let [menu, setmenu] = useState(false);
  let [visiable, setvisiable] = useState(false);

  let [img, setimg] = useState(0);

  const drag = () => {
    //获取对应的节点信息
    let target: any = document.querySelector(".modal");
    let context = document.querySelector(".context");
    //鼠标按下以后
    target.onmousedown = function (event: any) {
      var event = event || window.event;//兼容性的写法
      //获取鼠标当前的坐标值:
      var X1 = event.clientX;
      var Y1 = event.clientY;

      //获取盒子的偏倚位置
      var L = target.offsetLeft; //左偏倚的内容
      var T = target.offsetTop;//上面的偏倚值内容
      console.log("坐标值", X1, Y1)
      console.log("偏移值:", L, T);

      //开始移动鼠标
      document.onmousemove = function (event) {
        //获取鼠标当前的坐标值:
        var X2 = event.clientX;
        var Y2 = event.clientY;

        //移动盒子的位置
        target.style.left = X2 - X1 + L + "px";
        target.style.top = Y2 - Y1 + T + "px";
      }

      document.onmouseup = function(){
        document.onmousemove = null;
      }
    }
  }

  useEffect(() => {
    drag();//调用方法
  })

  return (
    <div className='window' style={{ backgroundImage: 'url(/imgs/wall-' + img + '.jpg)' }} onClick={() => {
      setact(-1);
      setmenu(false);
    }}>
      <div className="content">
        <div className={act === 1 ? 'icon act' : 'icon'} onClick={(event) => { event.stopPropagation(); setact(1) }} onDoubleClick={(event) => { event.stopPropagation(); setvisiable(true) }}>
          <img src="/imgs/skin.png" />
          <p>换肤</p>
        </div>
        <div className={act === 2 ? 'icon act' : 'icon'} onClick={(event) => { event.stopPropagation(); setact(2) }}>
          <img src="/imgs/2.png" />
          <p>浏览器</p>
        </div>
      </div>
      {/* 模态框的操作 */}
      <div className='modal' style={{ display: visiable ? "block" : "none" }}>
        <header><span>换皮肤</span> <span style={{ float: "right", fontSize: "20px", color: "#FFF" }} onClick={() => setvisiable(false)}>X</span></header>
        <div className='context' style={{ backgroundImage: 'url(/imgs/wall-' + img + '.jpg)' }}>
          <img src='/imgs/wall-0.jpg' onClick={() => setimg(0)} />
          <img src='/imgs/wall-1.jpg' onClick={() => setimg(1)} />
          <img src='/imgs/wall-2.jpg' onClick={() => setimg(2)} />
        </div>
      </div>

      <div className="task">
        <div className='menu'>
          {
            menu ?
              <div className='menu-list'>
                <img src="/imgs/1.png" />
              </div>
              :
              <></>
          }
          <img src="/imgs/Windows.png" onClick={(e) => { e.stopPropagation(); setmenu(true) }} />
        </div>
      </div>
    </div>
  );
}

如果页面上有文字的话,拖拽物体会将文字选中,这效果岂不是怪怪的,没错,这是因为拖拽的时候触发了浏览器的默认选择事件,所以,在拖拽的时候,我们要清除这个默认事件 e.stopPropagation() 

window.less

.window {
    width: 100vw;
    height: 100vh;
    background-repeat: no-repeat;
    cursor: pointer;
  
    .content {
      width: 100vw;
      height: 100vh;
  
      .icon {
        width: 120px;
        text-align: center;
        position: absolute;
        left: 20px;
  
        img {
          width: 60px;
        }
  
        p {
          color: #FAFAFA;
          text-align: center;
          line-height: 30px;
        }
      }
  
      .icon:nth-child(1) {
        top: 30px;
      }
  
      .icon:nth-child(2) {
        top: 150px;
      }
  
      .icon.act {
        background: rgba(50, 50, 50, .8);
      }
    }
  
    .modal {
      width: 500px;
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      box-shadow: 1px 3px 5px #333;
  
      header {
        width: 100%;
        height: 40px;
        background: #008800;
      }
  
      .context {
        width: 100%;
        height: 300px;
        background-repeat: no-repeat; 
        img {
          width: 100px;
        }
      }
  
    }
  
    .task {
      width: 100vw;
      background: #303030;
      position: fixed;
      bottom: 0px;
      box-sizing: border-box;
      padding: 10px;
  
      .menu {
        position: relative;
  
        .menu-list {
          width: 20vw;
          height: 35vh;
          background: #345;
          position: absolute;
          bottom: 70px;
          left: -10px;
          box-shadow: 1px 3px 5px #333;
          border-top-right-radius: 10px;
          transition: all 1s ease;
        }
      }
  
      img {
        height: 60px;
      }
    }
  }

页面效果

拖拽是对中间的div盒子进行拖拽的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值