精通 Flutter 动画开发:从基础显隐动画到自定义 Hero + 物理动画的全场景实战

欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycrossplatform.csdn.net),一起共建开源鸿蒙跨平台生态。

动画是 Flutter 应用的 “灵魂”—— 一个流畅的动画能让按钮点击、页面切换、数据加载等交互瞬间变得生动,而糟糕的动画则会让应用显得卡顿、廉价。但很多开发者仅停留在使用系统自带动画的层面,遇到自定义动画、复杂交互动画时就束手无策。本文将从基础的显隐动画入手,逐步实现 Hero 转场动画、物理动画、自定义动画控制器等进阶功能,既有严谨的代码规范,又有生动的场景拆解,让你彻底掌握 Flutter 动画开发的精髓。

一、Flutter 动画核心认知:为什么动画开发容易踩坑?

先理清 Flutter 动画的底层逻辑,避开新手常见误区:

  • 动画的核心是 “状态插值 + 帧刷新”:Flutter 动画通过Animation对象管理插值(从初始值到目标值的渐变),AnimationController控制动画生命周期,AnimatedWidget/AnimatedBuilder实现 UI 刷新;
  • 动画分类
    • 隐式动画:系统封装的动画(如AnimatedOpacity/AnimatedContainer),只需修改状态,自动生成动画;
    • 显式动画:手动控制动画控制器(如AnimationController+CurvedAnimation),灵活性更高;
    • 转场动画:页面 / 组件切换动画(如Hero/PageRouteBuilder);
    • 物理动画:模拟真实物理规律的动画(如SpringSimulation/GravitySimulation);
  • 性能优化点:避免动画过程中重建 Widget、使用RepaintBoundary隔离重绘区域、合理设置动画曲线。

本文所有代码基于:

plaintext

Flutter 3.32.0 Dart 3.9.0

二、入门:隐式动画(一键实现基础动效)

隐式动画是 Flutter 最友好的动画方式,无需手动管理控制器,只需修改 Widget 的属性,系统会自动生成过渡动画。我们先实现 “按钮点击显隐 + 容器尺寸 / 颜色渐变” 的基础案例。

2.1 完整代码实现

dart

import 'package:flutter/material.dart'; void main() => runApp(const AnimationDemoApp()); class AnimationDemoApp extends StatelessWidget { const AnimationDemoApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter动画实战', theme: ThemeData(primarySwatch: Colors.blue), home: const ImplicitAnimationPage(), ); } } class ImplicitAnimationPage extends StatefulWidget { const ImplicitAnimationPage({super.key}); @override State<ImplicitAnimationPage> createState() => _ImplicitAnimationPageState(); } class _ImplicitAnimationPageState extends State<ImplicitAnimationPage> { // 控制容器显隐 bool _isVisible = true; // 控制容器尺寸 double _containerSize = 200; // 控制容器颜色 Color _containerColor = Colors.blue; // 控制容器圆角 double _borderRadius = 16; // 切换显隐状态 void _toggleVisibility() { setState(() { _isVisible = !_isVisible; }); } // 随机修改容器属性 void _randomizeContainer() { setState(() { _containerSize = 100 + (Math.random() * 200); // 100-300px _containerColor = Color.fromRGBO( Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), 1.0, ); _borderRadius = Random().nextDouble() * 50; // 0-50px }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('隐式动画实战')), body: Padding( padding: const EdgeInsets.all(20), child: Column( children: [ // 核心:AnimatedOpacity实现显隐动画 AnimatedOpacity( // 透明度:显示1.0,隐藏0.0 opacity: _isVisible ? 1.0 : 0.0, // 动画时长 duration: const Duration(milliseconds: 500), // 动画曲线(缓入缓出) curve: Curves.easeInOut, // 动画结束后的状态(隐藏时不占空间) child: AnimatedContainer( // 尺寸动画 width: _containerSize, height: _containerSize, // 颜色动画 color: _containerColor, // 圆角动画 decoration: BoxDecoration( borderRadius: BorderRadius.circular(_borderRadius), ), // 动画时长(可单独设置) duration: const Duration(milliseconds: 800), // 不同属性可设置不同曲线 curve: Curves.bounceOut, // 容器内的内容 child: const Center( child: Text( '隐式动画', style: TextStyle(color: Colors.white, fontSize: 24), ), ), ), ), const SizedBox(height: 40), // 操作按钮 Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: _toggleVisibility, child: Text(_isVisible ? '隐藏容器' : '显示容器'), ), const SizedBox(width: 20), ElevatedButton( onPressed: _randomizeContainer, child: const Text('随机修改容器'), ), ], ), ], ), ), ); } }

2.2 核心代码解析

1. 隐式动画核心控件
  • AnimatedOpacity:专门用于透明度动画的隐式控件,核心属性:
    • opacity:目标透明度(0.0-1.0);
    • duration:动画时长;
    • curve:动画曲线(控制动画的速度变化);
  • AnimatedContainer:万能的隐式动画控件,支持尺寸、颜色、圆角、边距等几乎所有容器属性的动画,只需修改属性值,自动生成过渡动画;
  • 其他常用隐式动画
    • AnimatedSize:尺寸动画;
    • AnimatedPositioned:定位动画(需配合Stack);
    • AnimatedSwitcher:组件切换动画;
    • AnimatedTextStyle:文本样式动画。
2. 动画曲线(Curves)

Flutter 内置了丰富的动画曲线,不同曲线对应不同的动画效果:

  • Curves.easeInOut:缓入缓出(默认,最自然);
  • Curves.bounceOut:回弹效果(类似皮球落地);
  • Curves.elasticOut:弹性效果;
  • Curves.decelerate:减速效果;
  • Curves.linear:线性匀速效果。
3. 关键优化点
  • 状态驱动动画:所有动画都由setState修改状态触发,无需手动控制动画生命周期;
  • 动画叠加AnimatedOpacity嵌套AnimatedContainer实现多属性同时动画,Flutter 会自动处理动画叠加;
  • 性能优势:隐式动画内部已优化重绘逻辑,只会更新变化的属性,不会重建整个 Widget。

三、进阶:显式动画(手动控制动画生命周期)

隐式动画虽然简单,但灵活性不足(无法控制动画的暂停、反转、重复等)。显式动画通过AnimationController手动控制动画,适合复杂的交互场景。

3.1 实现自定义显式动画(进度条 + 旋转动画)

dart

import 'package:flutter/material.dart'; class ExplicitAnimationPage extends StatefulWidget { const ExplicitAnimationPage({super.key}); @override State<ExplicitAnimationPage> createState() => _ExplicitAnimationPageState(); } class _ExplicitAnimationPageState extends State<ExplicitAnimationPage> with SingleTickerProviderStateMixin { // 动画控制器(核心) late AnimationController _controller; // 进度动画(0.0-1.0) late Animation<double> _progressAnimation; // 旋转动画(0-2π) late Animation<double> _rotationAnimation; // 颜色动画(蓝色→红色→绿色) late Animation<Color?> _colorAnimation; @override void initState() { super.initState(); // 初始化动画控制器 _controller = AnimationController( // 动画时长 duration: const Duration(seconds: 2), // vsync:防止动画在后台运行(需混入SingleTickerProviderStateMixin) vsync: this, // 动画范围(0.0-1.0) lowerBound: 0.0, upperBound: 1.0, ); // 1. 进度动画(线性) _progressAnimation = Tween<double>(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: _controller, curve: Curves.linear), ); // 2. 旋转动画(0-2π) _rotationAnimation = Tween<double>(begin: 0.0, end: 2 * 3.1415926).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); // 3. 颜色动画(多颜色渐变) _colorAnimation = ColorTween( begin: Colors.blue, end: Colors.red, ).chain( ColorTween(begin: Colors.red, end: Colors.green), ).animate( CurvedAnimation(parent: _controller, curve: Curves.elasticOut), ); // 监听动画状态 _controller.addStatusListener((status) { if (status == AnimationStatus.completed) { // 动画完成后反转(从1.0→0.0) _controller.reverse(); } else if (status == AnimationStatus.dismissed) { // 动画回到初始状态后重新播放 _controller.forward(); } }); } // 控制动画播放/暂停 void _toggleAnimation() { if (_controller.isAnimating) { _controller.stop(); } else { _controller.forward(); // 从0.0→1.0播放 } } // 重置动画 void _resetAnimation() { _controller.reset(); // 回到初始状态 } @override void dispose() { // 释放动画控制器(必做!防止内存泄漏) _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('显式动画实战')), body: Padding( padding: const EdgeInsets.all(20), child: Column( children: [ // 核心:AnimatedBuilder实现自定义动画 AnimatedBuilder( // 动画对象(可传入多个动画的父控制器) animation: _controller, // 构建函数(只重建该区域,性能最优) builder: (context, child) { return Column( children: [ // 旋转+颜色动画容器 Transform.rotate( angle: _rotationAnimation.value, child: Container( width: 200, height: 200, color: _colorAnimation.value, child: const Center( child: Text( '显式动画', style: TextStyle(color: Colors.white, fontSize: 24), ), ), ), ), const SizedBox(height: 30), // 进度条动画 LinearProgressIndicator( value: _progressAnimation.value, backgroundColor: Colors.grey[200], valueColor: AlwaysStoppedAnimation<Color>( _colorAnimation.value ?? Colors.blue, ), minHeight: 10, ), const SizedBox(height: 10), Text( '进度:${(_progressAnimation.value * 100).toStringAsFixed(0)}%', style: const TextStyle(fontSize: 18), ), ], ); }, ), const SizedBox(height: 40), // 操作按钮 Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: _toggleAnimation, child: Text(_controller.isAnimating ? '暂停动画' : '播放动画'), ), const SizedBox(width: 20), ElevatedButton( onPressed: _resetAnimation, style: ElevatedButton.styleFrom(foregroundColor: Colors.red), child: const Text('重置动画'), ), ], ), ], ), ), ); } }

3.2 显式动画核心逻辑解析

1. 动画控制器(AnimationController)
  • 核心作用:控制动画的播放、暂停、反转、重置,管理动画的生命周期;
  • vsync:必须传入TickerProvider(通过混入SingleTickerProviderStateMixin实现),防止动画在页面不可见时继续运行,节省资源;
  • 生命周期管理:必须在dispose中释放控制器,否则会导致内存泄漏;
  • 常用方法
    • forward():从初始值播放到目标值;
    • reverse():从目标值反转到初始值;
    • stop():暂停动画;
    • reset():重置到初始状态;
    • repeat():重复播放动画。
2. 动画插值(Tween)
  • Tween:定义动画的取值范围,如Tween<double>(begin: 0.0, end: 1.0)表示从 0 到 1 的渐变;
  • ColorTween:颜色插值,支持从一个颜色渐变到另一个颜色;
  • Chain:多个 Tween 串联,实现多阶段插值(如蓝色→红色→绿色);
  • CurvedAnimation:为 Tween 添加动画曲线,控制动画的速度变化。
3. AnimatedBuilder(性能最优的显式动画方式)
  • 核心优势:只重建builder函数内的 Widget,不会重建整个父 Widget;
  • child 参数:如果有不参与动画的固定子 Widget,可通过child参数传入,避免重复重建;
  • 多动画管理:可传入AnimationController作为animation参数,监听所有基于该控制器的动画。

四、高阶 1:Hero 转场动画(页面间元素无缝过渡)

Hero 动画是 Flutter 中最具特色的转场动画之一,实现两个页面间同一元素的无缝过渡,比如点击商品图片跳转到详情页,图片会平滑地从列表位置过渡到详情页位置。

4.1 实现 Hero 动画(图片详情页转场)

第一步:列表页面(Hero 动画源)

dart

import 'package:flutter/material.dart'; import 'hero_detail_page.dart'; class HeroListPage extends StatelessWidget { const HeroListPage({super.key}); // 模拟商品列表数据 final List<Map<String, String>> _productList = [ { 'id': '1', 'name': 'Flutter实战教程', 'image': 'https://picsum.photos/200/200?random=1', }, { 'id': '2', 'name': 'Dart编程指南', 'image': 'https://picsum.photos/200/200?random=2', }, { 'id': '3', 'name': '动画开发实战', 'image': 'https://picsum.photos/200/200?random=3', }, ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Hero动画列表页')), body: GridView.builder( padding: const EdgeInsets.all(20), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, // 两列 crossAxisSpacing: 20, mainAxisSpacing: 20, childAspectRatio: 1.0, ), itemCount: _productList.length, itemBuilder: (context, index) { final product = _productList[index]; return GestureDetector( onTap: () { // 跳转到详情页 Navigator.push( context, MaterialPageRoute( builder: (context) => HeroDetailPage(product: product), ), ); }, child: Column( children: [ // 核心:Hero控件(必须设置唯一tag) Hero( tag: product['id']!, // 唯一标识,详情页需相同 // flightShuttleBuilder:自定义过渡组件(可选) flightShuttleBuilder: ( BuildContext flightContext, Animation<double> animation, HeroFlightDirection flightDirection, BuildContext fromHeroContext, BuildContext toHeroContext, ) { // 自定义过渡动画(缩放+渐变) return ScaleTransition( scale: animation.drive( Tween<double>(begin: 0.8, end: 1.2).chain( Tween<double>(begin: 1.2, end: 1.0), ), ), child: FadeTransition( opacity: animation, child: Image.network( product['image']!, fit: BoxFit.cover, ), ), ); }, child: ClipRRect( borderRadius: BorderRadius.circular(16), child: Image.network( product['image']!, width: 150, height: 150, fit: BoxFit.cover, ), ), ), const SizedBox(height: 10), Text( product['name']!, style: const TextStyle(fontSize: 16), ), ], ), ); }, ), ); } }
第二步:详情页面(Hero 动画目标)

dart

import 'package:flutter/material.dart'; class HeroDetailPage extends StatelessWidget { final Map<String, String> product; const HeroDetailPage({super.key, required this.product}); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: Column( children: [ // 核心:Hero控件(tag必须与列表页一致) Hero( tag: product['id']!, child: Image.network( product['image']!, width: double.infinity, height: 300, fit: BoxFit.cover, ), ), Expanded( child: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( product['name']!, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), ), const SizedBox(height: 20), const Text( '这是商品的详细描述信息,Hero动画实现了图片从列表页到详情页的无缝过渡,' '无需手动控制动画,只需给两个页面的相同元素添加相同tag的Hero控件即可。', style: TextStyle(fontSize: 16, color: Colors.grey), ), ], ), ), ), ], ), ); } }

4.2 Hero 动画核心逻辑解析

1. Hero 动画核心规则
  • 唯一 tag:两个页面的Hero控件必须设置相同的tag(通常用数据的唯一 ID),Flutter 通过 tag 识别需要过渡的元素;
  • 无需控制器:Hero 动画由 Flutter 自动管理,无需手动创建AnimationController
  • 过渡效果:默认是位置和尺寸的平滑过渡,可通过flightShuttleBuilder自定义过渡动画。
2. 自定义 Hero 过渡
  • flightShuttleBuilder:自定义过渡过程中的组件样式,可实现缩放、旋转、渐变等效果;
  • HeroFlightDirection:判断动画方向(push/pop),可根据方向设置不同的过渡效果;
  • transitionOnUserGestures:支持侧滑返回时的 Hero 动画(需配合PageRouteBuilder)。
3. 性能优化
  • 图片预加载:如果图片是网络图片,建议提前预加载,避免过渡过程中图片加载导致的卡顿;
  • 合理设置尺寸:Hero 动画会计算元素的尺寸和位置变化,避免过渡元素过大导致性能问题;
  • RepaintBoundary:如果过渡元素包含复杂的子 Widget,可包裹RepaintBoundary隔离重绘。

五、高阶 2:物理动画(模拟真实物理规律)

物理动画通过Simulation模拟真实世界的物理规律(如弹簧、重力、摩擦),让动画效果更自然、更贴近真实体验。

5.1 实现弹簧动画(拖拽小球回弹)

dart

import 'package:flutter/material.dart'; import 'package:flutter/physics.dart'; class PhysicsAnimationPage extends StatefulWidget { const PhysicsAnimationPage({super.key}); @override State<PhysicsAnimationPage> createState() => _PhysicsAnimationPageState(); } class _PhysicsAnimationPageState extends State<PhysicsAnimationPage> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<Offset> _animation; // 记录拖拽的初始位置 Offset _dragStart = Offset.zero; // 小球的当前位置 Offset _ballPosition = Offset.zero; @override void initState() { super.initState(); _controller = AnimationController(vsync: this); // 监听动画更新,更新小球位置 _controller.addListener(() { setState(() { _ballPosition = _animation.value; }); }); } // 处理拖拽开始 void _onDragStart(DragStartDetails details) { _controller.stop(); // 停止当前动画 _dragStart = details.globalPosition - _ballPosition; } // 处理拖拽中 void _onDragUpdate(DragUpdateDetails details) { setState(() { _ballPosition = details.globalPosition - _dragStart; }); } // 处理拖拽结束(触发物理动画) void _onDragEnd(DragEndDetails details) { // 创建弹簧模拟 final spring = SpringSimulation( SpringDescription( mass: 1.0, // 质量 stiffness: 100.0, // 刚度(越大越硬) damping: 15.0, // 阻尼(越大回弹越少) ), _ballPosition.dx, // 初始位置 MediaQuery.of(context).size.width / 2 - 25, // 目标位置(屏幕中心) details.velocity.pixelsPerSecond.dx, // 初始速度(拖拽结束时的速度) ); // 创建位置动画 _animation = _controller.drive( Tween<Offset>( begin: _ballPosition, end: Offset(MediaQuery.of(context).size.width / 2 - 25, _ballPosition.dy), ).animate( Animation<double>( controller: _controller, simulation: spring, ), ), ); // 播放动画 _controller.forward(from: 0.0); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('物理动画(弹簧)')), body: Stack( children: [ // 拖拽区域 Positioned( left: _ballPosition.dx, top: _ballPosition.dy == 0 ? MediaQuery.of(context).size.height / 2 - 25 : _ballPosition.dy, child: GestureDetector( onPanStart: _onDragStart, onPanUpdate: _onDragUpdate, onPanEnd: _onDragEnd, child: Container( width: 50, height: 50, decoration: const BoxDecoration( color: Colors.blue, shape: BoxShape.circle, boxShadow: [ BoxShadow( color: Colors.black12, blurRadius: 10, spreadRadius: 5, ), ], ), ), ), ), // 提示文本 const Positioned( bottom: 50, left: 0, right: 0, child: Center( child: Text( '拖拽小球体验弹簧物理动画', style: TextStyle(fontSize: 18, color: Colors.grey), ), ), ), ], ), ); } }

5.2 物理动画核心逻辑解析

1. 核心物理模拟(Simulation)

Flutter 提供了多种物理模拟:

  • SpringSimulation:弹簧模拟(最常用),核心参数:
    • mass:质量(越大运动越慢);
    • stiffness:刚度(越大弹簧越硬,回弹越快);
    • damping:阻尼(越大回弹越少,最终停止越快);
  • GravitySimulation:重力模拟;
  • FrictionSimulation:摩擦模拟;
  • ClampingScrollSimulation:滚动阻尼模拟(类似列表滚动)。
2. 拖拽 + 物理动画结合
  • 拖拽事件处理
    • onPanStart:记录拖拽初始位置;
    • onPanUpdate:实时更新小球位置;
    • onPanEnd:获取拖拽结束时的速度,创建物理模拟并触发动画;
  • 速度传递:将拖拽结束时的速度作为物理模拟的初始速度,让动画更贴合真实的拖拽体验。
3. 关键优化点
  • 动画与拖拽的衔接:拖拽开始时停止当前动画,避免动画和拖拽冲突;
  • 屏幕边界处理:实际开发中需添加边界检测,防止小球超出屏幕;
  • 性能优化:物理模拟的计算量较大,避免在动画过程中进行复杂的计算。

六、动画开发避坑指南

  1. 内存泄漏
    • 显式动画的AnimationController必须在dispose中释放;
    • 避免在initState中创建无限循环的动画,忘记停止;
  2. 性能问题
    • 避免在AnimatedBuilderbuilder函数中创建新的 Widget(如Text('${value}')),可提前缓存;
    • 复杂动画使用RepaintBoundary隔离重绘区域;
    • 避免同时进行多个高开销的动画(如大量元素的旋转 + 缩放);
  3. 动画卡顿
    • 网络图片提前预加载,避免动画过程中加载图片;
    • 减少动画过程中的布局计算(如LayoutBuilder);
    • 使用const构造函数创建静态子 Widget;
  4. Hero 动画坑点
    • 两个页面的Herotag 必须完全一致;
    • 避免 Hero 元素包含复杂的交互控件(如按钮);
    • 侧滑返回时的 Hero 动画需手动配置transitionOnUserGestures
  5. 物理动画坑点
    • 弹簧参数需反复调试,避免过度回弹或僵硬;
    • 拖拽速度的单位是pixelsPerSecond,需注意单位转换。

七、总结

Flutter 动画开发的学习路径是 “隐式动画→显式动画→转场动画→物理动画”,核心原则是 “按需选型、性能优先、贴近真实”:

  1. 简单动效(显隐、尺寸变化):使用隐式动画(AnimatedContainer/AnimatedOpacity),快速高效;
  2. 复杂交互动画(进度条、自定义曲线):使用显式动画(AnimationController+AnimatedBuilder),灵活可控;
  3. 页面转场:使用 Hero 动画,实现元素无缝过渡;
  4. 真实交互体验(拖拽、回弹):使用物理动画,模拟真实物理规律。

动画开发的核心不是 “炫技”,而是 “提升用户体验”—— 一个好的动画应该是 “润物细无声” 的,既让交互更生动,又不影响性能和使用。比如按钮点击的微小缩放、列表加载的淡入动画、页面切换的平滑过渡,这些细节能让应用的体验提升一个档次。希望本文的实战案例和原理解析,能让你避开动画开发的 “坑”,写出既严谨又生动的 Flutter 动画代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1015276.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深蓝词库转换:三分钟搞定全平台输入法词库同步

深蓝词库转换&#xff1a;三分钟搞定全平台输入法词库同步 【免费下载链接】imewlconverter ”深蓝词库转换“ 一款开源免费的输入法词库转换程序 项目地址: https://gitcode.com/gh_mirrors/im/imewlconverter 还在为换输入法时词库无法迁移而烦恼吗&#xff1f;深蓝词…

2025北京托福机构怎么选?这3家高分选手帮你划重点! - 品牌测评鉴赏家

2025北京托福机构怎么选?这3家高分选手帮你划重点!一、北京托福机构选择指南:避开套路,精准匹配需求 在教育资源扎堆的北京,面对五花八门的托福机构,如何避免被 “保过承诺” 迷惑,找到真正适合自己的课程?关键…

Cursor 又偷偷更新,这个功能太实用:Visual Editor for Cursor Browser

Cursor 又偷偷更新了&#xff1a;Visual Editor for Cursor Browser 超实用&#xff01; 是的&#xff0c;Cursor&#xff08;那个基于 VS Code 的 AI 代码编辑器&#xff09;在 2025年12月10-11日 左右的 2.2 版本 中&#xff0c;低调上线了 Visual Editor for Cursor Browse…

openpnp - Smoothieware - LPC17xx-DFU-Bootloader - 固件调试环境搭建

文章目录openpnp - Smoothieware - LPC17xx-DFU-Bootloader - 固件调试环境搭建概述笔记启动的脚本(start_eclipsecpp_with_msys2_arm_gcc_and_make.bat)中&#xff0c;要有arm-gcc工具链start_eclipsecpp_with_msys2_arm_gcc_and_make.bat更改openocd用到的硬件调试器拷贝JLin…

E-Hentai批量下载工具:高效管理数字收藏资源的最佳方案

在数字资源日益丰富的今天&#xff0c;如何高效管理和保存有价值的在线内容成为了许多用户的共同痛点。面对心仪的图库资源&#xff0c;传统的手动保存方式不仅效率低下&#xff0c;还容易导致文件混乱。针对这一需求&#xff0c;E-Hentai-Downloader提供了一个简单而强大的解决…

新的Unicode标准 18.0有些什么? 小篆字会进入标准!

今天逛了下Unicode.org的官方博客,看了下他们对明年18.0标准的讨论,发现一个有趣的事情,明年的标准会把小篆字收入标准作为新的字符。这些字符会编码在3D000~3FC3F这个区域。相关的工作文档,可以参见这个PDF文档,…

GUID为什么不会重复?

GUID为什么不会重复? GUID/UUID &#xff08;全局唯一标识符&#xff09;之所以被认为“几乎不会重复”&#xff0c;是因为其庞大的组合空间和精心设计的生成算法&#xff0c;使得在现实世界中重复的概率低到可以忽略不计。 以下是 GUID 不会重复的核心原因&#xff1a; 1. 庞…

深蓝词库转换:轻松打通全平台输入法数据壁垒

深蓝词库转换&#xff1a;轻松打通全平台输入法数据壁垒 【免费下载链接】imewlconverter ”深蓝词库转换“ 一款开源免费的输入法词库转换程序 项目地址: https://gitcode.com/gh_mirrors/im/imewlconverter 想要实现搜狗、百度、QQ、微软等主流输入法之间的词库自由迁…

【time-rs】time库 ConversionRange 错误类型详解(error/conversion_range.rs)

这是一个 Rust 时间库中的转换范围错误类型&#xff0c;用于表示类型转换时源值超出目标类型表示范围的情况。 1. 结构体定义 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ConversionRange;这是一个零大小类型&#xff08;ZST&#xff09;&#xff0c;表示转换…

理解 Cursor 的核心概念、优势和适用场景。

Cursor 的核心概念 Cursor 是一个AI 第一的代码编辑器&#xff08;AI-first code editor&#xff09;&#xff0c;它基于 Visual Studio Code (VS Code) 的开源代码分叉开发&#xff0c;由 Anysphere 公司打造。它的核心理念是将 AI 深度集成到编程工作中&#xff0c;让开发者…

雪花ID是什么?

雪花ID是什么&#xff1f; 雪花ID是由Twitter开源的分布式唯一ID生成算法&#xff0c;它通过一个64位的长整型ID&#xff0c;解决了在分布式系统中高效、有序地生成全局唯一标识符的难题。 &#x1f9e9; 核心结构与原理 雪花ID的核心在于将64位二进制数字划分为几个具有不同…

以空间为核心的信息感知与态势管控关键技术研究

——基于空间视频智能感知的新型高安全场景技术体系&#xff08;镜像视界&#xff08;浙江&#xff09;科技有限公司空间智能技术实践&#xff09;摘要在高安全仓储与地下硐室等复杂空间场景中&#xff0c;传统以二维视频监控和离散物联网监测为核心的安全管控体系&#xff0c;…

基于自适应启动策略的混合交叉动态约束多目标优化算法(MC-DCMOEA)求解CEC2018研究附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码及仿真咨询…

百度网盘直链解析工具:轻松获取高速下载链接的完整指南

还在为百度网盘的龟速下载而烦恼吗&#xff1f;baidu-wangpan-parse作为一款专业的百度网盘直链解析工具&#xff0c;能够巧妙绕过官方限速&#xff0c;让你重新体验全速下载的便捷。无论你是需要下载学习资料、工作文件还是个人资源&#xff0c;这款工具都能帮你轻松搞定。 【…

自学嵌入式day30,回收进程

父子进程关系与进程终止机制父子进程内存管理 子进程通过fork()创建时&#xff0c;初始阶段完全共享父进程的内存空间&#xff08;采用写时复制技术&#xff09;。只有当父子进程尝试修改同一内存区域时&#xff0c;内核才会为子进程分配独立的内存副本。这种机制优化了资源使用…

[iOS原理] Block的本质

[iOS原理] Block的本质 文章目录[iOS原理] Block的本质前置研究iOS内存五大分区栈区堆区全局区 / 静态区常量区代码区isa指针BlockBlock的本质Block的三种类型__block的本质ARC 在某些情况下会对 block 自动进行一次 copy 操作&#xff0c;将其从栈区移动到堆区Block的应用及其…

考虑可再生能源消纳的电热综合能源系统日前经济调度模型研究附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码及仿真咨询…

农作物检测和识别2:基于深度学习YOLOv12神经网络实现农作物检测和识别(含训练代码和数据集)

基于深度学习YOLOv12神经网络实现农作物检测和识别&#xff0c;其能识别检测出11种农作物检测&#xff1a;names: [bluegrass,chenopodium_album,cirsium_setosum,corn,sedge,cotton, nightshade, tomato, velvet,lettuce,radish] 具体图片见如下&#xff1a; 第一步&#xff…

计及N-k安全约束的含光热电站电力系统优化调度模型【IEEE14节点、118节点】附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码及仿真咨询…

2025低成本AI认证指南:从入门到进阶的高性价比路径盘点

人工智能已从前沿科技演变为驱动各行业变革的核心引擎。无论是希望提升职场竞争力的专业人士&#xff0c;还是寻求入行机会的毕业生&#xff0c;掌握AI技能都已成为一项重要需求。然而&#xff0c;面对市场上种类繁多的课程和动辄上万元的培训费用&#xff0c;许多人望而却步。…