Blazor实现菜单动画
想到动画,你可能会去安装Blazor的动画组件BlazorAnimate,然后使用它。本人初学,暂时我也不知道原理,先不用组件,自己实现吧。虽然项目中我用了AntDesignBlazor,但是我忘了使用它的菜单组件,我用的菜单组件还是VS2022自动生成的,后来我把这个菜单改造了一下,支持多级菜单,加了展示收缩箭头,那就在这基础上做吧。
1. 引用jQuery
这里使用jquery的animate方法实现动画
在wwwroot/js目录放一个jquery-1.9.1.js文件,然后在html(或_Layout.cshtml文件)中引入该js
<script src="js/jquery-1.9.1.js"></script>
2. 为左侧菜单组件NavMenu.razor添加一个js文件:NavMenu.razor.js
内容如下:
export function animate(index) { //index是菜单编码 2位数是一级菜单,4位数是二级菜单,以此类推
let time = 200;
let content = $(".content" + index);
let h = content.height() + "px";
content.css("overflow", "hidden");
if (index <= 99 || content.hasClass("collapse")) { //index<=99表示一级菜单,一级菜单只有展开动画,没有收缩动画;content.hasClass("collapse")表示当前是收缩状态。
content.css("height", "0");
//展开动画
content.animate({
height: h
}, time, "linear", () => {
content.css("height", "auto");
});
} else { //不是一级菜单并且当前是展开状态,将执行收缩动画
content.css("height", "auto");
//收缩动画
content.animate({
height: 0
}, time, "linear", () => {
setTimeout(function () { //延迟执行,否则会导致闪烁
content.css("height", "auto");
}, 100);
});
return [time]; //收缩时,需要等待收缩动画展示完成,再隐藏菜单容器div
}
return [0];
}
3. 在Blazor组件NavMenu.razor文件中引入该js
@inject IJSRuntime _js;
@code {
IJSObjectReference _module;
protected override async void OnAfterRender(bool firstRender)
{
if (firstRender)
{
_module = await _js.InvokeAsync<IJSObjectReference>("import", "./Shared/NavMenu.razor.js");
}
}
}
4. 调用js方法实现菜单动画
@code{
...省略此处的代码
private async Task ToggleMenuClick(int index)
{
object[] args = new object[] { index };
object[] objs = await _module.InvokeAsync<object[]>("animate", args);
int time = ((JsonElement)objs[0]).GetInt32();
if (time > 0) { await Task.Delay(time); } //time大于0,表示需要等待收缩动画展示完成,再隐藏菜单容器div
if (index > 99)
{
if (_dict.ContainsKey(index))
{
_dict[index] = !_dict[index]; //记录非一级菜单的展开状态
}
else
{
_dict[index] = false; //记录非一级菜单的展开状态
}
}
else
{
_index = index; //_index是当前展示的菜单编码
}
}
...省略此处的代码
}
效果图
NavMenu.razor页面完整代码如下
@using System.Text.Json;
@inject IJSRuntime _js;
<!-- 菜单组 -->
<div class="top-row ps-3 navbar navbar-dark" @onclick="@(async ()=>await ToggleMenuClick(01))">
<div class="container-fluid">
<a class="navbar-brand" href="javascript:void(0);">任务管理</a>
<button title="Navigation menu" class="navbar-toggler">
<span class="navbar-toggler-icon"></span>
</button>
<div class="@ArrowClass(01)"></div>
</div>
</div>
<!-- 菜单组内容 -->
<div class="@MenuGroupContentClass(01)">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="kpTask/taskList">
<span class="oi oi-list" aria-hidden="true"></span> 任务列表
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="kpTask/taskRunList">
<span class="oi oi-list" aria-hidden="true"></span> 任务执行记录
</NavLink>
<!-- 二级菜单组 -->
<NavLink class="nav-link" href="javascript:void(0);" @onclick="@(()=> ToggleMenuClick(0101))" style="display:;">
<span class="oi oi-list" aria-hidden="true"></span> 测试二级菜单组
<div class="@ArrowClass(0101)"></div>
</NavLink>
<!-- 二级菜单组内容 -->
<div class="@MenuGroupContentClass(0101)" style="display:;">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="oi oi-list" aria-hidden="true"></span> 测试二级菜单
</NavLink>
<!-- 三级菜单组 -->
<NavLink class="nav-link" href="javascript:void(0);" @onclick="@(()=> ToggleMenuClick(010101))" style="display:;">
<span class="oi oi-list" aria-hidden="true"></span> 测试三级菜单组
<div class="@ArrowClass(010101)"></div>
</NavLink>
<!-- 三级菜单组内容 -->
<div class="@MenuGroupContentClass(010101)" style="display:;">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="oi oi-list" aria-hidden="true"></span> 测试三级菜单
</NavLink>
</div>
</nav>
</div>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="oi oi-list" aria-hidden="true"></span> 测试二级菜单2
</NavLink>
</div>
</nav>
</div>
</div>
</nav>
</div>
<!-- 菜单组 -->
<div class="top-row ps-3 navbar navbar-dark" @onclick="@(async ()=>await ToggleMenuClick(02))">
<div class="container-fluid">
<a class="navbar-brand" href="javascript:void(0);">任务管理</a>
<button title="Navigation menu" class="navbar-toggler">
<span class="navbar-toggler-icon"></span>
</button>
<div class="@ArrowClass(01)"></div>
</div>
</div>
<!-- 菜单组内容 -->
<div class="@MenuGroupContentClass(02)">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="kpTask/taskList">
<span class="oi oi-list" aria-hidden="true"></span> 任务列表
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="kpTask/taskRunList">
<span class="oi oi-list" aria-hidden="true"></span> 任务执行记录
</NavLink>
<!-- 二级菜单组 -->
<NavLink class="nav-link" href="javascript:void(0);" @onclick="@(()=> ToggleMenuClick(0201))" style="display:none;">
<span class="oi oi-list" aria-hidden="true"></span> 测试二级菜单组
<div class="@ArrowClass(0201)"></div>
</NavLink>
<!-- 二级菜单组内容 -->
<div class="@MenuGroupContentClass(0201)" style="display:none;">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="oi oi-list" aria-hidden="true"></span> 测试二级菜单
</NavLink>
</div>
</nav>
</div>
</div>
</nav>
</div>
<!-- 菜单组 -->
<div class="top-row ps-3 navbar navbar-dark" @onclick="@(async ()=>await ToggleMenuClick(03))">
<div class="container-fluid">
<a class="navbar-brand" href="javascript:void(0);">任务管理</a>
<button title="Navigation menu" class="navbar-toggler">
<span class="navbar-toggler-icon"></span>
</button>
<div class="@ArrowClass(01)"></div>
</div>
</div>
<!-- 菜单组内容 -->
<div class="@MenuGroupContentClass(03)">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="kpTask/taskList">
<span class="oi oi-list" aria-hidden="true"></span> 任务列表
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="kpTask/taskRunList">
<span class="oi oi-list" aria-hidden="true"></span> 任务执行记录
</NavLink>
<!-- 二级菜单组 -->
<NavLink class="nav-link" href="javascript:void(0);" @onclick="@(()=> ToggleMenuClick(0301))" style="display:none;">
<span class="oi oi-list" aria-hidden="true"></span> 测试二级菜单组
<div class="@ArrowClass(0301)"></div>
</NavLink>
<!-- 二级菜单组内容 -->
<div class="@MenuGroupContentClass(0301)" style="display:none;">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="oi oi-list" aria-hidden="true"></span> 测试二级菜单
</NavLink>
</div>
</nav>
</div>
</div>
</nav>
</div>
@code {
int _index = 01;
Dictionary<int, bool> _dict = new Dictionary<int, bool>();
IJSObjectReference _module;
protected override async void OnAfterRender(bool firstRender)
{
if (firstRender)
{
_module = await _js.InvokeAsync<IJSObjectReference>("import", "./Shared/NavMenu.razor.js");
}
}
private async Task ToggleMenuClick(int index)
{
object[] args = new object[] { index };
object[] objs = await _module.InvokeAsync<object[]>("animate", args);
int time = ((JsonElement)objs[0]).GetInt32();
if (time > 0) { await Task.Delay(time); }
if (index > 99)
{
if (_dict.ContainsKey(index))
{
_dict[index] = !_dict[index];
}
else
{
_dict[index] = false;
}
}
else
{
_index = index;
}
}
private string MenuGroupContentClass(int index)
{
if (index > 99)
{
if (!_dict.ContainsKey(index) || _dict[index])
{
return $"collapse content{index}";
}
else
{
return $"content{index}";
}
}
else
{
if (index == _index)
{
return $"content{index}";
}
else
{
return $"collapse content{index}";
}
}
}
private string ArrowClass(int index)
{
if (index > 99)
{
if (!_dict.ContainsKey(index) || _dict[index])
{
return "arrow-collapse arrow-float";
}
else
{
return "arrow arrow-float";
}
}
else
{
if (index == _index)
{
return "arrow";
}
else
{
return "arrow-collapse";
}
}
}
}
Blazor实现菜单动画的更多相关文章
- Android菜单(动画菜单、360波纹菜单)
Android菜单(动画菜单.360波纹菜单) 前言:Android菜单常用集合:FragmentTabHost系统菜单.上移式菜单.360波纹菜单.展开式菜单.详解注释,可直接拿来用! 效果: ...
- CSS3--点击弹出菜单动画
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...
- 【译】仿Taasky的3D翻转菜单动画实现
最终效果 最终效果 开始 首先下载并打开一个事先搭好架子的Demo,然后来分析一下.这个Demo包含一个主页和详情页,其中MenuViewController继承自UITableViewControl ...
- jquery css3 手机菜单动画综合版
html <header> <a id="go-back" href="javascript:window.location.back(-1)" ...
- iOS-一个弹出菜单动画视图开源项目分享
相似于Tumblr公布button的弹出视图 使用非常easy: 初始化: @property (nonatomic, strong) XWMenuPopView *myMenuPopView; - ...
- No.1 - 制作一个简单的菜单动画效果---百度IFE
最近比较闲,在家做点训练 http://ife.baidu.com/course/detail/id/18?t=1527144851578#learn CSS3新特性,兼容性,兼容方法总结 https ...
- 基于HTML5和SVG的手机菜单动画
在线演示 本地下载
- vue基于 element-ui 实现菜单动画效果,任意添加 li 个数均匀撑满 ul 宽度
%)%)%%%))) .) .) .) .) .) .) .) .) .) .) .) .) .) .) .) .% %% %deg);}
- Flutter Demo: 径向菜单动画
video import 'dart:math'; import 'package:flutter/material.dart'; import 'package:vector_math/vector ...
- IOS中的动画菜单
SvpplyTable(可折叠可张开的菜单动画) 允许你简单地创建可折叠可张开的菜单动画效果,灵感来自于Svpply app.不同表格项目使用JSON定义,你可以定义每个菜单项和任何子菜单,为每个项目 ...
随机推荐
- 29. 干货系列从零用Rust编写正反向代理,异步回调(async trait)的使用
wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,七层负载均衡,内网穿透,后续将实现websocket代 ...
- 大数据 - MapReduce:从原理到实战的全面指南
本文深入探讨了MapReduce的各个方面,从基础概念和工作原理到编程模型和实际应用场景,最后专注于性能优化的最佳实践. 关注[TechLeadCloud],分享互联网架构.云服务技术的全维度知识.作 ...
- SpringBoot实现Flyway的Callback回调钩子
背景 产品迭代使用CI/CD升级过程中,需要对不同发布环境的不同产品版本进行数据库迭代升级,我们在中间某次产品迭代时加入了Flyway中间件以实现数据库结构的自动化升级. 需求 由于是迭代过程中加入的 ...
- NLP项目实战02:英文文本识别
简介: 欢迎来到本篇文章!今天我们将讨论一个新的自然语言处理任务--英文短文识别.具体而言,即通过分析输入的英文文本来判断其是比较消极的还是比较积极的. 展示: 1.项目界面 如下所示是项目启动后用户 ...
- MySQL按照日期查询
MySQL按时间查询 今天 select * from 表名 where TO_DAYS(时间字段名) = TO_DAYS(now()); 昨天 SELECT * FROM 表名 WHERE TO_D ...
- LeetCode5716:好因子的最大数目(数学、快速幂)
解题思路:因为primeFactors比较大,所以需要使用快速幂. class Solution: def quick_pow(self,base,x): ans = 1 while x>0: ...
- 2021AI量化投资训练营重磅升级,自带编程的优势显而易见
量化交易规模突破万亿大关 国内量化交易规模快速发展,今年量化基金已突破万亿大关,并且量化私募的整体业绩十分亮眼,过去5年一线量化私募的超额收益基本在20%~30%,量化交易的占比已达到20%-30%( ...
- URL路径参数转换器
作用和基本使用 作用: 用于校验请求的路由参数中的值是否符合符合指定的规则. 这个使用方法和django中的路由参数转换器是差不多的. 至于为什么用路径参数转换器,原因和django中的一样,虽然你可 ...
- 中企网安信息科技:数据防泄密DLP管理系统概述
由华企网安总公司北京中企网安信息科技有限责任公司开发的<数据防泄密DLP管理系统>,获得国家版权局颁发的计算机软件著作权登记证书. 数据防泄密DLP管理系统是用于保护.监控和管理敏感数据的 ...
- 【C#】【System.IO】关于拷贝文件夹以及(Directory和DirectoryInfo、File和FileInfo)的区别
本次问题是想要拷贝文件夹,但是找了一圈发现只有File有Copy或者FileInfo的CopyTo,并没有Directory的拷贝操作方法. 针对C#中拷贝文件夹的方法就是先生成一个目标文件夹(des ...