一个简单的动态菜单组件

点击图片查看

https://mock.ezcomezgo.com/%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E5%8A%A8%E6%80%81%E8%8F%9C%E5%8D%95%E7%BB%84%E4%BB%B6/

实现方法如下

Menu.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import { useState } from 'react'
import './Menu.css'

function Menu() {
const menus = [
{
title: 'Home',
icon: 'home'
},
{
title: 'search',
icon: 'search'
},
{
title: 'user',
icon: 'user'
},
{
title: 'Setting',
icon: 'setting'
}
]
const [activeMenu, setActiveMenu] = useState(menus[0].title)
const [current, setCurrent] = useState(0)

return (
<div className="Menu">
<div className='items'>
<div style={
{
transform: 'translateX(' + 350 / 4 * current + 'px)'
}
} className="pointer"></div>
{
menus.map((item, index) => {
return (
<span onClick={() => {
if (activeMenu !== item.title) {
setActiveMenu(item.title, index)
setCurrent(index)
}
}} key={item.title} className={`item iconfont icon-${item.icon} ${activeMenu === item.title ? 'active' : ''}`}>
<span className='title'>{item.title}</span>
</span>
)
})
}
</div>
</div>
)
}

export default Menu

Menu.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
@font-face {
font-family: "iconfont";
/* Project id */
src: url('iconfont.ttf?t=1653709881240') format('truetype');
}

.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

.icon-home:before {
content: "\f0174";
}

.icon-setting:before {
content: "\e78e";
}

.icon-user:before {
content: "\e7ae";
}

.icon-search:before {
content: "\e8ef";
}

.Menu {
color: rgb(0, 0, 0);
height: 50px;
width: 350px;
background-color: rgb(15, 136, 218);
border-top-left-radius: 15px;
border-top-right-radius: 15px;
display: flex;
position: relative;
}

.Menu .items {
display: flex;
width: 100%;
height: 100%;
flex-direction: row;
justify-content: space-around;
align-items: center;
/* border: 1px solid red; */
}

.Menu .items .item {
cursor: pointer;
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
font-size: 1.5em;
transition: .3s ease-out;
position: relative;
}

.Menu .items .item .title {
font-size: .5em;
font-weight: bold;
position: absolute;
top: 50px;
opacity: 0;
}

.Menu .pointer {
transition: .1s ease-out;
box-sizing: border-box;
position: absolute;
top: -30px;
left: calc(350px / 4 / 2 - 50px / 2);
width: 50px;
height: 50px;
border-radius: 50%;
border: 5px solid rgb(255, 255, 255);
background-color: rgb(25, 226, 69);
}

.Menu .items .active {
transform: translateY(-30px);
color: #fff;
}

.Menu .items .active .title {
opacity: 1;
}