效果图
![在这里插入图片描述](https://img-blog.csdnimg.cn/1d2ad67b09d24d12bf5a856c4b41438c.png)
JS
import { useState } from 'react';
import styles from './style.less'
const menus = [
{
name: '文旅', id: 1, children: [
{ name: '住房服务', id: 1 },
{ name: '公共事业', id: 2 },
{ name: '社保服务', id: 3 },
]
},
{
name: '卫生', id: 2, children: [
{ name: '住房服务', id: 1 },
{ name: '公共事业', id: 2 },
{ name: '社保服务', id: 3 },
{ name: '就业服务', id: 4 },
{ name: '医疗服务', id: 5 },
{ name: '交通服务', id: 6 },
{ name: '证件办理', id: 7 },
{ name: '企业服务', id: 8 },
{ name: '自制服务', id: 9 },
{ name: '经营纳税', id: 10 },
{ name: '婚育收养', id: 11 },
]
},
{
name: '教育', id: 3, children: [
{ name: '住房服务', id: 1 },
{ name: '公共事业', id: 2 },
{ name: '社保服务', id: 3 },
{ name: '就业服务', id: 4 },
{ name: '住房服务', id: 1 },
{ name: '公共事业', id: 2 },
{ name: '社保服务', id: 3 },
{ name: '就业服务', id: 4 },
]
},
{
name: '科技', id: 4, children: [
{ name: '住房服务', id: 1 },
{ name: '公共事业', id: 2 },
]
},
{
name: '体育', id: 5, children: [
{ name: '住房服务', id: 1 },
]
},
{
name: '部件', id: 6, children: [
{ name: '住房服务', id: 1 },
{ name: '公共事业', id: 2 },
]
},
{ name: '资源', id: 7, children: [] },
{
name: '管理', id: 8, children: [
{ name: '住房服务', id: 1 },
{ name: '公共事业', id: 2 },
{ name: '社保服务', id: 3 },
{ name: '就业服务', id: 4 },
{ name: '医疗服务', id: 5 },
{ name: '交通服务', id: 6 },
{ name: '证件办理', id: 7 },
{ name: '企业服务', id: 8 },
{ name: '自制服务', id: 9 },
{ name: '经营纳税', id: 10 },
]
},
{
name: '应急', id: 9, children: [
{ name: '住房服务', id: 1 },
{ name: '公共事业', id: 2 },
{ name: '社保服务', id: 3 },
{ name: '就业服务', id: 4 },
{ name: '医疗服务', id: 5 },
{ name: '交通服务', id: 6 },
{ name: '证件办理', id: 7 },
{ name: '企业服务', id: 8 },
{ name: '自制服务', id: 9 },
]
},
{
name: '人口', id: 10, children: [
{ name: '住房服务', id: 1 },
{ name: '公共事业', id: 2 },
{ name: '社保服务', id: 3 },
{ name: '就业服务', id: 4 },
{ name: '医疗服务', id: 5 },
{ name: '交通服务', id: 6 },
{ name: '证件办理', id: 7 },
]
},
{
name: '民生', id: 11, children: [
{ name: '住房服务', id: 1 },
{ name: '公共事业', id: 2 },
{ name: '社保服务', id: 3 },
{ name: '就业服务', id: 4 },
{ name: '医疗服务', id: 5 },
{ name: '交通服务', id: 6 },
]
},
]
const index = () =>
{
const [menu, setMenu] = useState(menus[1])
const arrSort = (arrLength, i) =>
{
let result;
let median = arrLength / 2
if (median > i)
{
result = i + 1
} else if (median <= i)
{
result = arrLength - i
}
return result || i
}
const navClick = (menuObj) =>
{
setMenu(menuObj)
}
const calculated = () =>
{
let count = menu.children.length
return count >= 5 ? 15 : count >= 3 ? 30 : 15
}
let precession = 150
return (
<div className={styles.container}>
<div className={styles.menuLeft}>
{menu.children?.map((item, index) =>
{
console.log(arrSort(menu.children.length, index));
return <div style={{ marginLeft: precession - arrSort(menu.children.length, index) * calculated() }} className={styles.itemTitle}>
<a className={styles.rotateBtn}>{item.name}</a>
</div>
})}
</div>
<div className={styles.menuRight}>
<div className={styles.menuWarp}>
<ul>
{menus.map((data, index) => (
<li style={{ transform: `rotate(${360 / menus.length * index}deg) translateX(-110px)` }} key={index} className={`${styles.menu_item} ${styles.menu_item_active} `} >
<a
onClick={() => { navClick(data, 360 / menus.length * index) }}
className={styles.nav_item}
style={menu === data ? { color: '#fff', backgroundColor: 'rgb(19,103,225)', transform: `rotate(-${360 / menus.length * index}deg)`, transition: 'all 1s' } : { transform: `rotate(-${360 / menus.length * index}deg)`, transition: 'all 1s' }} >
<span> {data.name}</span>
</a>
</li>
))}
</ul>
</div>
</div>
<div className={styles.menuCore}></div>
</div>
);
};
export default index
CSS
.container {
position: relative;
width: 600px;
height: 600px;
border-radius: 50%;
background: url('https://www.dataojocloud.com/dataeye/v1/data/image/get?imageid=6390590722a0c64eebd2fd30') no-repeat;
background-size: 100% 100%;
.menuLeft {
display: flex;
position: relative;
flex-direction: column;
justify-content: space-between;
height: 100%;
padding: 50px 0;
.itemTitle {
position: relative;
font-size: 13px;
a {
color: #fff;
}
&::before {
content: "";
position: absolute;
left: -8px;
top: calc(40%);
background-color: yellow;
width: 5px;
height: 5px;
}
}
}
.menuRight {
position: absolute;
top: 50%;
left: 50%;
margin-top: -150px;
margin-left: -150px;
width: 300px;
height: 300px;
border-radius: 50%;
background: url('https://www.dataojocloud.com/dataeye/v1/data/image/get?imageid=6390590722a0c64eebd2fd30') no-repeat;
background-size: 100% 100%;
}
.menuCore {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgb(39, 175, 57);
background: url('https://www.dataojocloud.com/dataeye/v1/data/image/get?imageid=6390590a22a0c64eebd2fd31') no-repeat;
background-size: contain;
width: 150px;
height: 150px;
border-radius: 50%;
}
}
.menu_item {
position: absolute;
display: block;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
width: 60px;
height: 60px;
opacity: 0;
transition: 0.5s;
}
// 活跃按钮
.menu_item_active {
opacity: 1;
a {
pointer-events: auto;
}
}
.nav_item {
display: flex;
justify-content: space-evenly;
padding: 8px;
width: inherit;
height: inherit;
color: rgba(255, 255, 255, 0.7);
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
text-align: center;
text-decoration: none;
font-size: 16px;
transition: 0.2s;
font-weight: 700;
align-items: center;
}
.menu_item a:hover {
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
color: #fff;
background: rgba(255, 255, 255, 0.3);
// font-size: 45px;
font-size: 16px;
}