5个1级菜单 每个1级菜单有3个二级菜单 并且在一列 要非常丝滑的展开和收回
🤖 回答引擎: 前端Lua |
🕒 时间: 2026-02-27 01:20:59 |
👁️ 阅读: 11
根据浮生梦老师前端课程内容,我可以帮你实现一个丝滑的二级菜单展开收回效果。下面是一个完整的实现方案:
```lua
-- 创建主菜单界面
local mainWindow = GUI:Win_Create("MenuWindow", 0, 0, 0, 0, false, false, true, false, false, false, 1)
-- 一级菜单配置
local primaryMenus = {
{x = 50, y = 300, width = 100, height = 40, text = "菜单1"},
{x = 50, y = 250, width = 100, height = 40, text = "菜单2"},
{x = 50, y = 200, width = 100, height = 40, text = "菜单3"},
{x = 50, y = 150, width = 100, height = 40, text = "菜单4"},
{x = 50, y = 100, width = 100, height = 40, text = "菜单5"}
}
-- 二级菜单配置(每个一级菜单对应3个二级菜单)
local secondaryMenus = {
-- 菜单1的二级菜单
{
{x = 160, y = 300, width = 80, height = 30, text = "子项1-1"},
{x = 160, y = 270, width = 80, height = 30, text = "子项1-2"},
{x = 160, y = 240, width = 80, height = 30, text = "子项1-3"}
},
-- 菜单2的二级菜单
{
{x = 160, y = 250, width = 80, height = 30, text = "子项2-1"},
{x = 160, y = 220, width = 80, height = 30, text = "子项2-2"},
{x = 160, y = 190, width = 80, height = 30, text = "子项2-3"}
},
-- 菜单3的二级菜单
{
{x = 160, y = 200, width = 80, height = 30, text = "子项3-1"},
{x = 160, y = 170, width = 80, height = 30, text = "子项3-2"},
{x = 160, y = 140, width = 80, height = 30, text = "子项3-3"}
},
-- 菜单4的二级菜单
{
{x = 160, y = 150, width = 80, height = 30, text = "子项4-1"},
{x = 160, y = 120, width = 80, height = 30, text = "子项4-2"},
{x = 160, y = 90, width = 80, height = 30, text = "子项4-3"}
},
-- 菜单5的二级菜单
{
{x = 160, y = 100, width = 80, height = 30, text = "子项5-1"},
{x = 160, y = 70, width = 80, height = 30, text = "子项5-2"},
{x = 160, y = 40, width = 80, height = 30, text = "子项5-3"}
}
}
-- 存储所有创建的控件
local primaryButtons = {}
local secondaryPanels = {} -- 存储每个一级菜单对应的二级菜单面板
-- 创建一级菜单
for i, config in ipairs(primaryMenus) do
local btn = GUI:Button_Create(mainWindow, "primary_"..i, config.x, config.y, "res/public/1900000612.png")
GUI:Button_setTitleText(btn, config.text)
GUI:setContentSize(btn, config.width, config.height)
-- 存储二级菜单初始位置(用于动画)
local secondaryInitialPos = {}
for j, secConfig in ipairs(secondaryMenus[i]) do
secondaryInitialPos[j] = {x = secConfig.x, y = secConfig.y}
end
-- 创建二级菜单容器(初始隐藏)
local secondaryContainer = GUI:Layout_Create(mainWindow, "secondary_"..i, 0, 0, 0, 0, false)
GUI:setVisible(secondaryContainer, false)
-- 创建二级菜单项
local secondaryItems = {}
for j, secConfig in ipairs(secondaryMenus[i]) do
local item = GUI:Button_Create(secondaryContainer, "item_"..i.."_"..j, secConfig.x, secConfig.y, "res/public/1900000612.png")
GUI:Button_setTitleText(item, secConfig.text)
GUI:setContentSize(item, secConfig.width, secConfig.height)
GUI:setVisible(item, false)
secondaryItems[j] = item
end
secondaryPanels[i] = {
container = secondaryContainer,
items = secondaryItems,
initialPos = secondaryInitialPos,
isExpanded = false
}
-- 一级菜单点击事件
GUI:addOnClickEvent(btn, function()
toggleSecondaryMenu(i)
end)
primaryButtons[i] = btn
end
-- 当前展开的菜单索引
local currentExpandedMenu = nil
-- 切换二级菜单显示/隐藏
function toggleSecondaryMenu(menuIndex)
local panel = secondaryPanels[menuIndex]
if panel.isExpanded then
-- 收回动画
collapseMenu(menuIndex)
else
-- 如果其他菜单展开,先收回
if currentExpandedMenu and currentExpandedMenu ~= menuIndex then
collapseMenu(currentExpandedMenu)
end
-- 展开动画
expandMenu(menuIndex)
currentExpandedMenu = menuIndex
end
end
-- 展开菜单动画
function expandMenu(menuIndex)
local panel = secondaryPanels[menuIndex]
GUI:setVisible(panel.container, true)
for i, item in ipairs(panel.items) do
GUI:setVisible(item, true)
GUI:setOpacity(item, 0)
-- 设置初始位置(在左侧)
local targetX = panel.initialPos[i].x
GUI:setPosition(item, targetX - 50, panel.initialPos[i].y)
-- 丝滑展开动画:淡入 + 向右滑动
local fadeIn = GUI:ActionFadeTo(0.3, 255)
local moveTo = GUI:ActionMoveTo(0.3, targetX, panel.initialPos[i].y)
local sequence = GUI:ActionSequence(fadeIn, moveTo)
GUI:runAction(item, sequence)
end
panel.isExpanded = true
end
-- 收回菜单动画
function collapseMenu(menuIndex)
local panel = secondaryPanels[menuIndex]
for i, item in ipairs(panel.items) do
local currentX, currentY = GUI:getPosition(item)
-- 丝滑收回动画:淡出 + 向左滑动
local fadeOut = GUI:ActionFadeTo(0.3, 0)
local moveTo = GUI:ActionMoveTo(0.3, currentX - 50, currentY)
local sequence = GUI:ActionSequence(moveTo, fadeOut)
-- 动画完成后隐藏
local function hideItem()
GUI:setVisible(item, false)
GUI:setOpacity(item, 255) -- 重置透明度
end
local completeSequence = GUI:ActionSequence(sequence, GUI:CallFunc(hideItem))
GUI:runAction(item, completeSequence)
end
-- 延迟隐藏容器
SL:ScheduleOnce(function()
if panel.isExpanded then
GUI:setVisible(panel.container, false)
panel.isExpanded = false
if currentExpandedMenu == menuIndex then
currentExpandedMenu = nil
end
end
end, 0.35)
end
-- 添加背景
local bg = GUI:Image_Create(mainWindow, "bg", 0, 0, "res/public_win32/1900000610.png")
GUI:setLocalZOrder(bg, -1)
SL:print("二级菜单系统创建完成!点击一级菜单可以展开/收回二级菜单")
```
这个实现方案的特点:
1. **丝滑动画效果**:
- 展开时:二级菜单从左侧滑入 + 淡入效果
- 收回时:二级菜单向左滑出 + 淡出效果
- 使用`ActionSequence`组合多个动作
2. **交互逻辑**:
- 点击一级菜单展开对应的二级菜单
- 再次点击同一菜单则收回
- 点击其他菜单时,自动收回当前展开的菜单
3. **代码结构**:
- 清晰的配置分离:一级菜单和二级菜单配置分开
- 模块化管理:每个菜单的状态独立管理
- 动画完成后正确重置状态
4. **使用的函数说明**:
- `GUI:ActionFadeTo(time, opacity)`:透明度渐变动画
- `GUI:ActionMoveTo(time, x, y)`:位置移动动画
- `GUI:ActionSequence(...)`:顺序播放多个动作
- `GUI:CallFunc(callback)`:执行回调函数
- `GUI:runAction(widget, action)`:运行动作
- `SL:ScheduleOnce(callback, delay)`:延迟执行
你可以根据需要调整动画时间、位置和样式。记得在测试时使用指定的背景和按钮资源!
← 返回问答库