效果图

JS
import {
useState } from 'react';
import styles from './style.less'
import pu from '@/assets/common/pu.png'
import itemImg from '@/assets/common/item.png'
import itemActiveImg from '@/assets/common/itemActive.png'
import gl from '@/assets/common/gl.png'
import jy from '@/assets/common/jy.png'
import kj from '@/assets/common/kj.png'
import ms from '@/assets/common/ms.png'
import ty from '@/assets/common/ty.png'
import wgbj from '@/assets/common/wgbj.png'
import wgll from '@/assets/common/wgll.png'
import wl from '@/assets/common/wl.png'
import ws from '@/assets/common/ws.png'
import gy from '@/assets/common/gy.png'
import mt from '@/assets/common/mt.png'
import hd from '@/assets/common/hd.png'
import tcc from '@/assets/common/tcc.png'
import xfs from '@/assets/common/xfs.png'
import bns from '@/assets/common/bns.png'
import ggcs from '@/assets/common/ggcs.png'
import ld from '@/assets/common/ld.png'
import wushui from '@/assets/common/wushui.png'
import xhd from '@/assets/common/xhd.png'
import ysss from '@/assets/common/ysss.png'
import gy_Active from '@/assets/common/gy_Active.png'
import mt_Active from '@/assets/common/mt_Active.png'
import hd_Active from '@/assets/common/hd_Active.png'
import tcc_Active from '@/assets/common/tcc_Active.png'
import xfs_Active from '@/assets/common/xfs_Active.png'
import bns_Active from '@/assets/common/bns_Active.png'
import ggcs_Active from '@/assets/common/ggcs_Active.png'
import ld_Active from '@/assets/common/ld_Active.png'
import wushui_Active from '@/assets/common/wushui_Active.png'
import xhd_Active from '@/assets/common/xhd_Active.png'
import ysss_Active from '@/assets/common/ysss_Active.png'
import topGy from '@/assets/common/popBox/topGy.png'
import topMt from '@/assets/common/popBox/topMt.png'
import topHd from '@/assets/common/popBox/topHd.png'
import topTcc from '@/assets/common/popBox/topTcc.png'
import topXfs from '@/assets/common/popBox/topXfs.png'
import topBns from '@/assets/common/popBox/topBns.png'
import topGgcs from '@/assets/common/popBox/topGgcs.png'
import topLd from '@/assets/common/popBox/topLd.png'
import topWushui from '@/assets/common/popBox/topWushui.png'
import topXhd from '@/assets/common/popBox/topXhd.png'
import topYsss from '@/assets/common/popBox/topYsss.png'
const navData = [
{
name: '网格部件', id: 1, rotate: 0, child: [
{
name: '公园', id: 1, img: gy, activeImg: gy_Active, topImg: topGy },
{
name: '码头', id: 2, img: mt, activeImg: mt_Active, topImg: topMt },
{
name: '涵洞', id: 3, img: hd, activeImg: hd_Active, topImg: topHd },
{
name: '停车场', id: 4, img: tcc, activeImg: tcc_Active, topImg: topTcc },
{
name: '消防栓', id: 5, img: xfs, activeImg: xfs_Active, topImg: topXfs },
{
name: '避难所', id: 6, img: bns, activeImg: bns_Active, topImg: topBns },
{
name: '公共厕所', id: 7, img: ggcs, activeImg: ggcs_Active, topImg: topGgcs },
{
name: '路灯', id: 8, img: ld, activeImg: ld_Active, topImg: topLd },
{
name: '污水', id: 9, img: wushui, activeImg: wushui_Active, topImg: topWushui },
{
name: '信号灯', id: 10, img: xhd, activeImg: xhd_Active, topImg: topXhd },
{
name: '雨水设施', id: 11, img: ysss, activeImg: ysss_Active, topImg: topYsss },
],
img: wgbj
},
{
name: '网格力量', id: 2, ysss: gy, rotate: 40, child: [
{
name: '网格员', img: gy, id: 1 },
{
name: '保洁员', img: gy, id: 2 },
{
name: '律师', img: gy, id: 3 },
{
name: '警官', img: gy, id: 4 },
{
name: '法官', img: gy, id: 5 },
{
name: '检察官', img: gy, id: 6 }
],
img: wgll
},
{
name: '文旅', id: 3, rotate: 80,
img: wl
},
{
name: '民生', id: 4, rotate: 120, child: [
{
name: '网格员', img: gy, id: 1 },
{
name: '保洁员', img: gy, id: 2 },
{
name: '律师', img: gy, id: 3 },
{
name: '警官', img: gy, id: 4 },
{
name: '法官', img: gy, id: 5 },
{
name: '检察官', img: gy, id: 6 }
], img: ms
},
{
name: '管理', id: 5, rotate: 160, child: [
{
name: '网格员', img: gy, id: 1 },
{
name: '保洁员', img: gy, id: 2 },
{
name: '警官', img: gy, id: 4 },
{
name: '检察官', img: gy, id: 6 }
], img: gl
},
{
name: '体育', id: 6, rotate: 200, child: [
{
name: '网格员', img: gy, id: 1 },
{
name: '保洁员', img: gy, id: 2 },
{
name: '检察官', img: gy, id: 6 }
], img: ty
},
{
name: '科技', id: 7, rotate: 240, child: [
{
name: '网格员', img: gy, id: 1 },
{
name: '保洁员', img: gy, id: 2 },
{
name: '律师', img: gy, id: 3 },
{
name: '警官', img: gy, id: 4 },
{
name: '法官', img: gy, id: 5 },
{
name: '检察官', img: gy, id: 6 }
], img: kj
},
{
name: '教育', id: 8, rotate: 280, child: [
{
name: '网格员', img: gy, id: 1 },
{
name: '律师', img: gy, id: 3 },
{
name: '警官', img: gy, id: 4 },
{
name: '法官', img: gy, id: 5 },
{
name: '检察官', img: gy, id: 6 }
], img: jy
},
{
name: '卫生', id: 9, rotate: 320, child: [
{
name: '网格员', img: gy, id: 1 },
{
name: '保洁员', img: gy, id: 2 },
{
name: '律师', img: gy, id: 3 },
{
name: '检察官', img: gy, id: 6 }
], img: ws
},
]
const index = () =>
{
const [isShow, setIsShow] = useState(false)
const [rotate, setRotate] = useState(0)
const [menuData, setMenuData] = useState(navData[0].child)
const [navDataActive, setNavDataActive] = useState(1)
const [menuDataActive, setMenuDataActive] = useState(null)
const handleMouse = (flag) =>
{
return () =>
{
setIsShow(flag)
}
}
const click = () =>
{
setIsShow(!isShow)
}
const navClick = (data, rotate) =>
{
console.log(rotate, 222);
setRotate(rotate)
setNavDataActive(data.id)
setMenuData(data.child)
setMenuDataActive(null)
}
const menuClick = (data) =>
{
setMenuDataActive(data.id)
}
return (
<div
onMouseLeave={
handleMouse(false)}
className={
isShow ? styles.container : styles.containerActive}>
<a className={
styles.menu_toggler} onClick={
click}>
<img onMouseEnter={
handleMouse(true)} style={
isShow ? {
transform: 'scale(1)', transition: 'all 1s' } : {
transform: 'scale(.8)', transition: 'all 1s' }} src={
pu} alt="" />
</a>
<div style={
isShow ? {
transform: 'scale(1)', transition: 'all 1s' } : {
transform: 'scale(.3)', transition: 'all 1s' }} className={
isShow ? styles.menuWarp : styles.menuWarpActive}>
<nav className={
styles.menu}>
<ul>
{
navData.map((data, index) => (
<li style={
isShow ? {
transform: `rotate(${
360 / navData.length * index}deg) translateX(-150px)` } : null} key={
index} className={
`${
styles.menu_item} ${
isShow && styles.menu_item_active} `} >
<a
onClick={
() => {
navClick(data, 360 / navData.length * index) }}
className={
styles.nav_item}
style={
navDataActive === data.id ? {
backgroundImage: `url(${
itemActiveImg} )`, backgroundSize: '100% 100%', transform: `rotate(-${
360 / navData.length * index}deg)`, transition: 'all 1s' } :
{
backgroundImage: `url(${
itemImg} )`, backgroundSize: '100% 100%', transform: `rotate(-${
360 / navData.length * index}deg)`, transition: 'all 1s' }}>
<img style={
{
width: '20px', height: '20px' }} src={
data.img} alt={
data.name} />
<span> {
data.name}</span>
</a>
</li>
))}
</ul>
<ul>
{
menuData?.map((data, index) => (
<li style={
isShow ? {
transform: `rotate(${
360 / menuData.length * index}deg) translateX(-270px)` } : null} key={
index} className={
`${
styles.menu_item} ${
isShow && styles.menu_item_active} `} >
<a
style={
menuDataActive === data.id ? {
flexFlow: 'column', backgroundImage: `url(${
itemActiveImg} )`, backgroundSize: '100% 100%', transform: `rotate(-${
360 / menuData.length * index}deg)`, transition: 'all 1s' } : {
flexFlow: 'column', backgroundImage: `url(${
itemImg} )`, backgroundSize: '100% 100%', transform: `rotate(-${
360 / menuData.length * index}deg)`, transition: 'all 1s' }}
className={
styles.nav_item}
onClick={
() => {
menuClick(data, index) }}>
<img style={
{
width: '34px', height: '32px' }} src={
menuDataActive === data.id ? data.activeImg : data.img} alt={
data.name} />
<span> {
data.name}</span>
</a>
</li>
))}
</ul>
</nav>
</div>
</div >
);
};
export default index
CSS
.container,
.containerActive {
display: flex;
justify-content: center;
align-items: center;
position: relative;
background: linear-gradient(to right, #ed6ea0, #ec8c69);
width: 700px;
height: 700px;
background: url('~@/assets/common/menu2.png') no-repeat;
background-size: 100% 100%;
margin: 0 auto;
// 按钮
.menu_toggler {
position: absolute;
display: block;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
// width: 40px;
// height: 40px;
width: 200px;
height: 200px;
z-index: 2;
opacity: 1;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
.menuWarp,
.menuWarpActive {
width: 400px;
height: 400px;
background-color: red;
background: url('~@/assets/common/menu2.png') no-repeat;
background-size: 100% 100%;
.menu_item {
position: absolute;
display: block;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
width: 80px;
height: 80px;
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;
}
// new
}
.menuWarpActive {
width: 200px;
height: 200px;
background-color: red;
background: url('~@/assets/common/menu2.png') no-repeat;
background-size: 100% 100%;
}
}
.containerActive {
width: 700px;
height: 700px;
background: transparent;
}