需求: 实现一个弧形的菜单栏,并将激活的菜单项移动到中间位置,点击按钮可对该菜单栏进行显示隐藏。
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. 参考文档
忘了。
网友评论