✨ 手把手带大家绘制 QQ 弹弹的圆环菜单,学不会找我!

lxf2023-02-16 15:50:08

持续创作,加速成长!这是我参与「AdminJS日新计划 · 10 月更文挑战」的第27天,点击查看活动详情

前言

菜单是每个网站都有的功能,它可以帮助我们更快找到对应的功能。但是菜单想要做的特别做的好看,就需要下点功夫了,一步步带大家做一个环绕展开菜单的效果。

思路分析

接下来我们一步一步的分析环绕展开圆环菜单的实现过程。

准备图标

首先我们先将 8 个图标准备好,没有的不要怕,我放在后面 Github 小节里了,大家需要自取。

按钮

菜单分为主菜单以及子菜单,1 个大圆 + 8 个小圆,共 9 个圆。我们直接在正方形的基础上给个 border-radius: 50% 就可以实现圆形的效果了。

<div class="menu">
  <div class="toggle">+</div>
  <li style="--i: 0">
    <a href="#">
      <img src="./static/8.png" alt="" />
    </a>
  </li>
  <li style="--i: 1">
    <a href="#">
      <img src="./static/1.png" alt="" />
    </a>
  </li>
  <li style="--i: 2">
    <a href="#">
      <img src="./static/2.png" alt="" />
    </a>
  </li>
  <li style="--i: 3">
    <a href="#">
      <img src="./static/3.png" alt="" />
    </a>
  </li>
  <li style="--i: 4">
    <a href="#">
      <img src="./static/4.png" alt="" />
    </a>
  </li>
  <li style="--i: 5">
    <a href="#">
      <img src="./static/5.png" alt="" />
    </a>
  </li>
  <li style="--i: 6">
    <a href="#">
      <img src="./static/6.png" alt="" />
    </a>
  </li>
  <li style="--i: 7">
    <a href="#">
      <img src="./static/7.png" alt="" />
    </a>
  </li>
</div>

这里我们需要将 .menu 设置为相对定位 relative ,然后将小圆 li 设置为绝对定位 absolute,方便我们对按钮位置进行调整。

.menu {
    position: relative;
    width: 200px;
    height: 200px;
    display: flex;
    justify-content: center;
    align-items: center;
}
.menu li {
    list-style: none;
}

我们观察一下此时小按钮的排列情况:

✨ 手把手带大家绘制 QQ 弹弹的圆环菜单,学不会找我!

可以发现显然和我们的预期不太一致。

围绕主按钮

接下来我们要让小按钮们都绕着主按钮进行排列。具体怎么做呢?

首先我们将小圆点们都设置为 绝对定位

.menu li {
    position: absolute;
    left: 0;
}

✨ 手把手带大家绘制 QQ 弹弹的圆环菜单,学不会找我!

可以观察都此时所有小圆点都在起始位置。

我们知道,如果要让一个物体进行旋转,可以使用 transformrotate 属性。

那么每个圆应该旋转多少度呢?我们知道一周是有 360° ,那么我们有 8 个小圆,平均分应当每个圆的旋转角度是 360 / 8,也就是 45°,因此 rotate 的值为 calc(var(--i) * 45deg)

✨ 手把手带大家绘制 QQ 弹弹的圆环菜单,学不会找我!

可以发现旋转角度是有生效的,但是整体并没有如我们预期一样绕着主按钮排列。

这是因为 rotate 是围绕物体的原点作用的,圆的原点就是圆心,旋转的话它的位置必然是不变的。

为了让圆围绕着一个点进行旋转,我们需要改变所有圆的原点位置,让它们都围着这个原点进行旋转。

这里我们就要用到 transform-origin 属性了,这个属性可以 改变需要变换的元素的原点

我们将 transform-origin 的值设置为 100px 看看。

✨ 手把手带大家绘制 QQ 弹弹的圆环菜单,学不会找我!

此时就符合预期了。不过小圆点的图标也跟着旋转了,这是因为我们刚刚给 li 设置了 rotate ,为了将图标摆正,我们需要让 img 标签反方向旋转对应的角度,即 calc(var(--i) * -45deg)

✨ 手把手带大家绘制 QQ 弹弹的圆环菜单,学不会找我!

如此就符合预期了。

旋转动画

接下来我们要着手旋转动画了,小圆点们一开始是 “藏”在主按钮里面且没有围绕 的,这里我们可以使用 translateX负值 实现,同时我们要将 rotate 的值设置为 0,这样 8 个小圆点就都 在一起并且藏于主按钮身后。

.li {
    ...
    transform: rotate(0deg) translateX(80px);
}

在点击主按钮之后,小圆点会旋转并围绕在主按钮周围。我们可以使用一个 .active 类,在点击时将类名进行切换,切换前后分别是“围绕”以及“收缩”两个状态。围绕态我们要将 rotate 以及 translateX 的值恢复

.menu.active li {
    transform: rotate(calc(var(--i) * 45deg));
}

js 代码如下:

<script>
  const toggleBtn = document.querySelector(".toggle");
  const menu = document.querySelector(".menu");
  toggleBtn.onclick = () => {
    menu.classList.toggle("active");
  };
</script>

此时我们点击主按钮:

✨ 手把手带大家绘制 QQ 弹弹的圆环菜单,学不会找我!

可以发现所有小圆点都是一下子蹦出来的,我们给它们分别加点延迟效果试试:

.menu li {
    ...
    transition: 0.5s;
    transition-delay: calc(0.1s * var(--i));
}

✨ 手把手带大家绘制 QQ 弹弹的圆环菜单,学不会找我!

OK,大功告成!

Github 源码地址

关于本文的所有代码及素材,都已上传至 Github 仓库,小伙伴们有需要的自取:

juejin-demo/rotate-menu-demo at main · catwatermelon/juejin-demo (github.com)

结束语

本文就到此结束了,希望大家阅读本文能所收获。

如果小伙伴们有别的想法,欢迎留言,让我们共同学习进步