vue实现环形菜单
实现环形菜单的基本思路
环形菜单通常指围绕中心点呈环形排列的菜单项,点击后可能展开或触发动作。Vue 结合 CSS 可以实现这种效果,核心在于计算每个菜单项的位置角度。
基础实现步骤
HTML 结构
<template>
<div class="circle-menu">
<div class="menu-item" v-for="(item, index) in items" :key="index"
:style="getItemStyle(index)">
{{ item.label }}
</div>
</div>
</template>
CSS 样式

.circle-menu {
position: relative;
width: 300px;
height: 300px;
margin: 0 auto;
}
.menu-item {
position: absolute;
width: 60px;
height: 60px;
background: #42b983;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transform-origin: center;
}
Vue 计算位置
<script>
export default {
data() {
return {
items: [
{ label: 'A' },
{ label: 'B' },
{ label: 'C' },
{ label: 'D' }
],
radius: 100 // 环形半径
}
},
methods: {
getItemStyle(index) {
const angle = (index * 2 * Math.PI) / this.items.length;
const x = this.radius * Math.cos(angle);
const y = this.radius * Math.sin(angle);
return {
left: `calc(50% + ${x}px - 30px)`,
top: `calc(50% + ${y}px - 30px)`
};
}
}
}
</script>
动态展开效果
通过添加状态控制环形展开/收缩:

data() {
return {
isExpanded: false,
expandedRadius: 150,
collapsedRadius: 0
}
},
methods: {
toggleMenu() {
this.isExpanded = !this.isExpanded;
},
getCurrentRadius() {
return this.isExpanded ? this.expandedRadius : this.collapsedRadius;
}
}
动画优化
添加 CSS 过渡效果:
.menu-item {
transition: all 0.3s ease;
}
交互事件处理
为菜单项添加点击事件:
<div class="menu-item" @click="handleClick(item)">
{{ item.label }}
</div>
methods: {
handleClick(item) {
alert(`Selected: ${item.label}`);
}
}
完整组件示例
<template>
<div>
<button @click="toggleMenu">Toggle Menu</button>
<div class="circle-menu">
<div
v-for="(item, index) in items"
:key="index"
class="menu-item"
:style="getItemStyle(index)"
@click="handleClick(item)"
>
{{ item.label }}
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
items: [
{ label: 'Home' },
{ label: 'About' },
{ label: 'Services' },
{ label: 'Contact' }
],
isExpanded: false,
radius: 120
}
},
methods: {
toggleMenu() {
this.isExpanded = !this.isExpanded;
},
getItemStyle(index) {
const currentRadius = this.isExpanded ? this.radius : 0;
const angle = (index * 2 * Math.PI) / this.items.length;
const x = currentRadius * Math.cos(angle);
const y = currentRadius * Math.sin(angle);
return {
left: `calc(50% + ${x}px - 30px)`,
top: `calc(50% + ${y}px - 30px)`
};
},
handleClick(item) {
console.log('Selected:', item.label);
}
}
}
</script>
注意事项
- 调整
radius值控制环形大小 - 菜单项数量变化时需要重新计算角度
- 移动端可能需要增加触摸事件支持
- 考虑添加遮罩层提升用户体验
通过以上方法可以实现基础的环形菜单,更复杂的效果可以结合 SVG 或第三方动画库实现。






