广告

HTML/CSS 实现可交互的六扇形环形菜单:完整教程与源码示例

1. 概要与实现思路

1.1 设计目标

在本文中,我们将展示如何使用 HTML/CSS 实现一个可交互的 六扇形环形菜单,以提升网页导航的直观性与美观度。核心目标是将 6 个等角扇区围绕圆心排布,提供悬停、聚焦与点击等交互效果,同时确保结构简洁、可维护。

该六扇形环形菜单的实现将以 HTML 标记、CSS 布局与过渡为基础,并辅以少量 JavaScript 逻辑,实现高亮、选中状态以及简单的子菜单触发展示。

2. 基础结构:HTML 构建

2.1 HTML 标记要点

要实现六扇形环形菜单,首先需要一个圆形容器来承载六个扇区按钮,确保可聚焦与可访问。圆心容器是整个布局的核心,内部 6 个扇区通过旋转角度来分布在圆周上。

每个扇区作为一个独立的按钮元素,便于键盘导航与屏幕阅读器使用。为后续美化与交互留出 自定义属性,如 --i 来标示扇区序号,以及颜色变量用于区分扇区。

为提升可访问性,我们在每个扇区按钮上使用 aria-labelrole="navigation",并确保键盘也能顺畅浏览六个扇区。

3. 样式设计:CSS 实现六扇形环形

3.1 形状与圆环的基础

核心技巧是用 CSS 的 conic-gradient 绘制扇区,并通过掩模实现内圆孔,形成环形效果。将每个扇区的角度通过 --i 变量控制,让六个扇区均匀分布在圆周上。

通过设置 transform-origin旋转缩放过渡,可以实现悬停放大、焦点突出等交互效果,同时保持整体的平滑性与响应性。

/* 示例:基础样式(简化版) */ 
:root {--ring-size: 420px;--inner-radius: 90px; /* 内孔半径,用于掩模实现环形 */--slice-color: #4f6fff;
}
.ring-menu {position: relative;width: var(--ring-size);height: var(--ring-size);margin: 40px auto;
}
.ring-menu .slice {position: absolute;inset: 0;border: 0;padding: 0;background: conic-gradient(from 0deg, var(--slice-color) 0 60deg, transparent 60deg 360deg);/* 掩模:保留环形的外圈,去掉中间圆 */-webkit-mask: radial-gradient(circle at center, transparent calc(var(--inner-radius) - 1px), black calc(var(--inner-radius) - 1px));mask: radial-gradient(circle at center, transparent calc(var(--inner-radius) - 1px), black calc(var(--inner-radius) - 1px));transform-origin: 50% 50%;/* 根据序号 i 旋转到正确的位置 */transform: rotate(calc(var(--i) * 60deg));display: grid;place-items: center;color: #fff;cursor: pointer;transition: transform 0.4s ease, filter 0.25s ease;
}
.ring-menu .slice:hover {transform: rotate(calc(var(--i) * 60deg)) scale(1.08);
}
.ring-menu .slice.active {filter: brightness(1.15);transform: rotate(calc(var(--i) * 60deg)) scale(1.12);
}
.ring-menu .slice-label {position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%) rotate(calc(-1 * var(--i) * 60deg));transform-origin: center;font-family: system-ui, -apple-system, "Segoe UI", Roboto;font-size: 14px;font-weight: bold;color: #ffffff;pointer-events: none;
}

3.2 完整的颜色与交互细化

为了让每个扇区更具辨识度,可以给不同扇区设置不同的颜色,通过 CSS 变量实现简单的渐变与风格切换。将每个扇区的颜色通过 style 或在 CSS 中按序设定即可。

在实际应用中,悬停与聚焦状态应具备明显的视觉反馈,例如放大、局部阴影或色彩增强,以提升可用性与可发现性。

/* 示例:每个扇区自定义颜色(可选) */ 
.slice[data-label="主页"] { --slice-color: #4f6fff; }
.slice[data-label="关于"] { --slice-color: #2ecc71; }
.slice[data-label="服务"] { --slice-color: #f39c12; }
.slice[data-label="作品"] { --slice-color: #9b59b6; }
.slice[data-label="案例"] { --slice-color: #e74c3c; }
.slice[data-label="联系"] { --slice-color: #16a085; }

4. 交互实现:鼠标悬停与点击

4.1 动画与选中逻辑

除了基础的悬停放大,六扇形环形菜单的交互还可以通过点击来设置 选中状态,并在 UI 上显示当前选中的扇区信息。下面的 JavaScript 逻辑实现了单选高亮和可访问性更新。

核心逻辑是遍历所有扇区,将点击的扇区标记为 active,移除其他扇区的 active 状态,同时更新 aria-pressed 等无障碍属性。

// 示例:简单的选中逻辑
const slices = document.querySelectorAll('.ring-menu .slice');
slices.forEach(btn => {btn.addEventListener('click', () => {slices.forEach(b => b.classList.remove('active'));btn.classList.add('active');btn.setAttribute('aria-pressed', 'true');});btn.addEventListener('keydown', (e) => {if (e.key === 'Enter' || e.key === ' ') {btn.click();e.preventDefault();}});
});

5. 无障碍与响应式设计

5.1 键盘导航与响应式考虑

一个优质的可访问性实现应确保屏幕阅读器用户与键盘导航用户也能顺畅使用该六扇形环形菜单。通过为每个扇区按钮提供 aria-labelaria-pressedtabindex,实现完整的无障碍体验。

此外,结合响应式布局,应该在不同屏幕尺寸下自动调整圆环尺寸与文本显示,确保在手机端也保持良好的触达与可读性。自适应单位(如 rem、vw/vh)和最小尺寸约束是关键。

/* 响应式调整示例:比例缩放圆环以适应屏幕宽度 */
@media (max-width: 720px) {:root { --ring-size: 320px; --inner-radius: 78px; }
}
@media (max-width: 420px) {:root { --ring-size: 280px; --inner-radius: 70px; }
}

6. 完整源码示例与自定义

6.1 完整源码片段

以下为一个可直接使用的完整示例,包含 HTML、CSS 与 JS,展示如何把上述要点整合为一个可运行的页面。你可以将其复制到一个新的 HTML 文件中,打开即可看到一个可交互的六扇形环形菜单。

HTML/CSS 实现可交互的六扇形环形菜单:完整教程与源码示例

<!doctype html>
<html lang="zh-CN">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>六扇形环形菜单:完整源码示例</title><style>:root{--ring-size: 420px;--inner-radius: 90px;--slice-color: #4f6fff;}body{ font-family: system-ui, -apple-system, "Segoe UI", Roboto; margin:0; padding:0; display:flex; align-items:center; justify-content:center; min-height:100vh; background:#111; color:#fff; }.ring-menu{ position: relative; width: var(--ring-size); height: var(--ring-size); }.ring-menu .slice{position: absolute; inset: 0; border:0; padding:0;background: conic-gradient(from 0deg, var(--slice-color) 0 60deg, transparent 60deg 360deg);-webkit-mask: radial-gradient(circle at center, transparent calc(var(--inner-radius) - 1px), black calc(var(--inner-radius) - 1px));mask: radial-gradient(circle at center, transparent calc(var(--inner-radius) - 1px), black calc(var(--inner-radius) - 1px));transform-origin: 50% 50%; transform: rotate(calc(var(--i) * 60deg));display: grid; place-items: center; cursor: pointer; transition: transform .4s ease, filter .25s ease;}.ring-menu .slice:hover{ transform: rotate(calc(var(--i) * 60deg)) scale(1.08); }.ring-menu .slice.active{ filter: brightness(1.15); transform: rotate(calc(var(--i) * 60deg)) scale(1.12); }.ring-menu .slice-label{ position: absolute; left:50%; top:50%; transform: translate(-50%, -50%) rotate(calc(-1 * var(--i) * 60deg)); font-weight: bold; font-size: 14px; color:#fff; pointer-events: none; }.ring-menu .slice:focus{ outline: 2px solid #fff; outline-offset: 2px; }@media (max-width: 720px){:root{ --ring-size: 320px; --inner-radius: 78px; }}@media (max-width: 420px){:root{ --ring-size: 280px; --inner-radius: 70px; }}</style>
</head>
<body>
<nav class="ring-menu" aria-label="六扇形环形菜单" role="navigation"><button class="slice" style="--i:0" aria-label="扇区 1" class="slice"><span class="slice-label">主页</span></button><button class="slice" style="--i:1" aria-label="扇区 2"><span class="slice-label">关于</span></button><button class="slice" style="--i:2" aria-label="扇区 3"><span class="slice-label">服务</span></button><button class="slice" style="--i:3" aria-label="扇区 4"><span class="slice-label">作品</span></button><button class="slice" style="--i:4" aria-label="扇区 5"><span class="slice-label">案例</span></button><button class="slice" style="--i:5" aria-label="扇区 6"><span class="slice-label">联系</span></button>
</nav><script>const slices = document.querySelectorAll('.ring-menu .slice');slices.forEach(btn => {btn.addEventListener('click', () => {slices.forEach(b => b.classList.remove('active'));btn.classList.add('active');btn.setAttribute('aria-pressed', 'true');});});
</script>
</body>
</html>

通过以上完整源码示例,你可以快速把现实世界中的 UI 需求落地为一个可交互的六扇形环形菜单。复制粘贴后即可在本地查看效果,并根据实际需求自定义颜色、文本与行为。

总结而言,本教程展示了如何用纯 HTML/CSS(配合少量 JavaScript)实现一个可交互的六扇形环形菜单。你可以将其嵌入到导航栏、仪表盘、数据可视化页面或移动端应用中,以提升用户体验和界面美感。关键点在于六扇区的等角分布、环形外观的实现、以及悬停/点击的清晰反馈,这些都是实现高质量前端交互组件的基石。