旋转菜单2.0

效果图

在这里插入图片描述

JS

import { useState, Fragment } 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, img: ms },
    { name: '管理', id: 5, rotate: 160, img: gl },
    { name: '体育', id: 6, rotate: 200, img: ty },
    { name: '科技', id: 7, rotate: 240, img: kj },
    { name: '教育', id: 8, rotate: 280, img: jy },
    { name: '卫生', id: 9, rotate: 320, 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)
        }
    }
    // 选中高亮以及更换2级菜单数据以及清空高亮状态
    const navClick = (data, rotate) =>
    {
        setNavDataActive(data.id)
        setMenuData(data.child)
        setMenuDataActive(null)
    }
    // 选中高亮
    const menuClick = (data) =>
    {
        setMenuDataActive(data.id)
    }
    return (
        <Fragment>
            <div onMouseLeave={handleMouse(false)} style={{ transition: 'all 1s' }} className={isShow ? styles.container : styles.containerActive}>
                <div className={styles.togglerContainers}>
                    <img style={isShow ? { transform: 'scale(1)', transition: 'all 1s' } : { transform: 'scale(.8)', transition: 'all 1s' }} onMouseEnter={handleMouse(true)} src={pu} alt="" />
                </div>
                <div style={{ transform: `rotate(-${rotate}deg)`, transition: 'all 1s' }} className={isShow ? styles.menuWarp : styles.menuWarpActive}>
                    <nav className={styles.menu} >
                        <ul >
                            {
                                navData.map((data, index) => (
                                    <li style={isShow ? { transform: `rotate(${data.rotate}deg) translateX(-150px)` } : null} key={index} className={`${styles.menu_item} ${isShow && styles.menu_item_active} `}  >
                                        <a style={navDataActive === data.id ? { backgroundImage: `url(${itemActiveImg} )`, backgroundSize: '100% 100%', transform: `rotate(-${data.rotate}deg)`, transition: 'all 1s' } : { backgroundImage: `url(${itemImg} )`, backgroundSize: '100% 100%', transform: `rotate(-${data.rotate}deg)`, transition: 'all 1s' }} onClick={() => { navClick(data, data.rotate) }}>
                                            <img style={{ width: '20px', height: '20px' }} src={data.img} alt={data.name} />
                                            <span> {data.name}</span>
                                        </a>
                                    </li>
                                ))
                            }
                        </ul>
                    </nav>
                </div>
                <div >
                    {menuData?.map((data, index) => (
                        <div 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' }} 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>
                        </div>
                    ))}
                </div>
            </div >
        </Fragment>
    );
};

export default index

CSS

.container,
.containerActive {
  margin: auto;
  position: relative;
  width: 700px;
  height: 700px;
  background: url('~@/assets/common/menu2.png') no-repeat;
  background-size: 100% 100%;
  display: flex;
  align-items: center;
  justify-content: center;


  pointer-events: auto;
  width: 700px;
  height: 700px;
  background-size: 100% 100%;


  .menuWarp,
  .menuWarpActive {
    width: 400px;
    height: 400px;
    background-color: red;
    background: url('~@/assets/common/menu2.png') no-repeat;
    background-size: 100% 100%;
  }

  .menuWarpActive {
    width: 210px;
    height: 210px;
    background-color: red;
    background: url('~@/assets/common/menu2.png') no-repeat;
    background-size: 100% 100%;
  }

  .togglerContainers {
    position: absolute;
    display: block;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
    // width: 40px;
    // height: 40px;
    width: 210px;
    height: 210px;
    z-index: 2;
    cursor: pointer;

    img {
      width: 210px;
      height: 210px;
    }
  }

  .menu_toggler {
    width: 100%;
    height: 5px;
    display: block;
    z-index: 1;
    border-radius: 2.5px;
    background: rgba(255, 255, 255, 0.7);
    transition: transform 0.5s, top 0.5s;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;




  }

  .menu_toggler_active {
    width: 100%;
    height: 5px;
    display: block;
    z-index: 1;
    border-radius: 2.5px;
    background: rgba(255, 255, 255, 1);
    transition: transform 0.5s, top 0.5s;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;

    &::before,
    &::after {
      width: 40px;
      height: 5px;
      display: block;
      z-index: 1;
      border-radius: 2.5px;
      background: rgba(255, 255, 255, 1);
      transition: transform 0.5s, top 0.5s;
      content: "";
      position: absolute;
      left: 0;
    }

    &::after {
      top: -10px;
    }

    &::before {
      top: 10px;
    }
  }


  .menu_toggler::before,
  .menu_toggler::after {
    width: 40px;
    height: 5px;
    display: block;
    z-index: 1;
    border-radius: 2.5px;
    background: rgba(255, 255, 255, 0.7);
    transition: transform 0.5s, top 0.5s;
    content: "";
    position: absolute;
    left: 0;
  }

  .menu_toggler::before {
    top: 10px;
  }

  .menu_toggler::after {
    top: -10px;
  }


  // 活跃的按钮
  .menu_item_active {
    opacity: 1 !important;
  }

  .menu_item_active:nth-child(1) {
    transform: rotate(0deg) translateX(-110px);

  }

  .menu_item_active:nth-child(2) {
    transform: rotate(60deg) translateX(-110px);
  }

  .menu_item_active:nth-child(3) {
    transform: rotate(120deg) translateX(-110px);
  }

  .menu_item_active:nth-child(4) {
    transform: rotate(180deg) translateX(-110px);
  }

  .menu_item_active:nth-child(5) {
    transform: rotate(240deg) translateX(-110px);
  }

  .menu_item_active:nth-child(6) {
    transform: rotate(300deg) translateX(-110px);
  }

  .menu_item_active:nth-child(1) a {
    transform: rotate(0deg);
  }

  .menu_item_active:nth-child(2) a {
    transform: rotate(-60deg);
  }

  .menu_item_active:nth-child(3) a {
    transform: rotate(-120deg);
  }

  .menu_item_active:nth-child(4) a {
    transform: rotate(-180deg);
  }

  .menu_item_active:nth-child(5) a {
    transform: rotate(-240deg);
  }

  .menu_item_active:nth-child(6) a {
    transform: rotate(-300deg);
  }

  .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 a {
    // display: block;
    // width: inherit;
    // height: inherit;
    // line-height: 80px;
    // 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;


    justify-content: space-evenly;
    padding: 8px;
    display: flex;
    /* display: block; */
    width: inherit;
    height: inherit;
    /* line-height: 80px; */
    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;

    &:hover {
      box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
      color: #fff;
      background: rgba(255, 255, 255, 0.3);
      //   font-size: 18px;
    }
  }
}

.containerActive {
  width: 700px;
  height: 700px;
  background: transparent;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

臧小川

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值