news 2026/9/1 1:23:23

刘海屏适配全攻略:安全区原理与多端实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
刘海屏适配全攻略:安全区原理与多端实现

去年秋天改版项目的时候,前端群里出现了一句很有意思的话:“你说喜欢海,我以为是我的齐刘海。”大家正在感慨产品经理又改了需求,结果发现这句话其实是从一张移动端 UI 稿里截出来的。UI 设计师的本意是“用户喜欢大海”,但到了前端这边,看到“海”和“刘海”放在一起,第一反应却是:又要调刘海屏适配了。

没错,对于天天和移动端页面打交道的人来说,“刘海”不是一个发型梗,而是一个实打实的技术难点。从 iPhone X 发布开始,刘海屏、挖孔屏、水滴屏轮番上阵,屏幕顶部的传感器区域、底部的 Home Indicator 横条,都会对页面的布局产生肉眼可见的挤压。如果适配不到位,就会出现页面顶部被传感器遮挡、底部按钮被手势条挡住、横向滑动内容被圆角裁切等一系列问题。

本文就围绕“红色感叹号这个‘齐刘海’”展开,完整梳理移动端刘海屏适配的原理、CSS 写法、Android 端处理方式,以及 H5、小程序、uni-app 中的常见适配策略。文章会包含可直接复制的代码示例、完整小案例和踩坑记录,适合刚接触移动端适配的前端新人,也适合正在做多端兼容的进阶开发者。

1. 背景与核心概念

1.1 刘海屏和安全区是什么

刘海屏指的是屏幕顶部存在一块凹槽区域,用来放置前置摄像头、听筒、Face ID 传感器等硬件。在 iPhone X 以及后续机型上,这块凹槽是黑色的,视觉效果上就像一个“刘海”。

如果页面默认按照旧机型的矩形安全区域渲染,那么刘海区域会直接遮挡状态栏下方的页面内容。除了顶部刘海,iPhone 底部还有一条 Home Indicator 横条,同样会覆盖页面底部内容。

为了解决这个问题,苹果在 iOS 11 中引入了 Safe Area(安全区)的概念。安全区是指屏幕中不受圆角、刘海、Home Indicator 影响的区域。开发者需要保证关键内容和可交互控件都处于安全区范围内。

Android 端从 Android P(API 28)开始官方支持 DisplayCutout 接口,用来获取屏幕上的刘海区域、挖孔区域坐标。不同厂商的机型差异较大,但整体思路是一致的:获取不可用区域,然后预留出足够的 padding 或 margin。

1.2 为什么需要前端主动适配

有同学会问:系统状态栏不是会自动占据顶部吗?为什么还要前端适配?

这里需要理清一个关键点:状态栏属于系统 UI,但页面内容默认是在状态栏下方展示的。在 WebView 中,如果页面没有开启全屏或者没有设置viewport-fit=cover,浏览器会主动把页面约束在安全区内,内容不会跑到刘海下面。

但问题在于,很多移动端页面为了实现沉浸式体验,会主动设置viewport-fit=cover,让页面延伸到整个屏幕。这时页面就不再被浏览器约束在安全区内,开发者也必须自己处理安全区边界。否则就会出现下面的情况:

  • 顶部标题栏被刘海遮住
  • 右侧按钮被刘海区域顶掉
  • 底部固定栏与 Home Indicator 重叠
  • 页面横屏时,内容被圆角切掉

所以,刘海屏适配的本质是:你选择了“全屏渲染”,就必须自己承担安全区边界计算的责任。

1.3 常见的刘海屏形态

目前市面上的异形屏主要分为三类:

类型代表机型主要特点
刘海屏iPhone X/XS/XR、华为 Mate 20(部分)顶部居中凹槽
水滴屏华为/荣耀/OPPO/vivo 大量机型顶部居中较小的圆形凹槽
挖孔屏荣耀/小米/三星部分机型左上角或居中的圆形开孔

另外还有一种不太算“刘海”但同样影响布局的情况,就是屏幕底部的手势条。iOS 的 Home Indicator 和 Android 全面屏手势提示条,都会占用底部区域。适配时也需要一并考虑。

2. 环境准备与版本说明

2.1 开发环境

本文示例主要以 Web 前端为主,涉及 H5 页面、小程序和 uni-app 三种场景。建议环境如下:

  • 操作系统:Windows 10 / macOS 任意版本均可
  • 浏览器:Chrome 最新版、Safari
  • 调试工具:Chrome DevTools 的设备模拟器、微信开发者工具
  • 语言:HTML、CSS、JavaScript
  • 框架:原生 Web 示例 + Vue 3 示例 + 微信小程序示例

版本不需要完全一致,下面演示的核心是 CSS 中的env()constant()函数,以及 Android 的DisplayCutout接口,这些都是比较稳定的能力,不依赖特定框架。

2.2 待适配的设备范围

适配工作开始前,建议先明确测试设备清单:

  • iOS:iPhone X、iPhone 11、iPhone 12/13/14 全系,以及后续刘海屏机型
  • Android:带刘海或挖孔的主流机型,至少覆盖 3 到 5 款
  • 工具:Chrome 模拟器中的 iPhone X 预设、微信开发者工具中的 iPhone X 模拟

如果团队没有这么多真机,至少要保证 iOS 端覆盖到位,因为 iOS 的刘海屏适配规则最严格。

3. 核心适配方案拆解

3.1 第一步:viewport-fit=cover

在 H5 页面中,适配刘海屏的第一个前提是设置viewportviewport-fit属性。

默认情况下,viewport-fit=auto,页面宽度等于安全区宽度。浏览器会把页面限制在安全区内,左右两侧不会延伸到屏幕边缘。

当我们需要页面全屏显示时,需要把viewport-fit设置为cover

<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">

设置之后,页面会铺满整个屏幕,包括刘海区域和底部 Home Indicator 区域。

此时必须在 CSS 中配合env(safe-area-inset-*)使用,否则内容就会被刘海遮挡。

常用写法:

body { padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom); padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right); }

关于safe-area-inset-*四个方向:

  • safe-area-inset-top:顶部安全区距离,刘海屏上有刘海时大于 0
  • safe-area-inset-bottom:底部安全区距离,有 Home Indicator 时大于 0
  • safe-area-inset-left:左侧安全区距离,横屏时如果存在圆角或刘海,可能大于 0
  • safe-area-inset-right:右侧安全区距离,横屏时可能大于 0

3.2 第二步:constant() 与 env() 兼容

env()是较新的 CSS 函数,但 iOS 11.0 到 iOS 11.1 使用的是constant(),而且constant()已经被废弃,只是用来兼容老版本。

更安全的写法是把constant()写在前面,env()写在后面:

.safe-top { padding-top: constant(safe-area-inset-top); padding-top: env(safe-area-inset-top); }

如果浏览器支持env(),后面的声明会覆盖前面的声明;如果不支持,则会使用constant()。需要注意的是,旧版浏览器在解析到不认识的函数时,会直接丢弃这一条声明,所以顺序不能反。

在实际项目中,更推荐使用 CSS 变量统一处理:

:root { --safe-top: constant(safe-area-inset-top); --safe-top: env(safe-area-inset-top); --safe-bottom: constant(safe-area-inset-bottom); --safe-bottom: env(safe-area-inset-bottom); } .page-header { padding-top: var(--safe-top); } .page-footer { padding-bottom: var(--safe-bottom); }

这样后续只需要维护 CSS 变量,代码会干净很多。

3.3 Android 刘海屏适配

Android 端从 Android 9(API 28)开始提供DisplayCutout接口,用来获取屏幕的刘海区域。Android 应用默认的刘海屏适配方式是:在非全屏状态下,系统会自动把内容布局在安全区内。

但对于 WebView 页面,情况会复杂一些。Android WebView 本身会遵守系统安全区,但部分 App 为了让 H5 页面铺满屏幕,可能会在原生层面设置全屏渲染。这时 H5 页面拿不到类似于 iOSenv()的浏览器自动变量,只能通过 JS 桥接获取刘海高度。

常见做法是原生端在 WebView 注入一段 JavaScript,把刘海高度通过window变量传递给 H5:

// 原生注入的代码 window.SAFE_AREA_TOP = 88; window.SAFE_AREA_BOTTOM = 34;

H5 侧在页面加载后读取这些变量,并添加对应的 CSS 类:

// 在页面加载完成后判断 document.addEventListener('DOMContentLoaded', () => { const top = window.SAFE_AREA_TOP || 0; const bottom = window.SAFE_AREA_BOTTOM || 0; if (top > 0) { document.documentElement.style.setProperty('--safe-top', top + 'px'); } if (bottom > 0) { document.documentElement.style.setProperty('--safe-bottom', bottom + 'px'); } });

对于纯 Android 原生应用,可以使用WindowInsetsCompat.getDisplayCutout()来获取刘海区域。

3.4 小程序和 uni-app 的适配

微信小程序提供了wx.getSystemInfoSync()wx.getMenuButtonBoundingClientRect()等接口。在小程序开发中,适配刘海屏最常用的方式是获取胶囊按钮的位置,然后动态计算导航栏高度。

下面是一个获取导航栏高度的常用代码:

const systemInfo = wx.getSystemInfoSync(); const menuRect = wx.getMenuButtonBoundingClientRect(); const statusBarHeight = systemInfo.statusBarHeight; // 状态栏高度 const menuTop = menuRect.top; // 胶囊按钮顶部距离屏幕顶部距离 const menuHeight = menuRect.height; // 胶囊按钮高度 // 导航栏实际高度 const navBarHeight = (menuTop - statusBarHeight) * 2 + menuHeight;

在 uni-app 中,可以直接使用官方提供的uni.getSystemInfoSync()获取safeAreaInsets

const systemInfo = uni.getSystemInfoSync(); const safeArea = systemInfo.safeAreaInsets; console.log(safeArea.top); // 顶部安全距离 console.log(safeArea.bottom); // 底部安全距离

需要注意,safeAreaInsets在某些低版本基础库中可能不存在,使用前建议做兼容判断。

4. 完整实战案例:一个 H5 页面适配刘海屏

下面完成一个完整的适配案例。页面包含顶部标题栏、中间内容区和底部操作栏,这是移动端最典型的三段式布局。

4.1 创建项目结构

项目结构非常简单:

notch-adapt-demo/ ├── index.html ├── css/ │ └── style.css └── js/ └── main.js

4.2 编写 HTML

<!-- 文件路径:index.html --> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, user-scalable=no"> <title>刘海屏适配示例</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <header class="header"> <button class="header-back">返回</button> <h1 class="header-title">商品详情</h1> <button class="header-more">更多</button> </header> <main class="content"> <section class="card"> <h2>什么是刘海屏适配?</h2> <p>刘海屏适配的核心是安全区处理。在设置 viewport-fit=cover 后,页面内容会铺满整个屏幕,如果不对安全区做处理,刘海区域和底部手势条会遮挡页面内容。</p> </section> <section class="card"> <h2>适配核心方案</h2> <p>使用 constant() 和 env() 函数读取 safe-area-inset-* 变量,为页面预留安全距离。</p> </section> </main> <footer class="footer"> <div class="footer-total">合计:¥ 299.00</div> <button class="footer-button">立即购买</button> </footer> <script src="js/main.js"></script> </body> </html>

4.3 编写 CSS

这是适配的核心部分。页面使用弹性布局,上下固定,中间可滚动。

/* 文件路径:css/style.css */ :root { --safe-top: 0px; --safe-bottom: 0px; --header-height: 44px; --footer-height: 56px; } /* iOS 兼容写法 */ @supports (padding-top: constant(safe-area-inset-top)) { :root { --safe-top: constant(safe-area-inset-top); --safe-bottom: constant(safe-area-inset-bottom); } } @supports (padding-top: env(safe-area-inset-top)) { :root { --safe-top: env(safe-area-inset-top); --safe-bottom: env(safe-area-inset-bottom); } } * { margin: 0; padding: 0; box-sizing: border-box; } html, body { height: 100%; font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", sans-serif; background-color: #f5f5f5; } body { display: flex; flex-direction: column; } /* ========== 顶部导航栏 ========== */ .header { position: fixed; top: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: space-between; height: calc(var(--header-height) + var(--safe-top)); padding-top: var(--safe-top); padding-left: calc(16px + var(--safe-left, 0px)); padding-right: calc(16px + var(--safe-right, 0px)); background-color: #ffffff; border-bottom: 1px solid #ebebeb; z-index: 100; } .header-back, .header-more { min-width: 44px; height: 44px; border: none; background: transparent; font-size: 16px; color: #333333; cursor: pointer; } .header-title { font-size: 17px; font-weight: 600; color: #222222; } /* ========== 中间内容区 ========== */ .content { flex: 1; padding: calc(var(--header-height) + var(--safe-top) + 16px) 16px calc(var(--footer-height) + var(--safe-bottom) + 16px); overflow-y: auto; } .card { background-color: #ffffff; border-radius: 12px; padding: 20px; margin-bottom: 16px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); } .card h2 { font-size: 18px; margin-bottom: 12px; color: #222222; } .card p { font-size: 15px; line-height: 1.7; color: #555555; } /* ========== 底部操作栏 ========== */ .footer { position: fixed; bottom: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: space-between; height: calc(var(--footer-height) + var(--safe-bottom)); padding-bottom: var(--safe-bottom); padding-left: 16px; padding-right: 16px; background-color: #ffffff; border-top: 1px solid #ebebeb; z-index: 100; } .footer-total { font-size: 16px; color: #333333; } .footer-total::first-line { font-weight: 600; color: #ff5000; } .footer-button { height: 40px; padding: 0 24px; border: none; border-radius: 20px; background-color: #ff5000; color: #ffffff; font-size: 15px; cursor: pointer; }

在这个示例中,顶部导航栏和底部操作栏都使用了position: fixed,并分别通过padding-toppadding-bottom撑出安全区。中间内容区的上下 padding 也把安全区计算进去了,这样内容不会在滚动时被遮住。

4.4 编写 JavaScript

JS 部分主要处理 Android WebView 环境下,通过原生注入的变量来补充安全区尺寸。

// 文件路径:js/main.js (function () { // 从原生侧注入的安全区变量 const nativeSafeTop = window.SAFE_AREA_TOP || 0; const nativeSafeBottom = window.SAFE_AREA_BOTTOM || 0; const nativeSafeLeft = window.SAFE_AREA_LEFT || 0; const nativeSafeRight = window.SAFE_AREA_RIGHT || 0; const root = document.documentElement; // 只有当原生传入的值大于 0 时才覆盖,避免误伤 iOS 的 env() 方案 if (nativeSafeTop > 0) { root.style.setProperty('--safe-top', nativeSafeTop + 'px'); } if (nativeSafeBottom > 0) { root.style.setProperty('--safe-bottom', nativeSafeBottom + 'px'); } if (nativeSafeLeft > 0) { root.style.setProperty('--safe-left', nativeSafeLeft + 'px'); } if (nativeSafeRight > 0) { root.style.setProperty('--safe-right', nativeSafeRight + 'px'); } })();

4.5 运行与验证

直接在浏览器中打开index.html,然后使用 Chrome DevTools 的模拟器:

  1. 打开开发者工具
  2. 点击设备图标切换到设备模拟模式
  3. 在设备列表中选择 iPhone X
  4. 观察页面顶部和底部是否被刘海或 Home Indicator 遮挡

预期效果:

  • 顶部导航栏的返回按钮、标题、更多按钮完整可见
  • 底部操作栏的“立即购买”按钮没有被 Home Indicator 遮挡
  • 中间内容滚动时,最后一条卡片可以完整滚到底部操作栏上方

在真机上验证时,重点对比 iOS 和 Android 的差异。部分 Android 机型的safe-area-inset-bottom可能为 0,但底部仍有手势条遮挡,这时可能需要结合原生注入的方案处理。

5. 常见问题与排查思路

5.1 页面顶部被刘海遮挡

问题现象常见原因解决思路
导航栏跑到刘海区域内部忘记设置 viewport-fit=cover 或未使用 safe-area-inset-top检查 meta 标签,添加对应的 padding-top
fixed 导航栏高度异常只设置了 padding-top,没有调整整体高度高度应设置为calc(基础高度 + 安全区高度)
部分浏览器 safe-area 变量不生效浏览器版本过老使用 constant() 和 env() 双写法,或通过 JS 获取

排查顺序:

  1. 确认页面是否设置了viewport-fit=cover
  2. 打开浏览器开发者工具,查看--safe-top是否生效
  3. 确认导航栏的高度是否使用calc()正确计算
  4. 如果依旧被遮挡,临时给导航栏设置一个较大 padding,验证安全区变量是否存在

5.2 底部按钮被 Home Indicator 遮挡

这种情况通常出现在 iPhone 全面屏机型上。页面底部固定栏使用了position: fixed,但没有添加padding-bottom

解决方案:

.footer { height: calc(56px + env(safe-area-inset-bottom)); padding-bottom: env(safe-area-inset-bottom); }

注意:padding-bottomheight都计算了安全区高度,否则会出现两个问题:一是按钮被遮挡,二是固定栏内部元素分布不均。

5.3 横屏状态下左右内容被截断

横屏时,刘海的遮挡区域会转移到屏幕的左右两侧,这时需要处理safe-area-inset-leftsafe-area-inset-right

.container { padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right); }

同时建议给内容区域也加上安全区边距,避免图片、滚动列表贴近圆角区域。

5.4 小程序自定义导航栏位置偏移

小程序中使用自定义导航栏时,胶囊按钮是系统渲染的,位置由微信控制。开发者需要动态计算导航栏高度。

常见错误是直接使用statusBarHeight,但忽略胶囊按钮的 top 和 height 之间的间距。

正确的计算方式:

const systemInfo = wx.getSystemInfoSync(); const menuRect = wx.getMenuButtonBoundingClientRect(); const statusBarHeight = systemInfo.statusBarHeight; const navBarHeight = (menuRect.top - statusBarHeight) * 2 + menuRect.height;

5.5 Android WebView 中 safe-area 变量不生效

很多 Android 机型在 WebView 中并不支持env(safe-area-inset-*),此时页面底部安全区无法自动计算。建议采用原生 + H5 桥接方案,由原生端注入安全区数值,H5 侧使用 CSS 变量覆盖。

另外要确认 App 的 WebView 是否开启了全屏渲染,如果没有开启,系统会默认处理安全区,H5 侧反而不需要额外适配。

6. 最佳实践与工程建议

6.1 统一封装安全区工具函数

在实际工程中,不建议每个页面都重复写安全区获取逻辑。建议封装成工具函数,统一处理 iOS 和 Android 的差异。

// 文件路径:utils/safe-area.js export function getSafeArea() { const safeArea = { top: 0, bottom: 0, left: 0, right: 0 }; // CSS 环境变量优先 const style = getComputedStyle(document.documentElement); safeArea.top = parseFloat(style.getPropertyValue('--safe-top')) || 0; safeArea.bottom = parseFloat(style.getPropertyValue('--safe-bottom')) || 0; safeArea.left = parseFloat(style.getPropertyValue('--safe-left')) || 0; safeArea.right = parseFloat(style.getPropertyValue('--safe-right')) || 0; // 原生注入兜底 safeArea.top = window.SAFE_AREA_TOP || safeArea.top; safeArea.bottom = window.SAFE_AREA_BOTTOM || safeArea.bottom; safeArea.left = window.SAFE_AREA_LEFT || safeArea.left; safeArea.right = window.SAFE_AREA_RIGHT || safeArea.right; return safeArea; }

6.2 尽量减少位置固定元素

刘海屏适配中,最容易出问题的就是position: fixed元素。越多的 fixed 元素意味着越多的安全区处理点。

一种更稳定的做法是使用 flex 布局实现上下固定、中间滚动的结构,这样安全区只需要加在最外层容器上:

.page { display: flex; flex-direction: column; height: 100vh; padding-top: constant(safe-area-inset-top); padding-bottom: constant(safe-area-inset-bottom); padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom); }

6.3 在视觉稿阶段提前沟通

UI 设计稿通常是在安全区内绘制的,但有时候设计稿的背景色会延伸到状态栏,这时候如果开发直接把内容放在安全区内,就不会有问题。但如果设计师希望内容铺满全屏,同时又要避开刘海,那么就需要明确标注安全区范围。

建议在项目的设计规范中增加一条:所有关键 UI 元素必须位于安全区边界内,非关键背景可以延伸到屏幕边缘。

6.4 真机测试清单

安全区适配不能只依赖模拟器。模拟器只能模拟 iPhone 的刘海,无法完整模拟所有 Android 机型的挖孔位置差异。

建议准备一份真机测试清单:

  • iPhone X / XS / XR 系列
  • iPhone 13/14 系列
  • 一台带水滴屏的华为/荣耀机型
  • 一台带挖孔屏的小米/OPPO/vivo 机型
  • 一台底部有手势条的老款 Android 机型

测试时重点检查四个方向:顶部、底部、左右圆角区域、横屏状态。

6.5 版本兼容与兜底方案

安全区适配代码必须考虑浏览器不支持的情况。常见的兜底方案是给元素设置默认 padding 值,只有当env()生效时才使用环境变量:

.header { /* 兜底值 */ padding-top: 20px; /* 支持时覆盖 */ padding-top: constant(safe-area-inset-top); padding-top: env(safe-area-inset-top); }

这种写法的好处是:在不支持的浏览器中页面依然可用,只是顶部间距为固定值;在支持的环境中,会自动切换到安全区高度。

6.6 避免过度适配

不是所有页面都需要全屏沉浸式效果。如果一个页面根本没有自定义顶部导航栏,也没有底部固定按钮,那么保持viewport-fit=auto即可,不需要做任何安全区处理。

过度适配的典型表现是:页面里大量使用env(safe-area-inset-*),导致在非刘海屏机型上出现奇怪的空白间距。解决方式是在设置 CSS 变量时增加判断:

@supports (padding-top: env(safe-area-inset-top)) { /* 仅支持 env() 的环境才覆盖变量 */ :root { --safe-top: env(safe-area-inset-top); } }

7. 总结与进阶方向

回到开头那句“你说喜欢海,我以为是我的齐刘海”。如果把它看作一次移动端适配的隐喻,那它恰恰说明了前端开发中常见的信息错位:设计师画的是理想中的沉浸式界面,开发却要面对真实设备上的遮挡与挤压。但只要理清了刘海屏的适配原理,掌握了安全区算法的规律,这个“误解”其实很容易消除。

本文主要梳理了以下关键内容:

  • 刘海屏适配的核心是安全区,包括safe-area-inset-topsafe-area-inset-bottomsafe-area-inset-leftsafe-area-inset-right
  • H5 页面必须显式设置viewport-fit=cover,才能使用env()读取安全区变量
  • iOS 需要同时兼容constant()env()两种写法,Android 则需要依赖原生端注入安全区数值
  • 小程序自定义导航栏需要动态计算状态栏高度和胶囊按钮位置
  • 固定元素是安全区适配的高危点,建议优先使用 flex 布局替代
  • 真机测试和兜底方案是避免线上问题的最后防线

下一步可以继续关注几个方向:一是 CSS 新特性env()在更多浏览器上的支持情况,二是 Android 各厂商的 DisplayCutout 差异,三是跨端框架(如 Taro、Flutter)中安全区适配的封装思路。

如果你正在开发移动端页面,建议先把本文的 demo 在真机上跑一遍,分别用 iPhone 和 Android 机型对比,体验一次“安全区适配前”和“适配后”的差异。亲手踩过一次坑之后,再遇到刘海屏相关需求,就会变得从容很多。

如果本文对你有所帮助,可以收藏备用。后续遇到具体的适配问题,也欢迎在评论区交流。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/1 1:23:06

STM32F103+CoreXY步进电机运动控制实现

用STM32F103驱动CoreXY机构的步进电机运动控制&#xff0c;整个过程最考验的不是让电机转起来&#xff0c;而是脉冲控制、加减速规划和结构联动是否稳定。我这次把CoreXY平台的最小系统跑通之后发现&#xff0c;单纯点动很容易&#xff0c;真正有价值的部分是把XY两个轴换算成两…

作者头像 李华
网站建设 2026/9/1 1:22:10

基于SpringBoot的老旧小区改造信息管理系统(程序+文档+讲解)

温馨提示&#xff1a;本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;本人主页置顶文章(点我)开头有 CSDN 平台…

作者头像 李华
网站建设 2026/9/1 1:19:41

社区服务小程序开发全流程:从账号准备到上线运营

社区服务小程序这两年需求一直很旺&#xff0c;跑腿、团购、家政、上门维修&#xff0c;几乎每个小区物业和本地服务商都想要一个。但真正动手做的时候&#xff0c;很多人卡在同一个问题上&#xff1a;不知道从哪一步开始&#xff0c;是先注册账号&#xff0c;还是先写代码&…

作者头像 李华
网站建设 2026/9/1 1:17:33

三环PID地对空导弹制导系统Simulink建模与参数整定

简介&#xff1a;本资源是一套面向地对空导弹制导系统建模与仿真的工程化MATLAB/Simulink解决方案&#xff0c;专为电子信息工程、计算机、数学等专业本科生课程设计、期末大作业及毕业设计打造&#xff0c;聚焦经典三环PID控制结构在飞行器制导中的系统级实现与动态验证。压缩…

作者头像 李华
网站建设 2026/9/1 1:17:03

基于CNN的水果识别分类系统开发实战:从数据集到答辩全流程

简介&#xff1a;这是一套面向计算机专业本科生的毕业设计与期末大作业实战资源&#xff0c;聚焦卷积神经网络在图像分类领域的典型应用——水果识别系统&#xff0c;帮助学习者掌握CNN模型构建、数据预处理、训练调优及部署演示全流程。资源包共2000个文件&#xff0c;含30个核…

作者头像 李华
网站建设 2026/9/1 1:11:37

基于Springboot的AI辅助的现代企业管理系统(源码+lw+部署文档+讲解等)

温馨提示&#xff1a;本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;本人主页置顶文章(点我)开头有 CSDN 平台…

作者头像 李华