美文网首页
vue实现弧形菜单栏

vue实现弧形菜单栏

作者: 橙子只过今天 | 来源:发表于2022-07-04 16:29 被阅读0次

需求: 实现一个弧形的菜单栏,并将激活的菜单项移动到中间位置,点击按钮可对该菜单栏进行显示隐藏。

1. 实现效果

菜单显示
菜单隐藏

2. 实现原理

按照圆环弧度计算每个菜单项应该分布的位置并进行设置,在点击菜单项时更新菜单的起始角度,重新进行分布。

3. 实现代码

<template>
<div class="circle-menu-box">
  <span v-if="showMenu" class="iconfont iconarrow-left" @click="onHiddenMenu"></span>
  <span v-else class="iconfont iconarrow-right" @click="onShowMenu"></span>
  <div class="circle" :style="`width:${circleInfo.circle_w}px;height:${circleInfo.circle_h}px`">
    <div
    class="origin"
    :style="`width:${circleInfo.box_w}px;transform: rotate(${circleInfo.stard}deg);visibility: ${showMenu ? 'visible':'hidden'}`"
    >
      <div
          :style="`width:${circleInfo.box_w}px;transform: rotate(${-circleInfo.stard}deg);`"
          class="img-box"
          v-for="(item, index) in menus"
          :key="index"
          @click="Turn(index)"
        >
          <div :class="['circle-content-box', circleInfo.activeIndex === index ? 'box-active':'']">
              <div class="content">{{ item.name }}</div>
          </div>
        </div>
      </div>
    </div>
</div>
  
</template>
    
<script setup>
import {reactive,ref, onMounted, nextTick} from 'vue'

let showMenu = ref(true) // 是否显示菜单
let menus = reactive([ // 菜单项
        { name: '菜单一'},
        { name: '菜单二'},
        { name: '菜单三'},
        { name: '菜单四'},
        { name: '菜单五'},
        { name: '菜单六'},
        { name: '菜单七'},
        { name: '菜单八'},
        { name: '菜单九'},
        { name: '菜单十'},
        { name: '菜单十一'},
      ])
let circleInfo = reactive({ // 圆形框架的数据
    circle_w: 1300, //圆盘的宽
    circle_h: 1300, //圆盘的高
    box_w: 300, //圆盘上覆盖的小圆点宽
    PI: 90, //分布角度,默认为360deg
    stard: -50, //起始角度
    stard_s: -50, //用来默认储存第一个初始值
    boxNum: 10, //圆盘上覆盖的小圆点个数
    descTitle: "", //模块描述标题
    descContent: "", //模块描述内容
    activeIndex: 0, //默认激活项
})

onMounted(() => {
  circleInfo.activeIndex = Math.floor(menus.length / 2) // 默认激活中间项
  init()
  Turn(circleInfo.activeIndex)
})

/**
 * 初始化项目,根据计算使其分布到对应位置
 **/
const init = () => {
    let box = document.querySelectorAll(".img-box");
    let avd = circleInfo.PI / box.length; //每一个 菜单项 对应的角度
    let ahd = (avd * Math.PI) / 180; //每一个 菜单项 对应的弧度
    let radius = (circleInfo.circle_w + 320) / 2; //圆的半径
    for (let i = 0; i < box.length; i++) {  // 给菜单项定位
      box[i].style.left = (Math.sin(ahd * i) * radius) + "px";
      box[i].style.top = (Math.cos(ahd * i) * radius)+ "px";
    }
}

/** 
 * 点击菜单项,圆盘进行相对应角度的转动
 **/
const Turn = (index = 0) => {
    let bx = document.querySelectorAll(".circle-content-box");
    circleInfo.activeIndex = index

    let deg = (10 - index) * 10 // 改变起始角度
    circleInfo.stard = - deg
    nextTick(() => {
      init()
    })
}

/**
 * 隐藏菜单
 */
const onHiddenMenu = () => {
  showMenu.value = false
  let boxDom = document.querySelector('.circle-menu-box')
  boxDom.style.left = '-31%'
}

/**
 * 显示菜单
 */
const onShowMenu = () => {
  showMenu.value = true
  let boxDom = document.querySelector('.circle-menu-box')
  boxDom.style.left = '-28%'
  init()
}

</script>
    
<style lang="scss"  scoped>
.circle-menu-box {
  position: absolute; //注释--------------------------此处显示全圆
  // overflow: hidden; //注释----------------------此处显示全圆
  left: -28%; //注释---------------------此处显示全圆
  top: 50%;
  transform: translateY(-50%);
  transition: 0.5s;

  .iconfont {
    position: absolute;
    top: 50%;
    font-size: 50px;
    transform: translateX(-50%);
    color:  #86E7FF;
    cursor: pointer;
    z-index: 15;
  }

  .iconarrow-left {
    right: 5%;
  }

  .iconarrow-right {
    right: 0;
  }

  .circle {
    // transform: scale(0.9);
    width: 100%;
    height: 90%;
    border-radius: 50%;
    box-sizing: border-box;
    // border: 1px solid #4d4c4c;
    box-shadow: 0 0 8px #DDD;
    -moz-box-shadow: 0 0 8px #DDD;
    -webkit-box-shadow: 0 0 8px #DDD;
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    // margin-right: 50%; //注释----------------此处显示全圆
    background: linear-gradient(90deg, rgba(178, 243, 254, 0) 0%, rgba(178, 243, 254, 0) 0%, rgba(142, 233, 253, 0) 54%,
     rgba(142, 233, 253, 0) 80%, rgba(123, 228, 252, 0.2) 100%);
    border: 4px solid rgba(123, 228, 252, 1);

    .origin {
      position: relative;
      transition: 0.5s; //控制圆盘的的旋转速率
      .img-box {
        position: absolute;
        top: 0;
        left: 0;
        .circle-content-box {
          width: 100%;
          height: 100%;
          cursor: pointer;
          overflow: hidden;
          
          .content {
           font-size: 28px;
            font-family: SourceHanSansCN-Medium, SourceHanSansCN;
            font-weight: 500;
            color: #C6DAED;
          }
        }
        .box-active {

          .content {
           font-size: 38px;
            font-family: SourceHanSansCN-Bold, SourceHanSansCN;
            font-weight: bold;
            color: #7BE4FC;
          }
        }
      }
    }
  }
}
</style>

4. 参考文档

忘了。

相关文章

  • vue实现弧形菜单栏

    需求: 实现一个弧形的菜单栏,并将激活的菜单项移动到中间位置,点击按钮可对该菜单栏进行显示隐藏。 1. 实现效果 ...

  • vue+element ui 实现菜单无限极分类

    需后端返回数据结构如下: 后端实现方法可参考: 菜单栏数据递归实现 新建MenuBar.vue文件,实现获取后端数...

  • vue实现文字平滑弯曲弧形效果

    项目中有一个功能,需要将文字实现这种弯曲的弧形效果感觉好麻烦,终于找到了这个超级赞的工具arctext 第一步:安...

  • Flutter 布局聊天列表页及网络数据处理

    下拉菜单栏实现 如图所示,实现这种菜单栏我们可以使用 Flutter 提供的部件 PopupMenuButton ...

  • css3的一些简单效果笔记

    1 用css实现一段弧形 主要是利用border-radius的一个方向 2 用css实现一段半圆 3弧形 4椭圆...

  • css实现漂亮弧形

    在实现页面五花八门的有特色的ui时,我们有时会遇到要用实现一个弧形,而这样的弧形要怎么实现呢?用图片?好像不大现实...

  • css 伪类实现弧形

    在实现页面五花八门的有特色的ui时,我们有时会遇到要用实现一个弧形,而这样的弧形要怎么实现呢?用图片?好像不大现实...

  • PageMenu分页控制器(优化篇)-PageMenu复用

    备注:本文是在使用PageMenu实现顶部滑动菜单栏的基础上进行封装优化,实现顶部滑动菜单栏PageMenu的复用...

  • vue实现侧边折叠菜单栏手风琴效果

    在我们做管理后台亦或是产品流程时,总是需要一个菜单栏或者导航栏来架起我们的产品架构,那么,如何用vue实现侧边折叠...

  • echarts 实现环形图渐变

    echarts 原生是不支持弧形渐变的,本文只是取巧,利用线性渐变 linear 实现视觉上的弧形渐变。适用于以弧...

网友评论

      本文标题:vue实现弧形菜单栏

      本文链接:https://www.haomeiwen.com/subject/dkidbrtx.html