flutter3_douyin:基于flutter3+dart3短视频直播实例|Flutter3.x仿抖音

flutter3-dylive 跨平台仿抖音短视频直播app实战项目。

全新原创基于flutter3.19.2+dart3.3.0+getx等技术开发仿抖音app实战项目。实现了类似抖音整屏丝滑式上下滑动视频、左右滑动切换页面模块,直播间进场/礼物动效,聊天等模块。

在这里插入图片描述

运用技术

  • 编辑器:vscode
  • 技术框架:flutter3.19.2+dart3.3.0
  • 路由/状态插件:get: ^4.6.6
  • 缓存服务:get_storage: ^2.1.1
  • 图片预览插件:photo_view: ^0.14.0
  • 刷新加载:easy_refresh^3.3.4
  • toast轻提示:toast^0.3.0
  • 视频套件:media_kit: ^1.1.10+1

在这里插入图片描述
在这里插入图片描述
Flutter-dyLive实现了类似抖音全屏上下滑动、左右切换页面效果。

左右滑动的同时,顶部状态栏+Tab菜单+底部bottomNavigationBar导航栏三者联动效果。

在这里插入图片描述

在这里插入图片描述

目录结构

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
本篇分享主要是短视频和直播模块,至于其它技术知识点,大家可以去看看之前分享的flutter3聊天实例文章。

https://blog.csdn.net/yanxinyun1990/article/details/136051099
https://blog.csdn.net/yanxinyun1990/article/details/136410049

flutter底部导航菜单

在这里插入图片描述
使用 bottomNavigationBar 组件实现底部导航页面模块切换。通过getx状态来联动控制底部导航栏背景颜色。

中间图标/图片按钮,使用了 Positioned 组件定位实现功能。

return Scaffold(
  backgroundColor: Colors.grey[50],
  body: pageList[pageCurrent],
  // 底部导航栏
  bottomNavigationBar: Theme(
    // Flutter去掉BottomNavigationBar底部导航栏的水波纹
    data: ThemeData(
      splashColor: Colors.transparent,
      highlightColor: Colors.transparent,
      hoverColor: Colors.transparent,
    ),
    child: Obx(() {
      return Stack(
        children: [
          Container(
            decoration: const BoxDecoration(
              border: Border(top: BorderSide(color: Colors.black54, width: .1)),
            ),
            child: BottomNavigationBar(
              backgroundColor: bottomNavigationBgcolor(),
              fixedColor: FStyle.primaryColor,
              unselectedItemColor: bottomNavigationItemcolor(),
              type: BottomNavigationBarType.fixed,
              elevation: 1.0,
              unselectedFontSize: 12.0,
              selectedFontSize: 12.0,
              currentIndex: pageCurrent,
              items: [
                ...pageItems
              ],
              onTap: (index) {
                setState(() {
                  pageCurrent = index;
                });
              },
            ),
          ),
          // 自定义底部导航栏中间按钮
          Positioned(
            left: MediaQuery.of(context).size.width / 2 - 15,
            top: 0,
            bottom: 0,
            child: InkWell(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  // Icon(Icons.tiktok, color: bottomNavigationItemcolor(centerDocked: true), size: 32.0,),
                  Image.asset('assets/images/applogo.png', width: 32.0, fit: BoxFit.contain,)
                  // Text('直播', style: TextStyle(color: bottomNavigationItemcolor(centerDocked: true), fontSize: 12.0),)
                ],
              ),
              onTap: () {
                setState(() {
                  pageCurrent = 2;
                });
              },
            ),
          ),
        ],
      );
    }),
  ),
);
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../styles/index.dart';
import '../../controllers/page_video_controller.dart';

// 引入pages页面
import '../pages/index/index.dart';
import '../pages/video/index.dart';
import '../pages/live/index.dart';
import '../pages/message/index.dart';
import '../pages/my/index.dart';

class Layout extends StatefulWidget {
  const Layout({super.key});

  
  State<Layout> createState() => _LayoutState();
}

class _LayoutState extends State<Layout> {
  PageVideoController pageVideoController = Get.put(PageVideoController());

  // page索引
  int pageCurrent = 0;
  // page页面
  List pageList = [const Index(), const FVideo(), const FLiveList(), const Message(), const My()];
  // tabs选项
  List pageItems = [
    const BottomNavigationBarItem(
      icon: Icon(Icons.home_outlined),
      label: '首页'
    ),
    const BottomNavigationBarItem(
      icon: Icon(Icons.play_arrow_outlined),
      label: '短视频'
    ),
    const BottomNavigationBarItem(
      icon: Icon(Icons.live_tv_rounded, color: Colors.transparent,),
      label: ''
    ),
    BottomNavigationBarItem(
      icon: Stack(
        alignment: const Alignment(4, -2),
        children: [
          const Icon(Icons.messenger_outline),
          FStyle.badge(1)
        ],
      ),
      label: '消息'
    ),
    BottomNavigationBarItem(
      icon: Stack(
        alignment: const Alignment(1.5, -1),
        children: [
          const Icon(Icons.person_outline),
          FStyle.badge(0, isdot: true)
        ],
      ),
      label: '我'
    )
  ];

  // 底部导航栏背景色
  Color bottomNavigationBgcolor() {
    int index = pageCurrent;
    int pageVideoTabIndex = pageVideoController.pageVideoTabIndex.value;
    Color color = Colors.white;
    if(index == 1) {
      if([1, 2, 3].contains(pageVideoTabIndex)) {
        color = Colors.white;
      }else {
        color = Colors.black;
      }
    }
    return color;
  }
  // 底部导航栏颜色
  Color bottomNavigationItemcolor({centerDocked = false}) {
    int index = pageCurrent;
    int pageVideoTabIndex = pageVideoController.pageVideoTabIndex.value;
    Color color = Colors.black54;
    if(index == 1) {
      if([1, 2, 3].contains(pageVideoTabIndex)) {
        color = Colors.black54;
      }else {
        color = Colors.white60;
      }
    }else if(index == 2 && centerDocked) {
      color = FStyle.primaryColor;
    }
    return color;
  }

  // ...
}

在这里插入图片描述

flutter3实现抖音沉浸式滑动

在这里插入图片描述
在这里插入图片描述
使用TabBar组件和PageView组件实现顶部菜单和页面联动切换效果。

return Scaffold(
  extendBodyBehindAppBar: true,
  appBar: AppBar(
    forceMaterialTransparency: true,
    backgroundColor: [1, 2, 3].contains(pageVideoController.pageVideoTabIndex.value) ? null : Colors.transparent,
    foregroundColor: [1, 2, 3].contains(pageVideoController.pageVideoTabIndex.value) ? Colors.black : Colors.white,
    titleSpacing: 1.0,
    leading: Obx(() => IconButton(icon: Icon(Icons.menu, color: tabColor(),), onPressed: () {},),),
    title: Obx(() {
      return TabBar(
        controller: tabController,
        tabs: pageTabs.map((v) => Tab(text: v)).toList(),
        isScrollable: true,
        tabAlignment: TabAlignment.center,
        overlayColor: MaterialStateProperty.all(Colors.transparent),
        unselectedLabelColor: unselectedTabColor(),
        labelColor: tabColor(),
        indicatorColor: tabColor(),
        indicatorSize: TabBarIndicatorSize.label,
        unselectedLabelStyle: const TextStyle(fontSize: 16.0, fontFamily: 'Microsoft YaHei'),
        labelStyle: const TextStyle(fontSize: 16.0, fontFamily: 'Microsoft YaHei', fontWeight: FontWeight.w600),
        dividerHeight: 0,
        labelPadding: const EdgeInsets.symmetric(horizontal: 10.0),
        indicatorPadding: const EdgeInsets.symmetric(horizontal: 5.0),
        onTap: (index) {
          pageVideoController.updatePageVideoTabIndex(index); // 更新索引
          pageController.jumpToPage(index);
        },
      );
    }),
    actions: [
      Obx(() => IconButton(icon: Icon(Icons.search, color: tabColor(),), onPressed: () {},),),
    ],
  ),
  body: Column(
    children: [
      Expanded(
        child: Stack(
          children: [
            /// 水平滚动模块
            PageView(
              // 自定义滚动行为(支持桌面端滑动、去掉滚动条槽)
              scrollBehavior: PageScrollBehavior().copyWith(scrollbars: false),
              scrollDirection: Axis.horizontal,
              controller: pageController,
              onPageChanged: (index) {
                pageVideoController.updatePageVideoTabIndex(index); // 更新索引
                setState(() {
                  tabController.animateTo(index);
                });
              },
              children: [
                ...pageModules
              ],
            ),
          ],
        ),
      ),
    ],
  ),
);
PageVideoController pageVideoController = Get.put(PageVideoController());

List<String> pageTabs = ['热点', '长视频', '文旅', '商城', '关注', '同城服务', '推荐'];
final pageModules = [
  const HotModule(),
  const LongVideoModule(),
  const TripModule(),
  const MallModule(),
  const FavorModule(),
  const NearModule(),
  const RecommendModule()
];
late final TabController tabController = TabController(initialIndex: pageVideoController.pageVideoTabIndex.value, length: pageTabs.length, vsync: this);
// 页面controller
late final PageController pageController = PageController(initialPage: pageVideoController.pageVideoTabIndex.value, viewportFraction: 1.0);


void dispose() {
  tabController.dispose();
  pageController.dispose();
  super.dispose();
}

flutter实现短视频底部播放拖拽条

在这里插入图片描述
短视频底部又一条mini播放进度条,可实时显示视频播放进度,可拖拽到指定播放时间点。

// flutter滑动短视频模块  Q:282310962

return Container(
  color: Colors.black,
  child: Column(
    children: [
      Expanded(
        child: Stack(
          children: [
            /// 垂直滚动模块
            PageView.builder(
              // 自定义滚动行为(支持桌面端滑动、去掉滚动条槽)
              scrollBehavior: PageScrollBehavior().copyWith(scrollbars: false),
              scrollDirection: Axis.vertical,
              controller: pageController,
              onPageChanged: (index) async {
                ...
              },
              itemCount: videoList.length,
              itemBuilder: (context, index) {
                return Stack(
                  children: [
                    // 视频区域
                    Positioned(
                      top: 0,
                      left: 0,
                      right: 0,
                      bottom: 0,
                      child: GestureDetector(
                        child: Stack(
                          children: [
                            // 短视频插件
                            Visibility(
                              visible: videoIndex == index,
                              child: Video(
                                controller: videoController,
                                fit: BoxFit.cover,
                                // 无控制条
                                controls: NoVideoControls,
                              ),
                            ),
                            // 播放/暂停按钮
                            StreamBuilder(
                              stream: player.stream.playing,
                              builder: (context, playing) {
                                return Visibility(
                                  visible: playing.data == false,
                                  child: Center(
                                    child: IconButton(
                                      padding: EdgeInsets.zero,
                                      onPressed: () {
                                        player.playOrPause();
                                      },
                                      icon: Icon(
                                        playing.data == true ? Icons.pause : Icons.play_arrow_rounded,
                                        color: Colors.white70,
                                        size: 70,
                                      ),
                                    ),
                                  ),
                                );
                              },
                            ),
                          ],
                        ),
                        onTap: () {
                          player.playOrPause();
                        },
                      ),
                    ),
                    // 右侧操作栏
                    Positioned(
                      bottom: 15.0,
                      right: 10.0,
                      child: Column(
                        ...
                      ),
                    ),
                    // 底部信息区域
                    Positioned(
                      bottom: 15.0,
                      left: 10.0,
                      right: 80.0,
                      child: Column(
                        ...
                      ),
                    ),
                    // 播放mini进度条
                    Positioned(
                      bottom: 0.0,
                      left: 10.0,
                      right: 10.0,
                      child: Visibility(
                        visible: videoIndex == index && position > Duration.zero,
                        child: Listener(
                          child: SliderTheme(
                            data: const SliderThemeData(
                              trackHeight: 2.0,
                              thumbShape: RoundSliderThumbShape(enabledThumbRadius: 4.0), // 调整滑块的大小
                              // trackShape: RectangularSliderTrackShape(), // 使用矩形轨道形状
                              overlayShape: RoundSliderOverlayShape(overlayRadius: 0), // 去掉Slider默认上下边距间隙
                              inactiveTrackColor: Colors.white24, // 设置非活动进度条的颜色
                              activeTrackColor: Colors.white, // 设置活动进度条的颜色
                              thumbColor: Colors.pinkAccent, // 设置滑块的颜色
                              overlayColor: Colors.transparent, // 设置滑块覆盖层的颜色
                            ),
                            child: Slider(
                              value: sliderValue,
                              onChanged: (value) async {
                                // debugPrint('当前视频播放时间$value');
                                setState(() {
                                  sliderValue = value;
                                });
                                // 跳转播放时间
                                await player.seek(duration * value.clamp(0.0, 1.0));
                              },
                              onChangeEnd: (value) async {
                                setState(() {
                                  sliderDraging = false;
                                });
                                // 继续播放
                                if(!player.state.playing) {
                                  await player.play();
                                }
                              },
                            ),
                          ),
                          onPointerMove: (e) {
                            setState(() {
                              sliderDraging = true;
                            });
                          },
                        ),
                      ),
                    ),
                    // 视频播放时间
                    Positioned(
                      bottom: 90.0,
                      left: 10.0,
                      right: 10.0,
                      child: Visibility(
                        visible: sliderDraging,
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Text(position.label(reference: duration), style: const TextStyle(color: Colors.white, fontSize: 16.0, fontWeight: FontWeight.w600),),
                            Container(
                              margin: const EdgeInsets.symmetric(horizontal: 7.0),
                              child: const Text('/', style: TextStyle(color: Colors.white54, fontSize: 10.0,),),
                            ),
                            Text(duration.label(reference: duration), style: const TextStyle(color: Colors.white54, fontSize: 16.0, fontWeight: FontWeight.w600),),
                          ],
                        ),
                      ),
                    ),
                  ],
                );
              },
            ),
            /// 固定层
            // 红包
            Positioned(
              left: 15.0,
              top: MediaQuery.of(context).padding.top + 20,
              child: Container(
                height: 40.0,
                width: 40.0,
                decoration: BoxDecoration(
                  color: Colors.black12,
                  borderRadius: BorderRadius.circular(100.0),
                ),
                child: UnconstrainedBox(
                  child: Image.asset('assets/images/time-hb.png', width: 30.0, fit: BoxFit.contain,),
                ),
              ),
            ),
          ],
        ),
      ),
    ],
  ),
);

flutter3直播模块

在这里插入图片描述
在这里插入图片描述

// 商品购买动效
Container(
  ...
),

// 加入直播间动效
const AnimationLiveJoin(
  joinQueryList: [
    {'avatar': 'assets/images/logo.png', 'name': 'andy'},
    {'avatar': 'assets/images/logo.png', 'name': 'jack'},
    {'avatar': 'assets/images/logo.png', 'name': '一条咸鱼'},
    {'avatar': 'assets/images/logo.png', 'name': '四季平安'},
    {'avatar': 'assets/images/logo.png', 'name': '叶子'},
  ],
),

// 送礼物动效
const AnimationLiveGift(
  giftQueryList: [
    {'label': '小心心', 'gift': 'assets/images/gift/gift1.png', 'user': 'Jack', 'avatar': 'assets/images/avatar/uimg2.jpg', 'num': 12},
    {'label': '棒棒糖', 'gift': 'assets/images/gift/gift2.png', 'user': 'Andy', 'avatar': 'assets/images/avatar/uimg6.jpg', 'num': 36},
    {'label': '大啤酒', 'gift': 'assets/images/gift/gift3.png', 'user': '一条咸鱼', 'avatar': 'assets/images/avatar/uimg1.jpg', 'num': 162},
    {'label': '人气票', 'gift': 'assets/images/gift/gift4.png', 'user': 'Flower', 'avatar': 'assets/images/avatar/uimg5.jpg', 'num': 57},
    {'label': '鲜花', 'gift': 'assets/images/gift/gift5.png', 'user': '四季平安', 'avatar': 'assets/images/avatar/uimg3.jpg', 'num': 6},
    {'label': '捏捏小脸', 'gift': 'assets/images/gift/gift6.png', 'user': 'Alice', 'avatar': 'assets/images/avatar/uimg4.jpg', 'num': 28},
    {'label': '你真好看', 'gift': 'assets/images/gift/gift7.png', 'user': '叶子', 'avatar': 'assets/images/avatar/uimg7.jpg', 'num': 95},
    {'label': '亲吻', 'gift': 'assets/images/gift/gift8.png', 'user': 'YOYO', 'avatar': 'assets/images/avatar/uimg8.jpg', 'num': 11},
    {'label': '玫瑰', 'gift': 'assets/images/gift/gift12.png', 'user': '宇辉', 'avatar': 'assets/images/avatar/uimg9.jpg', 'num': 3},
    {'label': '私人飞机', 'gift': 'assets/images/gift/gift16.png', 'user': 'Hison', 'avatar': 'assets/images/avatar/uimg10.jpg', 'num': 273},
  ],
),

// 直播弹幕+商品讲解
Container(
  margin: const EdgeInsets.only(top: 7.0),
  height: 200.0,
  child: Row(
    crossAxisAlignment: CrossAxisAlignment.end,
    children: [
      Expanded(
        child: ListView.builder(
          padding: EdgeInsets.zero,
          itemCount: liveJson[index]['message']?.length,
          itemBuilder: (context, i) => danmuList(liveJson[index]['message'])[i],
        ),
      ),
      SizedBox(
        width: isVisibleGoodsTalk ? 7 : 35,
      ),
      // 商品讲解
      Visibility(
        visible: isVisibleGoodsTalk,
        child: Column(
          ...
        ),
      ),
    ],
  ),
),

// 底部工具栏
Container(
  margin: const EdgeInsets.only(top: 7.0),
  child: Row(
    ...
  ),
),

直播间从右到左进入直播间动画及礼物左侧滑入效果,通过 SlideTransition 组件实现进场动画。

return SlideTransition(
  position: animationFirst ? animation : animationMix,
  child: Container(
    alignment: Alignment.centerLeft,
    margin: const EdgeInsets.only(top: 7.0),
    padding: const EdgeInsets.symmetric(horizontal: 7.0,),
    height: 23.0,
    width: 250,
    decoration: const BoxDecoration(
      gradient: LinearGradient(
        begin: Alignment.centerLeft,
        end: Alignment.centerRight,
        colors: [
          Color(0xFF6301FF), Colors.transparent
        ],
      ),
      borderRadius: BorderRadius.horizontal(left: Radius.circular(10.0)),
    ),
    child: joinList!.isNotEmpty ? 
      Text('欢迎 ${joinList![0]['name']} 加入直播间', style: const TextStyle(color: Colors.white, fontSize: 14.0,),)
      :
      Container()
    ,
  ),
);
class _AnimationLiveJoinState extends State<AnimationLiveJoin> with TickerProviderStateMixin {
  // 动画控制器
  late AnimationController controller = AnimationController(
    vsync: this,
    duration: const Duration(milliseconds: 500), // 第一个动画持续时间
  );
  late AnimationController controllerMix = AnimationController(
    vsync: this,
    duration: const Duration(milliseconds: 1000), // 第二个动画持续时间
  );
  // 动画
  late Animation<Offset> animation = Tween(begin: const Offset(2.5, 0), end: const Offset(0, 0)).animate(controller);
  late Animation<Offset> animationMix = Tween(begin: const Offset(0, 0), end: const Offset(-2.5, 0)).animate(controllerMix);

  Timer? timer;
  // 是否第一个动画
  bool animationFirst = true;
  // 是否空闲
  bool idle = true;
  // 加入直播间数据列表
  List? joinList;

  
  void initState() {
    super.initState();

    joinList = widget.joinQueryList!.toList();

    runAnimation();
    animation.addListener(() {
      if(animation.status == AnimationStatus.forward) {
        debugPrint('第一个动画进行中');
        idle = false;
        setState(() {});
      }else if(animation.status == AnimationStatus.completed) {
        debugPrint('第一个动画结束');
        animationFirst = false;
        if(controllerMix.isCompleted || controllerMix.isDismissed) {
          timer = Timer(const Duration(seconds: 2), () {
            controllerMix.forward();
            debugPrint('第二个动画开始');
          });
        }
        setState(() {});
      }
    });
    animationMix.addListener(() {
      if(animationMix.status == AnimationStatus.forward) {
        setState(() {});
      }else if(animationMix.status == AnimationStatus.completed) {
        animationFirst = true;
        controller.reset();
        controllerMix.reset();
        if(joinList!.isNotEmpty) {
          joinList!.removeAt(0);
        }
        idle = true;
        // 执行下一个数据
        runAnimation();
        setState(() {});
      }
    });
  }

  void runAnimation() {
    if(joinList!.isNotEmpty) {
      // 空闲状态才能执行,防止添加数据播放状态混淆
      if(idle == true) {
        if(controller.isCompleted || controller.isDismissed) {
          setState(() {});
          timer = Timer(Duration.zero, () {
            controller.forward();
          });
        }
      }
    }
  }

  
  void dispose() {
    controller.dispose();
    controllerMix.dispose();
    timer?.cancel();
    super.dispose();
  }

}

另外项目中还加入了之前flutter3聊天功能模块。

Ok,综上就是flutter3+dart3仿抖音app实例的一些技术知识分享,希望对大家有所帮助。

最后附上两个实例项目

  • uni-app+vue3+vk-uview多端直播商城项目
    https://blog.csdn.net/yanxinyun1990/article/details/135329724

  • vue3+vite4中后台管理系统
    https://blog.csdn.net/yanxinyun1990/article/details/130144212

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Web前端Html的表单

表单的关键字&#xff1a; form标签表示一个表单区域 action“后端地址” method“提交数据方式:get/post” input 单行输入框 type“text” 文本 name“定义名称 名字自定义” 向后端提交的键 readonly“readonly” 只读&#xff0c;不可修改&#xff0c;但是可以提交 disab…

Django 三板斧、静态文件、request方法

【一】三板斧 【1】HttpResponse &#xff08;1&#xff09;介绍 HttpResponse是Django中的一个类&#xff0c;用于构建HTTP响应对象。它允许创建并返回包含特定内容的HTTP响应。 &#xff08;2&#xff09;使用 导入HttpResponse类 from django.http import HttpResponse创…

C++ unordered_set和unordered_map

哈希 1. unordered_set/unordered_map1.1 背景1.2 unordered_set1.2.1 特性1.2.2 常用方法 1.3 unordered_map1.3.1 特性1.3.2 常用方法 2. 哈希2.1概念2.2 哈希冲突2.2.1哈希函数2.2.2 解决哈希冲突2.2.2.1 闭散列2.2.2.2 开散列 1. unordered_set/unordered_map 1.1 背景 之…

Rust并发编程thread多线程和channel消息传递

安全高效的处理并发是 Rust 诞生的目的之一&#xff0c;主要解决的是服务器高负载承受能力。 并发&#xff08;concurrent&#xff09;的概念是指程序不同的部分独立执行&#xff0c;这与并行&#xff08;parallel&#xff09;的概念容易混淆&#xff0c;并行强调的是"同…

如何理解OSI七层模型?

一、是什么 OSI &#xff08;Open System Interconnect&#xff09;模型全称为开放式通信系统互连参考模型&#xff0c;是国际标准化组织 ( ISO ) 提出的一个试图使各种计算机在世界范围内互连为网络的标准框架 OSI将计算机网络体系结构划分为七层&#xff0c;每一层实现各自…

存储随笔原创科普视频首播~

一周之前&#xff0c;存储随笔创建了B站账号。小编利用上个周末休息时间专门研究了B站视频录制的各种方案。发现并没有想象的很容易&#xff0c;先花了很长时间准备了一个PPT&#xff0c;再准备演讲大纲&#xff0c;最终磕磕绊绊完成了首期原创视频录制&#xff01; 可能不尽如…

PCB布线中晶振电容、电源大小电容、电源电容的设计细节

嵌入式软硬件爱好者 一张手册走天下。嵌入式单片机/Linux/Openwrt/电子电路技术交流分享。//主打一个技术层面的剑走偏锋&#xff0c;直击众人重视和不重视的重点//专注基础&#xff0c;才能走的更远 晶振电容 晶振旁边的电容在电路设计中不是用于滤波的。实际上&#xff0c;…

中国疆域从古至今版图演变,中国历史各个朝代地图大全

一、图片描述 每个朝代都有数十张地图&#xff0c;朝代疆域全图重点区域地图&#xff0c;图片是JPG格式&#xff0c;都是高清地图&#xff0c;行政名称清晰可见&#xff0c;非常适合喜欢历史的朋友。本套历史朝代地图&#xff0c;大小1.32G&#xff0c;18个压缩文件。 二、图…

ShardingSphere水平分表——开发经验(2)

1. 什么场景下分表&#xff1f; 数据量过大或者数据库表对应的磁盘文件过大。 Q&#xff1a;多少数据分表&#xff1f; A&#xff1a;网上有人说1kw&#xff0c;2kw&#xff1f;不准确。 1、一般看字段的数量&#xff0c;有没有包含text类型的字段。我们的主表里面是不允许有t…

C语言数据结构之归并排序

疏雨池塘见 微风襟袖知 目录 归并排序的介绍 基本思想 时间复杂度分析 ⭐归并排序步骤 空间复杂度分析 代码展示 ✨归并排序的非递归 代码展示 总结&#x1f525; 归并排序的介绍 归并排序&#xff0c;是创建在归并操作上的一种有效的排序算法。算法是采用分治法&#xff…

项目1-加法计算器

1.创建项目 2.导入前端代码 2.1 static包内 2.2 测试前端代码是否有误 显示成功说明无误 2.3 定义用户接口 请求路径&#xff1a;calc/sum 请求方式&#xff1a;GET/POST 接口描述&#xff1a;计算两个整数相加 请求参数: 参数名类型是否必须备注num1Integer是参与计算的第…

瑞萨杯(一)

基础信息 RA6M5&#xff1a;ARM V8架构&#xff0c;24MHz外置晶振&#xff0c;200MHz主频 SCI&#xff08;Serial Communications Interface&#xff09;&#xff0c;意为串行通信接口 参考链接&#xff1a; 【瑞萨RA系列FSP库开发】RASCKeil的环境搭建_瑞萨ra mdk-CSDN博客…

主干网络篇 | YOLOv8改进之在主干网络中引入密集连接卷积网络DenseNet

前言:Hello大家好,我是小哥谈。DenseNet(密集连接卷积网络)是一种深度学习神经网络架构,它在2017年由Gao Huang等人提出。DenseNet的核心思想是通过密集连接(dense connection)来促进信息的流动和共享。在传统的卷积神经网络中,每个层的输入只来自于前一层的输出。而在…

C语言之strsep用法实例(八十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

【Python音视频技术】Python音视频技术系列文章2---视频提取音频转换文字

接上一篇文章 【Python音视频技术】玩AI视频创作引发写Python音视频技术系列文章1---视频添加字幕 之前我想在视频中提取音频转换文字&#xff0c; 当时是用 PC剪映专业版搞定的&#xff0c; 详情见 【AI应用】模仿爆款视频二次创作短视频操作步骤 。 这里我准备用pytho…

铁道障碍物检测6种YOLOV8

铁道障碍物检测6种&#xff0c;采用YOLOV8训练&#xff0c;得到PT模型&#xff0c;然后转换成ONNX模型&#xff0c;OPENCV调用 铁道障碍物检测6种YOLOV8

android Fragment 生命周期 方法调用顺序

文章目录 Introlog 及结论代码 Intro 界面设计&#xff1a;点击左侧按钮&#xff0c;会将右侧 青色的RightFragment 替换成 黄色的AnotherRightFragment&#xff0c;而这两个 Fragment 的生命周期方法都会打印日志。 所以只要看执行结果中的日志&#xff0c;就可以知道 Fragme…

Linux 系统 快速卸载docker

(卸载前一定要做好相关数据的备份) 卸载&#xff1a; 第一种卸载方法 1、查询docker安装过的包&#xff1a; yum list installed | grep docker 2、删除安装包&#xff1a; yum remove docker-ce.x86_64 ddocker-ce-cli.x86_64 -y 3、删除镜像/容器等 rm -rf /var/lib/dock…

IT运维服务规范标准与实施细则

一、 总则 本部分规定了 IT 运维服务支撑系统的应用需求&#xff0c;包括 IT 运维服务模型与模式、 IT 运维服务管理体系、以及 IT 运维服务和管理能力评估与提升途径。 二、 参考标准 下列文件中的条款通过本部分的引用而成为本部分的条款。凡是注日期的引用文件&#xff0c…

基于QT的实现的人脸识别、人脸标记、人脸比对

该项目使用的人脸模型框架采用的是seetaface开源版本&#xff0c;经过测试发现效果还算可以。 人脸识别的效果图如下: 人脸比对的效果图如下&#xff1a; 鉴于测试识别的精度特意找了不同两人相似的人脸进行比对&#xff0c;效果如下图&#xff1a; 由于该模型采用的阈值是0.6…