news 2026/10/21 18:55:40

artcraft 从零到一:创意编程框架的分层设计与粒子动画实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
artcraft 从零到一:创意编程框架的分层设计与粒子动画实战

1. 从“artcraft”这个名字说起:它到底想解决什么问题

第一次看到“artcraft”这个标题,我脑子里蹦出来的第一反应是:这大概率是一个把“艺术(art)”和“手工艺/工程(craft)”揉在一起的项目。事实也确实如此。在我接触过的众多个人项目里,这类命名往往指向一个非常具体的诉求——让创意表达和工程实现之间的那道墙变矮一点。说白了,就是让那些有想法但不想被复杂工具链折磨的人,能顺畅地把脑子里的画面、结构、交互变成看得见摸得着的东西。

我之所以对这个方向特别有感触,是因为过去几年我陆陆续续帮不少朋友做过类似的事情:有人想做一套属于自己的视觉作品集,有人想给孩子的生日做一个能互动的小装置,还有人只是单纯想把自己画的插画变成可以动起来的网页。这些人有一个共同点——他们不缺创意,缺的是一个门槛足够低、但天花板又足够高的工具或框架。artcraft 这个标题背后,我理解的核心诉求就是:用一套相对统一的思路,把艺术创作和工程实现串起来,让“做出来”这件事变得不那么痛苦。

那么这篇博文适合谁看?如果你是一个独立创作者、设计师、前端开发者,或者是一个想入门创意编程但被各种术语劝退的爱好者,那接下来的内容应该对你有用。我会从整体设计思路、核心技术点、实操流程、常见坑这几个维度,把 artcraft 这类项目从零到一拆开讲清楚。我不会只告诉你“怎么做”,更会告诉你“为什么这么做”,以及我在实际操作中踩过的那些坑。文章会比较长,但每一段都是我实打实整理出来的经验,你可以挑自己需要的部分看,也可以从头顺着读下来。

在正式开始之前,先明确一下我对 artcraft 这类项目的定位理解:它不是一个单纯的绘图工具,也不是一个纯粹的代码框架,而是一个中间层——向上承接创意意图,向下对接渲染、交互、导出等工程能力。这个定位决定了它的设计取舍,也决定了我们在使用它时应该抱有什么样的预期。

2. 整体设计思路拆解:为什么是“分层”而不是“一把梭”

2.1 核心思路:把创意和实现拆成两层

我在研究 artcraft 这类项目时,发现一个很有意思的现象:很多同类工具失败的原因,不是功能不够强,而是把创意和实现混在了一起。用户打开界面,左边是画布,右边是一堆参数滑块,底下还有代码编辑器,新手一看就懵了。artcraft 的思路明显不一样,它倾向于把整个流程拆成两层:

  • 创意层:负责“我想要什么”,比如一个形状、一段动画、一种材质感。这一层尽量用接近自然语言或可视化操作的方式表达。
  • 实现层:负责“怎么把它做出来”,比如用哪种渲染方式、怎么组织数据结构、怎么优化性能。这一层对普通用户透明,但对进阶用户开放。

这种分层的好处是显而易见的。新手可以在创意层里快速试错,不用关心底层发生了什么;老手可以随时下沉到实现层,精细控制每一个参数。我实测下来,这种设计对降低入门门槛的效果非常明显——一个完全没写过代码的人,也能在几分钟内做出一个能看的东西,这种正反馈是坚持下去的关键。

2.2 方案选型:为什么不用现成的重型引擎

很多人会问,既然要做创意项目,为什么不直接用那些成熟的游戏引擎或者三维软件?我一开始也有这个疑问,后来自己动手搭了一遍才明白:重型引擎是为大型团队和长期项目设计的,它们的优势在于功能全面,但代价是学习曲线陡峭、启动成本高。对于一个只想快速验证想法、或者做一个小而美作品的人来说,用重型引擎就像开卡车去菜市场买菜——不是不行,是没必要。

artcraft 这类项目通常选择更轻量的技术路线,比如基于 Web 的渲染方案、声明式的场景描述、以及一套约定优于配置的组织方式。这样做的好处是:

  • 启动快:不需要安装庞大的运行时,打开就能用。
  • 迭代快:改一个参数立刻能看到效果,适合创意探索。
  • 分享快:产物可以直接在浏览器里运行,发给别人就能看。

当然,轻量也有代价。比如在处理特别复杂的场景时,性能可能不如重型引擎;在需要高度定制化的时候,可能需要自己写一些底层代码。但我觉得这个取舍是合理的,因为 artcraft 的目标用户本来就不是要做3A大作,而是要做有个人表达的小作品。

2.3 优势与边界:它擅长什么,不擅长什么

在动手之前,搞清楚一个工具的边界非常重要,这能帮你少走很多弯路。根据我的经验,artcraft 这类项目擅长的是:

  • 快速原型:几分钟内把想法变成可交互的 demo。
  • 视觉实验:尝试不同的颜色、形状、动画曲线。
  • 小型互动作品:比如个人主页的背景动画、数据可视化的艺术化呈现。
  • 教学演示:用来讲解某个视觉原理或交互逻辑。

它不太擅长的是:

  • 超大规模场景:比如几万个独立物体的实时物理模拟。
  • 重度依赖特定平台特性:比如需要调用某些系统级接口。
  • 长期维护的大型项目:缺乏完整的工程化配套。

提示:在决定用 artcraft 做项目之前,先花十分钟想清楚你的核心需求是什么。如果只是想做一个小而美的作品,它非常合适;如果你要做的是一个需要多人协作、长期迭代的产品,可能需要考虑更重的方案。

3. 核心细节解析与实操要点:从零搭起一个 artcraft 项目

3.1 环境准备:别一上来就装一堆东西

我见过太多人,项目还没开始写,先花半天时间折腾环境,最后热情都耗没了。artcraft 这类项目的优势就是环境简单,所以我的建议是:能用浏览器解决的,就不要装本地工具。具体来说,你需要准备的其实只有三样东西:

  1. 一个现代浏览器:Chrome 或 Edge 都行,确保版本不要太老。
  2. 一个代码编辑器:VS Code 就够用,轻量且插件丰富。
  3. 一个本地服务器:用来预览你的作品,Python 自带的http.server或者 Node 的serve都可以。

如果你只是想先试试水,甚至可以直接在浏览器的开发者工具里写几行代码看看效果。等确定要深入了,再考虑搭建完整的本地环境。

# 如果你装了 Python,一行命令就能起一个本地服务器 python -m http.server 8000 # 如果你用 Node,也可以这样 npx serve .

注意:不要用file://协议直接打开 HTML 文件,很多渲染相关的功能会因为跨域限制而失效。一定要通过本地服务器访问。

3.2 项目结构:约定优于配置

artcraft 这类项目通常有一套推荐的项目结构,我建议你一开始就按照这个结构来组织文件,后面会省很多事。一个典型的目录长这样:

my-artcraft-project/ ├── index.html # 入口页面 ├── src/ │ ├── main.js # 主逻辑 │ ├── scenes/ # 场景定义 │ ├── assets/ # 图片、模型等资源 │ └── utils/ # 工具函数 ├── styles/ │ └── main.css # 样式 └── package.json # 依赖管理(如果需要)

这个结构的好处是职责清晰。场景定义单独放,资源单独放,工具函数单独放,找东西的时候不用满项目翻。我自己的习惯是,哪怕项目再小,也至少把scenes和assets分开,因为这两类东西的修改频率和修改原因完全不同。

3.3 核心概念:场景、节点、属性

artcraft 这类项目的核心概念通常围绕三个词展开:场景(Scene)、节点(Node)、属性(Property)。理解这三个词,基本就理解了整个框架的运作方式。

  • 场景:你可以把它想象成一个舞台,所有的东西都放在这个舞台上。一个项目可以有多个场景,比如“首页场景”“详情场景”。
  • 节点:舞台上的每一个元素,比如一个方块、一段文字、一张图片,都是一个节点。节点可以嵌套,形成父子关系。
  • 属性:每个节点都有一堆属性,比如位置、大小、颜色、旋转角度。你改属性,画面就跟着变。

用生活化的类比来说,场景就像是一个房间,节点就像是房间里的家具,属性就像是家具的摆放位置和外观。你要做的就是往房间里摆家具,然后调整它们的位置和样子。

// 一个典型的场景定义大概长这样 const scene = { nodes: [ { type: 'rect', x: 100, y: 100, width: 200, height: 200, fill: '#ff6b6b', rotation: 45 }, { type: 'text', content: 'Hello Artcraft', x: 150, y: 350, fontSize: 24, fill: '#333' } ] };

这段代码的意思是:在场景里放一个红色的方块和一个文字。方块在 (100, 100) 的位置,宽高都是 200,旋转了 45 度;文字在 (150, 350) 的位置,字号 24。你看,不需要任何渲染知识,就能把东西摆出来。

3.4 属性动画:让静态画面动起来

静态画面做完了,接下来就是让它动起来。artcraft 这类项目通常提供两种动画方式:关键帧动画和程序化动画。

关键帧动画就是你定义几个时间点上的属性值,系统自动补间。比如:

const animation = { target: 'rect1', keyframes: [ { time: 0, x: 100, rotation: 0 }, { time: 1000, x: 400, rotation: 360 }, { time: 2000, x: 100, rotation: 720 } ], easing: 'ease-in-out', loop: true };

这段代码的意思是:方块在 0 毫秒时在 x=100 的位置,旋转 0 度;在 1000 毫秒时移动到 x=400,旋转 360 度;在 2000 毫秒时回到 x=100,旋转 720 度。整个过程循环播放,缓动曲线是 ease-in-out。

程序化动画则是你在每一帧里根据时间或其他变量计算属性值。这种方式更灵活,适合做复杂的、有逻辑的动画。

function update(time) { const t = time / 1000; rect.x = 100 + Math.sin(t) * 200; rect.rotation = t * 90; }

两种方式各有优劣。关键帧动画直观、易调试,适合做固定的动作;程序化动画灵活、可组合,适合做有交互反馈的效果。我自己的经验是,先用关键帧把大框架搭出来,再用程序化动画做细节,这样效率最高。

3.5 交互处理:让用户能“碰”到你的作品

一个作品如果只能看不能碰,那它的感染力会大打折扣。artcraft 这类项目通常提供了一套事件系统,让你能监听用户的鼠标、键盘、触摸操作。

scene.on('pointerdown', (event) => { const node = event.target; if (node) { node.fill = '#4ecdc4'; node.scale = 1.2; } }); scene.on('pointerup', (event) => { const node = event.target; if (node) { node.fill = '#ff6b6b'; node.scale = 1.0; } });

这段代码的意思是:当用户按下鼠标时,如果点到了某个节点,就把它的颜色改成青色,放大到 1.2 倍;松开鼠标时恢复原样。这种即时反馈能让用户感觉到“这个东西是活的”,参与感会强很多。

实操心得:交互设计里有一个很重要的原则叫“即时反馈”。用户做了任何操作,系统都应该在 100 毫秒内给出视觉或听觉上的回应。如果超过这个时间,用户就会觉得卡顿或者没反应。所以在做交互的时候,尽量把反馈逻辑放在最前面,不要等复杂计算完成后再更新画面。

4. 实操过程与核心环节实现:做一个完整的互动小作品

4.1 需求定义:先想清楚要做什么

在动手写代码之前,我习惯先用一句话把需求写下来。比如这次我们要做的是一个“点击生成彩色粒子”的小作品。具体描述是:页面上有一个深色背景,用户点击任意位置,就会从点击处迸发出一组彩色粒子,粒子向外扩散并逐渐消失。

这个需求足够简单,适合用来演示完整流程;同时又包含了场景、节点、属性、动画、交互这几个核心要素,麻雀虽小五脏俱全。

4.2 场景搭建:从背景开始

第一步是搭场景。我们先把背景设成深色,这样彩色粒子会更明显。

const scene = { background: '#1a1a2e', nodes: [] };

背景色我选了#1a1a2e,这是一个偏深的蓝紫色,比纯黑更有质感,也不会太刺眼。这种颜色在视觉上比较“沉”,能让上面的彩色粒子“浮”起来。

4.3 粒子生成:核心逻辑实现

接下来是核心的粒子生成逻辑。每次点击,我们生成 20 个粒子,每个粒子有随机的方向、速度、颜色和生命周期。

function createParticles(x, y) { const particles = []; const count = 20; for (let i = 0; i < count; i++) { const angle = (Math.PI * 2 * i) / count + Math.random() * 0.5; const speed = 2 + Math.random() * 4; const hue = Math.random() * 360; particles.push({ type: 'circle', x: x, y: y, radius: 3 + Math.random() * 5, fill: `hsl(${hue}, 80%, 60%)`, vx: Math.cos(angle) * speed, vy: Math.sin(angle) * speed, life: 1.0, decay: 0.015 + Math.random() * 0.01 }); } return particles; }

这里有几个细节值得说明。angle的计算用了(Math.PI * 2 * i) / count,这样粒子会均匀分布在一个圆上,再加上一点随机偏移,避免看起来太规整。speed在 2 到 6 之间随机,让粒子扩散速度有快有慢,更有层次感。hue随机取 0 到 360,保证颜色丰富。life初始为 1.0,每帧减去decay,减到 0 以下就移除。

4.4 动画循环:让粒子动起来

粒子生成后,需要在每一帧更新它们的位置和透明度。

function updateParticles(particles, deltaTime) { for (let i = particles.length - 1; i >= 0; i--) { const p = particles[i]; p.x += p.vx * deltaTime; p.y += p.vy * deltaTime; p.vy += 0.1 * deltaTime; // 模拟重力 p.vx *= 0.99; // 空气阻力 p.vy *= 0.99; p.life -= p.decay * deltaTime; if (p.life <= 0) { particles.splice(i, 1); } } }

这里加了两个物理效果:重力和空气阻力。重力让粒子有下坠的趋势,空气阻力让粒子逐渐减速。这两个效果加起来,粒子就不会一直直线飞出去,而是会形成一个漂亮的抛物线轨迹,最后慢慢停下来然后消失。

deltaTime是帧间隔时间,用它来乘速度,可以保证在不同刷新率的设备上动画速度一致。这一点很重要,否则在 144Hz 的屏幕上粒子会飞得比 60Hz 快一倍多。

4.5 渲染与清理:保证性能稳定

渲染部分就是把粒子画到画布上。同时要注意清理已经消失的粒子,避免数组无限增长。

function render(particles) { ctx.clearRect(0, 0, canvas.width, canvas.height); for (const p of particles) { ctx.globalAlpha = p.life; ctx.beginPath(); ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2); ctx.fillStyle = p.fill; ctx.fill(); } ctx.globalAlpha = 1.0; }

globalAlpha设为p.life,这样粒子在消失的过程中会逐渐变透明,视觉效果更自然。渲染完成后记得把globalAlpha恢复成 1.0,否则会影响后续的绘制。

注意:粒子的数量一定要有上限。我一般会设一个最大值,比如 500 个,超过就不再生成新的。否则用户疯狂点击的时候,粒子数量会爆炸,帧率会掉得很厉害。这个上限可以根据你的设备性能调整,移动端建议设低一点,桌面端可以设高一点。

4.6 参数调优:从“能用”到“好看”

代码写完了,能跑起来,但这只是第一步。真正决定作品质量的是参数调优。我一般会从以下几个维度去调:

参数作用我的常用值调整方向
粒子数量每次点击生成多少20多了壮观但吃性能,少了精致但不够震撼
初始速度粒子飞出的快慢2-6快了有冲击力,慢了更优雅
衰减速度粒子消失的快慢0.015-0.025快了干净利落,慢了余韵悠长
重力系数下坠的强度0.1大了像下雨,小了像太空
阻力系数减速的强度0.99越接近1越滑,越接近0越黏
粒子大小圆点的半径3-8大了厚重,小了轻盈

调参这件事没有标准答案,完全取决于你想要什么感觉。我的建议是先定一个基调,比如“轻盈梦幻”还是“厚重有力”,然后所有参数都往这个方向靠。不要一会儿想轻盈一会儿想厚重,最后出来的东西会四不像。

5. 常见问题与排查技巧实录

5.1 画面不显示或显示异常

这是最常见的问题,我把它拆成几种情况:

情况一:完全黑屏或白屏。首先检查控制台有没有报错。如果有报错,按报错信息去查。如果没有报错,检查画布的尺寸是不是 0——有时候 CSS 没设好,画布宽高是 0,自然什么都看不到。

情况二:画面显示但位置不对。大概率是坐标系的问题。有些框架的原点在左上角,有些在中心;有些 y 轴向下,有些向上。先确认你用的坐标系是哪种,再检查你的坐标值。

情况三:画面闪烁或撕裂。这通常是渲染和更新不同步导致的。确保你在每一帧里先更新所有状态,再统一渲染,不要边更新边渲染。

5.2 动画卡顿或掉帧

卡顿的原因通常有三个:粒子太多、计算太重、渲染太频繁。

  • 粒子太多:加一个数量上限,超过就不再生成。
  • 计算太重:把一些不必要每帧计算的东西缓存起来,比如颜色字符串、路径对象。
  • 渲染太频繁:如果设备刷新率是 144Hz,但你的动画只需要 60Hz,可以用时间累积的方式控制渲染频率。
let lastRenderTime = 0; const renderInterval = 1000 / 60; // 目标 60fps function loop(currentTime) { const deltaTime = currentTime - lastRenderTime; if (deltaTime >= renderInterval) { update(deltaTime); render(); lastRenderTime = currentTime; } requestAnimationFrame(loop); }

5.3 交互没反应

交互没反应,先检查三件事:

  1. 事件有没有绑定到正确的对象上。有时候你绑到了画布上,但用户点的是画布里的某个元素,事件冒泡没处理好就会漏掉。
  2. 事件有没有被阻止。有些默认行为会阻止事件传递,比如touchstart在某些情况下会阻止click。
  3. 坐标转换有没有做。如果画布有缩放或偏移,鼠标坐标需要转换到画布坐标系才能正确命中。
function getCanvasCoords(event, canvas) { const rect = canvas.getBoundingClientRect(); const scaleX = canvas.width / rect.width; const scaleY = canvas.height / rect.height; return { x: (event.clientX - rect.left) * scaleX, y: (event.clientY - rect.top) * scaleY }; }

5.4 常见问题速查表

问题现象可能原因排查方向解决方法
完全黑屏画布尺寸为0检查CSS宽高设置明确的宽高
画面偏移坐标系不一致确认原点位置统一坐标系
动画卡顿粒子过多查看粒子数量加数量上限
交互无反应事件未绑定检查事件监听重新绑定事件
颜色不对颜色格式错误检查颜色值使用标准格式
内存增长对象未回收检查数组长度及时移除无用对象

5.5 独家避坑技巧

技巧一:用console.time定位性能瓶颈。不要凭感觉猜哪里慢,用数据说话。

console.time('update'); updateParticles(particles, deltaTime); console.timeEnd('update');

技巧二:把常用值提取成常量。不要到处写魔法数字,提取成常量后,调参的时候改一个地方就行。

技巧三:先做减法再做加法。一开始不要加太多效果,先把最核心的跑通,再一点点往上加。每加一个效果就测一次性能,确保没有明显下降。

技巧四:在低性能设备上测试。你的开发机可能很快,但用户的设备不一定。用浏览器的性能面板模拟低端设备,看看还能不能跑。

6. 工具选型与扩展思路

6.1 渲染方案怎么选

artcraft 这类项目在渲染层面通常有几种选择:Canvas 2D、SVG、WebGL。它们各有适用场景:

  • Canvas 2D:适合粒子多、需要频繁重绘的场景。性能好,但矢量图形支持弱。
  • SVG:适合图形少、需要精确控制每个元素的场景。矢量清晰,但元素多了会卡。
  • WebGL:适合三维场景或超大量元素的场景。性能最强,但学习曲线陡。

我的建议是:先用 Canvas 2D 把东西做出来,如果性能不够再考虑 WebGL。不要一上来就上 WebGL,除非你明确知道需要三维效果。

6.2 资源管理的小技巧

图片、字体、音频这些资源,加载是异步的,但使用是同步的。如果不处理好,很容易出现“资源还没加载完就开始用”的问题。

async function loadAssets() { const assets = { texture: await loadImage('texture.png'), font: await loadFont('font.woff2'), sound: await loadAudio('sound.mp3') }; return assets; } loadAssets().then(assets => { // 资源加载完成后再启动场景 startScene(assets); });

把所有资源加载完再启动场景,虽然会让首屏等待时间变长,但能避免很多奇怪的 bug。如果等待时间太长,可以加一个加载进度条,让用户知道系统在工作。

6.3 后续可以怎么扩展

这个粒子作品只是一个起点,后面可以往很多方向扩展:

  • 加入物理碰撞:让粒子之间或者粒子与边界产生碰撞。
  • 加入鼠标吸引力:粒子被鼠标吸引或排斥。
  • 加入颜色渐变:粒子的颜色随时间或位置变化。
  • 加入音效:点击时播放一个短促的音效,增强反馈。
  • 加入多种粒子形状:不只是圆点,还可以是星星、方块、三角形。

每加一个功能,都建议单独测试,确保它不会破坏已有的效果。我自己的习惯是,每完成一个功能就提交一次代码,这样出问题的时候可以快速回滚。

7. 我个人的一些实操体会

做这类创意项目,最大的敌人往往不是技术难度,而是完美主义。我见过太多人,一开始想做一个“很酷的东西”,结果在细节上反复纠结,最后什么都没做出来。我的建议是:先做一个能跑的丑东西,再慢慢把它变好看。一个能跑的丑东西,比一个完美的空想有价值得多。

另外,不要害怕抄。我说的抄不是复制粘贴,而是参考别人的实现思路。看到好的效果,去研究它是怎么做的,然后用自己的方式实现一遍。这个过程本身就是最好的学习。

最后,记得把你的作品分享出去。不管是发在社交平台,还是发给朋友看,别人的反馈会给你很多意想不到的灵感。而且,当你看到别人因为你的作品而感到开心的时候,那种成就感是任何技术指标都替代不了的。

这个内容后续还可以这样扩展:把粒子系统封装成一个可复用的组件,加上参数面板,让不懂代码的人也能通过拖拽滑块来调整效果。这样它就从一个“作品”变成了一个“工具”,价值会更大。

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

差动制动横摆稳定性控制:从算法设计到仿真验证

干整车底盘控制的工程师&#xff0c;或者做车辆动力学仿真的研究生&#xff0c;一定绕不开一个问题&#xff1a;车辆在高速避障、急打方向盘的时候&#xff0c;为什么明明驾驶员没踩错踏板&#xff0c;车还是会突然掉头甩尾&#xff0c;甚至失控打转&#xff1f;这背后就是横摆…

作者头像 李华
网站建设 2026/10/21 18:55:12

SolidWorks云服务器+设计云桌面:多人共享使用方案全解析

你在一个小型机械设计团队里待过&#xff0c;大概率见过这种场面&#xff1a;几台高性能工作站摆在工位上&#xff0c;风扇全速转&#xff0c;负责跑大型装配体的那台每天被抢着用&#xff1b;图纸散落在各自硬盘里&#xff0c;版本管理靠“最终版-改2-再改3”这种文件名&#…

作者头像 李华
网站建设 2026/10/21 18:55:01

代码审查机制实战:从流程设计到自动化门禁落地

1. 项目概述代码审查这事&#xff0c;说起来简单&#xff0c;做起来全是细节。我在团队里牵头搭过这套名为“open-code-review”的代码审查机制&#xff0c;前后折腾了不少版本&#xff0c;踩过不少坑&#xff0c;今天把整个思路、流程和工具选型整理出来&#xff0c;希望能给正…

作者头像 李华
网站建设 2026/10/21 18:49:14

artcraft 工程化实践:从零搭建艺术与工艺融合的创意项目

1. 从“artcraft”这个名字说起&#xff1a;它到底想解决什么问题第一次看到“artcraft”这个标题&#xff0c;我脑子里蹦出来的第一反应是&#xff1a;这大概率不是一个单纯的艺术创作工具&#xff0c;也不是一个纯粹的代码项目&#xff0c;而是某种把“艺术表达”和“工程实现…

作者头像 李华
网站建设 2026/10/21 18:47:27

Linux pinctrl子系统原理详解:从引脚复用到设备树与GPIO协作

前阵子帮客户调一块评估板&#xff0c;遇到一个特别邪门的问题&#xff1a;SD卡持续读写大文件时会随机报错。查到最后&#xff0c;罪魁祸首不是SD卡驱动&#xff0c;而是卡检测脚。内核起来以后&#xff0c;pinctrl子系统按照某个外设节点的默认状态&#xff0c;把原本应该保持…

作者头像 李华