圆形导航栏

效果图

在这里插入图片描述

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])
    /**
 * 得到数组平均值并依次排序及倒叙
 * @param {Number} arrLength 数组长度  
 * @param {Number} i 数组下标  
 * @return {Number} 处理后的结果
*/
    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;
  /* 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;
}

.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;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

臧小川

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

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

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

打赏作者

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

抵扣说明:

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

余额充值