Html+Css+JS实现悬浮球移动+吸附+菜单效果

Css

    :root {
      --item-translateX: -100px;
    }

    /* * {
      margin: 0;
      padding: 0;
    } */

    /* body,
    html {
      width: 100%;
      height: 100%;
    } */

    /* body {
      background: linear-gradient(rgb(35, 189, 236), rgb(45, 99, 248));
    } */

    .boxButton+.circular,
    .boxButton+.circular+.fork,
    .boxButton,
    .box-item {
      position: absolute;
      top: 200px;
      right: -20px;
    }

    .boxButton {
      display: block;
      width: 40px;
      height: 40px;
      z-index: 2;
      opacity: 0;
      cursor: pointer;
    }

    .boxButton+.circular {
      width: 30px;
      height: 30px;
      display: block;
      z-index: 1;
      border-radius: 50%;
      /* 控制中心圆圈 */
      border: 5px solid rgba(255, 255, 255, 0.7);
      /* 圆圈中心颜色 */
      /* background: rgba(255, 255, 255, 0.2); */
      background-color: blueviolet;
      /* 外围光圈阴影 */
      box-shadow: 0px 0px 0px 10px rgba(255, 255, 255, 0.2);
      margin: 10px;
      /* 过渡 */
      transition: all 0.5s;
      transform-origin: 50% 50%;
    }

    .boxButton:checked+.circular+.fork {
      width: 40px;
      height: 40px;
      display: block;
      z-index: 1;
      border-radius: 50%;
      /* 控制另一个交互颜色*/
      /* background: rgba(255, 255, 255, 0.2); */
      background-color: blue;
      /* 另外一个周围阴影颜色效果 */
      box-shadow: 0px 0px 0px 10px rgba(255, 255, 255, 0.2);
      margin: 10px;
      /* 过渡 */
      transition: all 0.5s;
    }

    /* 中心的X */
    .boxButton:checked+.circular+.fork::after,
    .boxButton:checked+.circular+.fork::before {
      content: "";
      width: 30px;
      height: 3px;
      display: block;
      z-index: 1;
      border-radius: 2.5px;
      background: rgba(255, 255, 255, 0.7);
      transition: all 0.5s;
      content: "";
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }

    /* 旋转效果 点击后里面按钮 */
    .boxButton:checked+.circular+.fork {
      transform: rotate(360deg);
    }

    /* 中间×的位置变化 */
    .boxButton:checked+.circular+.fork::after {
      transform: translate(-50%, -50%) rotate(45deg);
    }

    /* 中间×的位置变化 */
    .boxButton:checked+.circular+.fork::before {
      transform: translate(-50%, -50%) rotate(-45deg);
    }


    .boxButton:checked+.circular {
      width: 0;
      height: 0;
      border: 0px;
      box-shadow: none;
    }

    .boxButton:checked~ul .box-item {
      opacity: 1;
    }

    .box-item:nth-child(1) {
      transform: rotate(90deg);
    }


    .box-item:nth-child(2) {
      transform: rotate(45deg);
    }

    .box-item:nth-child(3) {
      transform: rotate(0deg);
    }

    .box-item:nth-child(4) {
      transform: rotate(315deg);
    }

    .box-item:nth-child(5) {
      transform: rotate(270deg);
    }


    .box-item:nth-child(1) a {
      transform: rotate(0deg);
    }

    .box-item:nth-child(2) a {
      transform: rotate(-45deg);
    }

    .box-item:nth-child(3) a {
      transform: rotate(0deg);
    }

    .box-item:nth-child(4) a {
      transform: rotate(45deg);
    }

    .box-item:nth-child(5) a {
      transform: rotate(90deg);
    }

    /* 可控制按钮分布 */
    .boxButton1:checked~ul .box-item:nth-child(1) {
      /* 更改rotate值控制按钮散波方向 */
      transform: rotate(45deg) translateX(var(--item-translateX));
    }

    .boxButton1:checked~ul .box-item:nth-child(2) {
      transform: rotate(0deg) translateX(var(--item-translateX));
    }

    .boxButton1:checked~ul .box-item:nth-child(3) {
      transform: rotate(-45deg) translateX(var(--item-translateX));
    }

    /* .boxButton:checked~ul .box-item:nth-child(4) {
      transform: rotate(315deg) translateX(var(--item-translateX));
    }

    .boxButton:checked~ul .box-item:nth-child(5) {
      transform: rotate(270deg) translateX(var(--item-translateX));
    } */

    .boxButton:checked~ul .box-item a {
      pointer-events: auto;
    }

    .boxButton+.circular::before {
      top: 10px;
    }

    .boxButton+.circular::after {
      top: -10px;
    }

    .box-item {
      display: block;
      width: 60px;
      height: 60px;
      opacity: 0;
      transition: 0.5s;
    }

    .box-item a {
      display: block;
      width: inherit;
      height: inherit;
      line-height: 60px;
      /* 过渡显示颜色 */
      /* color: rgba(255, 255, 255, 0.7); */
      color: brown;
      /* background: rgba(255, 255, 255, 0.2); */
      /* 标签背景颜色 */
      background-color: yellow;
      border-radius: 50%;
      text-align: center;
      text-decoration: none;
      font-size: 30px;
      pointer-events: none;
      transition: 0.2s;
    }

    .touming {
      opacity: 0.3;
    }

    .xuanfu {
      position: absolute;
    }

    .boxButton2:checked~ul .box-item:nth-child(1) {
      /* 更改rotate值控制按钮散波方向 */
      transform: rotate(135deg) translateX(var(--item-translateX));
    }

    .boxButton2:checked~ul .box-item:nth-child(2) {
      transform: rotate(180deg) translateX(var(--item-translateX));
    }

    .boxButton2:checked~ul .box-item:nth-child(3) {
      transform: rotate(225deg) translateX(var(--item-translateX));
    }

    /* .box-button1:checked~ul .box-item:nth-child(4) {
      transform: rotate(315deg) translateX(var(--item-translateX));
    }

    .box-button1:checked~ul .box-item:nth-child(5) {
      transform: rotate(270deg) translateX(var(--item-translateX));
    } */

Html

<div class="box xuanfu touming">
    <input type="checkbox" class="boxButton " id="box-buttons" />
    <label class="circular" for="box-buttons"></label>
    <label class="fork" for="box-buttons"></label>
    <ul>
      <li class="box-item">
        <a href="#"><i class="fa fa-square-o"></i></a>
      </li>
      <li class="box-item">
        <a href="#"><i class="fa fa-bars"></i></a>
      </li>
      <li class="box-item">
        <a href="#"><i class="fa fa-lock"></i></a>
      </li>
      <!-- <li class="box-item">
        <a href="#"><i class="fa fa-crop"></i></a>
      </li> -->
      <!-- <li class="box-item">
        <a href="#"><i class="fa fa-commenting-o"></i></a>
      </li> -->
    </ul>
  </div>

JS部分

// 获取元素的对象
    const xuanfu = document.querySelector('.xuanfu')
    const boxButton = document.querySelector('.boxButton')
    // console.log(xuanfu)
    // console.log(boxButton)

    //绑定事件触摸
    xuanfu.addEventListener('touchstart', function (e) {
      // 获取元素当前距离左侧的偏移量
      this.l = this.offsetLeft
      // 获取触摸开始时 触摸点距离左侧的偏移量
      this.x = e.targetTouches[0].clientX

      // 获取元素当前距离顶侧的偏移量
      this.t = this.offsetTop
      // 获取触摸开始时 触摸点距离顶侧的偏移量
      this.y = e.targetTouches[0].clientY

      // 使其不透明
      this.classList.remove('touming')
      // 清空定时器
      clearTimeout(this.timer)
    })
    xuanfu.addEventListener('touchmove', function (e) {
      // 获取触摸移动后,触摸点距离左侧的偏移
      this._x = e.targetTouches[0].clientX
      // 计算最终的left
      let newLeft = this._x - (this.x - this.l);
      // console.log(newLeft)
      // 判断
      if (newLeft <= 0) newLeft = 0
      if (newLeft >= document.documentElement.clientWidth - this.offsetWidth) {
        newLeft = document.documentElement.clientWidth - this.offsetWidth
      }


      // 获取触摸移动后,触摸点距离左侧的偏移
      this._y = e.targetTouches[0].clientY
      // 计算最终的left
      let newTop = this._y - (this.y - this.t);
      // console.log(newTop)
      // 判断
      if (newTop <= 0) newTop = 0
      if (newTop >= document.documentElement.clientWidth - this.offsetHeight) {
        newTop = document.documentElement.clientWidth - this.offsetHeight
      }
      // 设置样式
      this.style.left = newLeft + 'px'
      this.style.top = newTop + 'px'
    })
    xuanfu.addEventListener('touchend', function (e) {
      // 增加过渡效果
      this.style.transition = 'none'

      // 吸附效果
      // 计算居中状态下left值
      this.middle = (document.documentElement.clientWidth - this.offsetWidth) / 2
      // console.log(middle)
      //计算
      this.left = this.offsetLeft
      // console.log(left)

      // 声明变量 存放最终的left值
      let newLeft
      //判断
      if (this.left <= this.middle) {
        newLeft = 0
      } else {
        newLeft = document.documentElement.clientWidth - this.offsetWidth
      }
      // 设置
      this.style.left = newLeft + 'px'
      // 启动定时器,使其变成透明的
      this.timer = setTimeout(() => {
        this.classList.add('touming')
      }, 2000)
    })
    boxButton.addEventListener('click', function (e) {
      console.log(e)
      // console.log(this.Left)
      let res = (document.documentElement.clientWidth) / 2
      console.log(res)
      if (e.clientX <= res) {
        this.classList.add('boxButton2')
      } else {
        this.classList.remove('boxButton2')
        this.classList.add('boxButton1')
      }
    })

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值