Canvas+JS打造H5连线题:坐标换算与交互状态管理

发布时间:2026/10/6 3:58:34

Canvas+JS打造H5连线题:坐标换算与交互状态管理 简介一套基于HTML5 Canvas与jQuery实现的连线题交互模板适合在线测评、教育游戏、自测练习及课堂互动等场景使用。压缩包内共4个文件包含2个CSS样式文件用于页面布局、按钮与连线视觉样式调整、1个HTML文件承载题目区域与画布元素、1个JS文件负责拖拽事件、连线绘制、答案校验和取值回调整体约9KB体量小巧而逻辑完整。资源已有640人学习浏览适合前端学习者与交互应用开发者参考。项目内置纵向题与横向题两种模板覆盖了Canvas二维绘图、鼠标与触屏事件处理、坐标计算、两点距离判定、答案实时判断、重绘性能优化以及回调函数等核心知识点帮助读者理解一个互动型前端小功能从界面设计到数据处理的全过程。同时代码结构清晰、变量命名直观学习者能将题目数据、样式外观和回调业务直接替换为自己的内容快速部署到题库系统或在线课件中是练习Canvas与jQuery综合运用的实用小案例。1. 为什么 H5 连线题要把 canvas 和 JS 绑在一起先看清交互的本来面目在线答题页里连线题通常是“左侧几个选项、右侧几个选项用户拖一条线表示匹配”。这类题的核心难点不在数据逻辑而在 canvas 与 JS 的配合按下时定位、移动中实时绘图、松手时判定落点再叠加移动端触摸事件和高清屏适配很多方案就卡在坐标这关。用原生 canvas JS 做连线题是性价比很高的做法一张画布解决全部绘制几段事件代码解决交互题库数据保持纯 JSON 结构适合在线考试、教学课件和活动互动页。我按一条可复现的实现路径往下拆从画布初始化讲到命中检测、答案判定、撤销与常见坑位最后补上自适应和结果上报。你照着搭完替换题面数据就能直接上线。2. 初始化画布与坐标系换算把像素对齐后面才不返工连线题一上来就要面对一个容易忽视的问题canvas 的绘图尺寸和它在页面上的 CSS 尺寸是两套坐标系。如果不处理这两者的关系等拖拽交互做完再回头看线会整体偏移而且只在部分屏幕出现排查起来很烦。所以第二章先把地基打稳。2.1 先搭一个能运行的最小结构容器、可拖元素与覆盖画布页面结构上大多数人第一反应是“canvas 放在中间左右元素排两边”但实际做起来会撞到一个事件穿透问题。更稳的布局是canvas 用绝对定位覆盖整个容器左右两列照常排布canvas 设pointer-events: none让鼠标和触摸事件落在真正的选项节点上。div classmatch-app idmatchApp div classcolumn left-col div classnode>.match-app { position: relative; width: min(720px, 92vw); height: 320px; touch-action: none; } #lineCanvas { position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; } .column { width: 180px; } .left-col { position: absolute; left: 0; top: 10px; } .right-col { position: absolute; right: 0; top: 10px; } .node { height: 52px; line-height: 52px; text-align: center; border: 1px solid #d9d9d9; border-radius: 8px; background: #fff; margin-bottom: 20px; cursor: pointer; user-select: none; }这段结构里有两个关键决定。第一canvas 覆盖全容器但不接收事件选项节点才能正常响应 mousedown 和 touchstart第二容器加了touch-action: none否则移动端用户在 canvas 区域拖线时会触发页面滚动这也是连线题在手机上最常见的“拖不动”原因。选项节点的>let app null; function init() { app { el: document.getElementById(matchApp), canvas: document.getElementById(lineCanvas), nodeMap: {}, lines: [], undoStack: [], draft: null, drawing: false, stdAnswer: { a: 1, b: 3, c: 2 } }; app.ctx app.canvas.getContext(2d); app.el.querySelectorAll(.node).forEach((node) { app.nodeMap[node.dataset.key] node; }); resizeCanvas(); bindEvents(); } function resizeCanvas() { const rect app.el.getBoundingClientRect(); const dpr window.devicePixelRatio || 1; app.box { left: rect.left, top: rect.top, width: rect.width, height: rect.height }; app.canvas.width Math.round(rect.width * dpr); app.canvas.height Math.round(rect.height * dpr); app.canvas.style.width rect.width px; app.canvas.style.height rect.height px; app.ctx.setTransform(dpr, 0, 0, dpr, 0, 0); draw(); }这里有两步容易漏。第一步canvas.width/height用物理像素style.width/height用 CSS 像素第二步setTransform(dpr, 0, 0, dpr, 0, 0)让后续所有绘制 API 直接按 CSS 像素传参不用每个点都手动乘 dpr。坐标换算函数也要跟着统一。事件对象里拿到的是clientX/clientY它是相对浏览器视口的 CSS 像素坐标而画布在页面里有自己的偏移。用容器getBoundingClientRect()记录一次偏移后续拖拽过程中直接用这个缓存值避免高频 mousemove 里反复触发布局计算。function getCanvasPos(clientX, clientY) { return { x: clientX - app.box.left, y: clientY - app.box.top }; }注意resizeCanvas里用getBoundingClientRect取到的left/top已经包含页面滚动偏移所以只要在窗口 resize 或容器位置变化时重新调用它坐标系统就能保持一致。这也是后面白屏问题的一个重要铺垫——resize 不只是改尺寸还要重算偏移并重绘。3. 拖拽连线的完整交互链路从按下、移动、命中到松手吸附画布和坐标系就绪后进入交互主体。连线题最核心的体验在于按下左列节点时开始画线移动时线条实时跟随指针接近右侧有效节点时自动吸附松手后落线并进入状态管理。这个过程用一套统一的事件处理就能覆盖鼠标和触摸。3.1 拖拽状态机与动态线的实时绘制贝塞尔曲线怎么画才自然拖拽过程中的绘制对象有两种已经提交的连线和正在拖拽的临时线。临时线只存在于拖拽期间松手后要么被丢弃要么转正为正式连线。因此我用一个draft对象保存当前拖拽的起点 key 和实时终点坐标draw()每次全量重绘整个画布。function bindEvents() { const box app.el; box.addEventListener(pointerdown, (e) { const node e.target.closest(.node); if (!node || !node.closest(.left-col)) return; const pos getCanvasPos(e.clientX, e.clientY); app.draft { fromKey: node.dataset.key, toX: pos.x, toY: pos.y }; app.drawing true; }); window.addEventListener(pointermove, (e) { if (!app.drawing) return; const pos getCanvasPos(e.clientX, e.clientY); app.draft.toX pos.x; app.draft.toY pos.y; draw(); }); window.addEventListener(pointerup, (e) { if (!app.drawing) return; const hit findHitNode(e.clientX, e.clientY, .right-col); if (hit) { commitLine(app.draft.fromKey, hit.dataset.key); } app.drawing false; app.draft null; draw(); }); }这里统一用了 Pointer Events一套事件同时覆盖鼠标、触摸和触控笔代码少一半。需要注意 pointermove 和 pointerup 绑在 window 上这样拖出容器后依然能继续绘制和收线不会因为鼠标离开容器就断掉。Pointer Events 在 iOS 13.4 以上完整支持如果你的项目必须兼容更低版本再回退到 touch 事件方案。draw 函数是整道题最核心的绘制逻辑function draw() { const ctx app.ctx; ctx.clearRect(0, 0, app.box.width, app.box.height); ctx.lineWidth 3; ctx.lineCap round; ctx.lineJoin round; ctx.strokeStyle #5B8FF9; // 画已提交的正式连线 app.lines.forEach((line) { const p1 getAnchor(line.leftKey); const p2 getAnchor(line.rightKey); const midX (p1.x p2.x) / 2; ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.quadraticCurveTo(midX, p1.y, p2.x, p2.y); ctx.stroke(); }); // 画正在拖拽的临时线 if (app.draft) { const p1 getAnchor(app.draft.fromKey); const midX (p1.x app.draft.toX) / 2; ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.quadraticCurveTo(midX, p1.y, app.draft.toX, app.draft.toY); ctx.stroke(); } }为什么临时线不单独用一个透明 canvas 画因为连线题需要频繁清空重绘两层 canvas 会增加同步成本单层全量重绘在这个量级下性能完全够用。如果连线数量超过三四十条再考虑分层优化也不迟。贝塞尔曲线选择的是二次曲线控制点取起点和终点的中点、y 轴跟随起点。这样拖拽时线条呈现一个自然弯曲的弧比直线耐看。如果你想要更“硬”的连线手感可以直接把控制点 y 设为起点和终点的平均 y得到类似 S 形的效果这个参数看产品偏好代码里只改一行。getAnchor负责把节点的 DOM 位置换算成 canvas 内的锚点坐标function getAnchor(key) { const node app.nodeMap[key]; const rect node.getBoundingClientRect(); const pos getCanvasPos(rect.left rect.width / 2, rect.top rect.height / 2); return { x: pos.x, y: pos.y }; }3.2 命中检测与吸附阈值的调参思路松手时要知道指针落在哪个右侧节点上。常见做法有两种用document.elementFromPoint(e.clientX, e.clientY)直接查元素或者遍历节点做矩形碰撞。我更推荐后者的中心点距离方案因为它天然支持「吸附阈值」这个交互细节——指针不用严格落在节点范围内靠近到一定距离就能触发吸附手感会好很多。function findHitNode(clientX, clientY, selector, pad 16) { let best null; let bestDist pad; const nodes app.el.querySelectorAll(selector); nodes.forEach((node) { const rect node.getBoundingClientRect(); const cx rect.left rect.width / 2; const cy rect.top rect.height / 2; const dist Math.hypot(clientX - cx, clientY - cy); if (dist bestDist) { bestDist dist; best node; } }); return best; }这个函数的逻辑是遍历所有右侧节点计算指针到每个节点中心的欧氏距离取距离最小的那个而且最小距离必须小于bestDist才生效。pad就是吸附阈值我一般取 16px。阈值不是越大越好。当左右列节点间距比较近时如果阈值太大用户还没拖到目标附近就被错误吸附反而觉得线“粘人”。我的经验是节点间距 40px 以上用 16-20px间距 30px 以内就把阈值压到 10px。这种调参属于靠感觉打磨的部分上线前找几个人随手拖一圈基本能定下来。这里还有一个判断起点的问题。当前实现只允许从左侧节点发起拖拽右侧节点作为终点。如果你要支持从右往左连把pointerdown里的closest(.left-col)条件去掉findHitNode里传.left-col即可。不过连线题通常是有向匹配单方向发起交互逻辑更清晰也方便后面对答案。4. 用数组管理连线状态记录、替换、撤销与答案判定交互做完后用户的每一次落线都要被记录下来否则重绘时没有数据可画。这一步很多人会随手用几个变量存“当前连线”但线一多就乱了。连线题的状态管理核心是左列 key 唯一、右侧可重复或不可重复、支持替换旧线、支持撤销。我用一个 lines 数组加一个 undoStack 解决。4.1 数据模型为什么是 lines undoStack而不是散装变量数据结构如果设计成{ a: 1, b: 3 }这样的对象做替换很方便但做撤销时要记住旧值而且无法表达“某次操作只新增了一条线”的语义。用数组表达顺序再用一个独立的撤销栈记录操作步骤整体更可控。function commitLine(leftKey, rightKey) { const oldIndex app.lines.findIndex((l) l.leftKey leftKey); if (oldIndex -1) { // 同一左列节点已经连过线替换旧线并记录旧线 const oldLine app.lines[oldIndex]; app.lines[oldIndex] { leftKey, rightKey }; app.undoStack.push({ type: replace, oldLine, newLine: { leftKey, rightKey } }); } else { const newLine { leftKey, rightKey }; app.lines.push(newLine); app.undoStack.push({ type: add, line: newLine }); } draw(); }这里的语义是左侧一个选项只能连一条线如果用户拖着新线落到同一左侧节点上旧线被替换。替换操作在 undo 栈里记录旧线和新线撤销时把新线换回旧线即可。这个“左 key 唯一”的规则是大多数连线题的标准玩法也避免了同一条左节点同时连到多个右侧答案的混乱局面。为什么不用线的 id因为连线题里一条线的身份就是 leftKey 到 rightKey 的映射线本身没有其他业务属性用 key 查找更直接。如果你的题目要求一个左节点可以连多个右节点就把findIndex改为push并放开重复限制但那样答案判定逻辑也需要一起改。4.2 提交判分与答案归一化忽略大小写和未完成状态的兜底数据记录在案后判分就是纯粹的映射比较。先定义标准答案再遍历用户连线数组比对。为了让答案兼容题面可能的大小写问题我在比对前统一做一次归一化右列 key 若来自用户拖拽的 DOM 节点本来就是定值防的是出题人把标准答案写成「JavaScript」而右列节点写「javascript」这类情况。function normalizeKey(key) { return String(key).trim().toLowerCase(); } function judge() { const answerKeys Object.keys(app.stdAnswer); if (app.lines.length answerKeys.length) { return { done: false, code: unfinished, correct: 0, total: answerKeys.length }; } let correct 0; app.lines.forEach((line) { const stdRight app.stdAnswer[normalizeKey(line.leftKey)]; if (normalizeKey(line.rightKey) stdRight) { correct 1; } }); return { done: true, code: finished, correct, total: answerKeys.length }; }判分有两个细节容易踩。第一lines的长度必须达到标准答案的数量才算完成少一条就要提示「还有未完成的连线」否则用户连一半提交判分结果毫无意义。第二归一化放在两个 key 上一起做trim去掉意外空格toLowerCase统一大小写这样「JavaScript」和「javascript」能正常匹配。这个归一化习惯在文本型答案、简答题场景里同样通用。4.3 撤销与重置给用户留好后悔药交互题一定要允许改错。撤销的本质是“弹出上一个操作并反向执行”重置的本质是“清空所有记录并重绘”。这里最难的一点是撤销要对 add 和 replace 两种操作分别处理否则会出现撤销后线还在的诡异现象。function undo() { const step app.undoStack.pop(); if (!step) return; if (step.type add) { const idx app.lines.indexOf(step.line); if (idx -1) app.lines.splice(idx, 1); } else if (step.type replace) { const idx app.lines.findIndex((l) l.leftKey step.newLine.leftKey); if (idx -1) app.lines[idx] step.oldLine; } draw(); } function reset() { app.lines []; app.undoStack []; draw(); }add 操作的撤销是删除replace 操作的撤销是把新线替换成旧线。注意 replace 撤销里我改用了leftKey查找而不是比较引用因为在多次替换后新线的引用可能已经被后续操作覆盖按 leftKey 找更稳。撤销按钮绑定到页面上时记得在undo()后重绘并更新已答题数。如果用户撤销了最后一条线判分状态要从“已提交”退回“进行中”这个状态变化要同步给 UI 上的“提交”按钮。很多连线题在这个边界上翻过车——线看起来撤掉了但提交按钮还是灰的。5. 连线题最容易翻车的 4 个坑坐标偏差、白屏、触摸事件与命中穿透这个方案跑通不难但上线前有几个高频问题几乎每个人都会撞到。我把它们集中在这一章每条都按“现象 → 原因 → 解决”的排查思路写方便你对照自己的项目。5.1 高清屏点击偏位canvas 的绘图尺寸和 CSS 尺寸是两套坐标系现象在 Retina 屏或手机浏览器上按下去画线线条起点和手指落点差一截而且设备像素比越高偏差越大。原因canvas 默认绘图缓冲区以像素为单位canvas.width如果没按 DPR 放大浏览器会把 720px 宽的缓冲拉伸到 1440px 的显示宽度绘制坐标系和指针坐标系就脱节了。解决初始化时按window.devicePixelRatio设置canvas.width/height再用setTransform(dpr, 0, 0, dpr, 0, 0)复位坐标系。之后所有绘制和坐标换算都用 CSS 像素代码里不用再到处乘 dpr。5.2 窗口缩放后画布变白resize 要重设尺寸也要重绘现象PC 端拖动浏览器窗口边缘、切换 DevTools 面板、或者手机屏幕旋转后画布上的线全部消失只剩背景色。原因对canvas.width或canvas.height赋新值会重置整个 canvas 的绘图状态并清空内容而 resize 回调里如果没有重新执行draw()或者 resize 的时机早于数据初始化画布就是空的。解决把 resize 处理统一封装成函数先重算app.box和 DPR再调用draw()全量重绘。只要draw()只依赖数据状态不依赖旧画布内容任何时机调用都能恢复到正确画面。这也是我坚持“数据驱动绘制”的原因——canvas 内容只是状态的投影。5.3 touchend 拿不到坐标touches 和 changedTouches 的区别现象移动端测试时松手瞬间控制台报e.clientX is undefined之前的拖拽表现都正常唯独松手那一锤子出问题。原因touchend事件的touches列表里已经没有了手指的触点信息因为手指已经离开屏幕正确数据在changedTouches里。直接用e.touches[0].clientX必然会拿不到。解决如果你用的是 Pointer Events这个坑自然不存在pointerup直接用e.clientX。如果因为兼容性用了传统 touch 事件touchend里必须取e.changedTouches[0]touchstart里倒是两者都能用但统一都从changedTouches取可以省去排查心智。5.4 canvas 挡住点击pointer-events 没设事件全被画布吃掉现象选项节点看得见摸得着但点击没反应或者要点击好几次才生效DevTools 里看事件目标始终是 canvas。原因canvas 绝对定位覆盖了整个容器作为 DOM 里最上层的元素它拦截了所有鼠标和触摸事件。监听器绑在容器上事件目标却指向 canvasclosest(.node)自然扑空。解决给 canvas 加pointer-events: none让它只负责显示、不参与事件派发。交互事件的监听统一挂在容器上通过e.target.closest(.node)命中具体节点。这个方案比“手动判断 canvas 坐标再去 numbers 元素”要简单可靠得多。6. 能上线的进阶收尾自适应重绘、键盘提交与结果上报基础功能和踩坑都过完后剩下的是上线前的工程化细节。这里有两个我认为必须要做的能力一是窗口旋转或尺寸变化时保持状态不丢二是答题结果能在页面关闭前稳定送回服务端。6.1 resize 后全量重绘把 draw 写成幂等函数我把draw()设计成纯状态驱动只要app.lines和app.draft不变任何时刻调用它画布内容都完全一致。这带来的好处是resize、撤销、提交判分后都能安全地直接调用。window.addEventListener(resize, () { resizeCanvas(); draw(); });resizeCanvas里已经包含清空画布和重建坐标系所以上面这个组合就是完整的自适应逻辑。手机旋转、PC 拖拽窗口线都会按新布局重新渲染。6.2 提交答案与结果回传sendBeacon 和普通上报怎么选提交按钮的点击处理里先判分再回传。常规 Ajax 上报在页面即将跳转或关闭时可能会被浏览器中断所以我通常分两种场景处理上报方式适用场景注意点fetch / XMLHttpRequest用户点击提交后停留在当前页需要处理 loading 和错误重试navigator.sendBeacon提交后立即跳转或关闭页面无法读到响应结果适合埋点URL 参数跳转同步跳转到结果页答案会暴露在地址栏不适合敏感题const result judge(); if (!result.done) { showToast(还有未完成的连线); return; } navigator.sendBeacon(/api/answer, new Blob([ JSON.stringify({ questionId: q_001, lines: app.lines, correct: result.correct, total: result.total }) ], { type: application/json }));sendBeacon不需要担心请求被页面卸载打断提交后直接跳转结果页也行。但要注意如果服务端要求读返回值做业务判断就还是老老实实用 fetch 或 XMLHttpRequest。连线题的答案本身就是数组结构比单个选择题更适合直接打包上报服务端解析起来也直观。我个人的习惯是把连线题当成一个“状态机 重绘函数”的组合来看待凡是会改变数据的操作最后都调一次draw()这样页面永远呈现最新状态。这套思路落地后连图片替换、选项 shuffle、多题复用都变得很顺手。希望帮到你。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/6 3:53:33

AI Agent触达层设计:让大模型从能想到到够得着的实战指南

1. 项目解剖:Agent-Reach 到底解决了什么问题先说结论:Agent-Reach 是一个面向 AI Agent 开发者的触达层框架,核心解决的是“大模型能想到、但够不着”这件事。我在做这个项目之前,已经踩过好几个 Agent 项目的坑。最常见的一幕是…

2026/10/6 3:53:33

SOLIDWORKS Simulation本地交互接触参数详解:从应用到避坑

说到SOLIDWORKS Simulation里的接触定义,我估计不少工程师都有过这种经历:明明模型、材料、载荷都检查过了,结果一求解要么不收敛,要么接触压力看起来完全不合理,最后折腾半天发现是接触参数那几项没弄明白。尤其是“本…

2026/10/6 3:53:33

OpenHarmony真机跑通Flutter列表页:状态机、异步与性能优化实战

这次我真正在 OpenHarmony 真机上把“万能游戏库App”里的“瑞克和莫蒂地点列表”模块用 Flutter 跑通了。说句实话,刚开始心里没底,毕竟 Flutter for OpenHarmony 的适配还处于快速迭代阶段,做列表页这种最常见的场景恰好可以验证跨端方案的…

2026/10/6 7:18:41

ESP-IDF升级后GDB报No match?工具链与寄存器匹配排查指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 7:18:41

PVE8.0 LXC部署Jellyfin启用Intel核显硬解全指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 7:18:41

华为交换机命令行配置实战:视图、端口、VLAN与排错指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 7:18:41

MST-Net时空预测模型复现指南:并联卷积与GRU注意力机制实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 7:13:41

HCIA-Datacom题库本质是VRP命令行行为映射表

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 6:32:56

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/6 4:01:51

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/5 17:38:27

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 0:03:23

MR25H40CDF+STM32F031C6工业级高可靠数据存储方案

1. 项目概述:为什么在工业现场非得用 MR25H40CDF 配 STM32F031C6 做数据存储?在工厂产线的 PLC 控制柜里、在风电变流器的散热片背面、在矿井监测终端的金属外壳下,你经常能看到一块指甲盖大小的黑色芯片——它既不是 Flash,也不是…

2026/10/6 0:03:23

MRAM+STM32工业断电数据保全实战指南

1. 项目概述:为什么在工业现场非得用 MR25H40CDF 配 STM32F031C6 做数据存储?在工厂产线的PLC柜里、在野外无人值守的环境监测终端里、在高速运转的包装机控制板上,你经常能看到一块指甲盖大小的黑色芯片,旁边贴着“MR25H40CDF”丝…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑