EMI云数据平台(数据大屏)— 速记版
项目时间:2022年11月 - 2023年01月 | 工厂设备运行与化工用料实时数据展示 技术栈:Nuxt2 + Vue2 + DataV + v-scale-screen + ECharts + echarts-gl + Element UI + Less 一句话定位:挂在工厂大厅的大屏,实时展示机台效率、环保数据、染化料用量,配合 3D 地球、字幕雨这类要震撼的可视化。
📋 速记表(面试前快速扫)
| 题 | 一句话结论 | 关键词 |
|---|---|---|
| Q1 | v-zoom-up 放大+引导线,scale 反算坐标 | v-zoom-up 反算scale |
| Q2 | echarts-gl globe + lines3D 飞线 | globe lines3D |
| Q3 | v-scale-screen 等比缩放 + client-only 兼容 SSR | 等比缩放 SSR |
| Q4 | Canvas rAF 字幕雨,半透明拖尾 | Canvas rAF 雨 |
| Q5 | clip-path 六边形蜂窝 + content-visibility | clip-path 蜂窝 |
| Q6 | target:static + nuxt-precompress 预压 gz/br | 静态 预压缩 |
| Q7 | rAF 表格自动滚动 + sessionStorage 缓存 | rAF滚动 缓存 |
| Q8 | 自封 Fullscreen API + IE 兜底 F11 | 全屏兼容 IE兜底 |
Q1: v-zoom-up 自定义指令设计
面试官可能问:v-zoom-up 怎么实现放大和引导线?
🗣️ 口述稿:
鼠标悬浮 DataV 边框盒出现放大按钮,点击模块从原位居中放大到屏幕中央,原位置 Canvas 画虚线框+网格"引导线",点遮罩/引导线恢复。动态创建按钮、getBoundingClientRect 记 originRect、加遮罩 + CSS 过渡 + transform:scale(1.35) 放大。
💡 关键词提示:放大按钮 引导线 transform:scale
⚠️ 备注:
- 最值钱的是坐标系转换:外层 v-scale-screen 缩放后 offsetLeft 是缩放布局坐标,要居中必须反算
diffX=(window.innerWidth-rect.width)/2/scaleWidth - elOffsetLeft,能背出公式证明真调过坑 - 每次悬浮 setTimeout 300ms 重取 originRect 防表格刷新导致脏缓存,顺便 pointerEvents:none 防误点
追问①:为什么 mouseenter 时 setTimeout 300ms 再取 originRect?
大屏数据几秒刷新改元素尺寸,缓存旧 originRect 会让引导线偏移。每次悬浮取最新 + pointerEvents:none 防误点。防脏缓存。
追问②:指令的 modifier/arg 干嘛?
v-zoom-up:table-visible(arg) 控制放大时表头半透明适配边框发光;.normalShadow(modifier) 关掉默认 box-shadow。用参数修正不同块的特例。
Q2: echarts-gl 动态地球飞线图
面试官可能问:3D 地球飞线怎么做的?
🗣️ 口述稿:
首页中央 echarts-gl 的 globe 做 3D 地球:baseTexture 卫星图 + heightTexture 地形、displacementScale 起伏、autoRotate 自转。两个 lines3D 系列模拟飞出飞线,effect.trailLength 拖尾、trailColor 配色,起点固定、终点随机经纬度,造全球扩散效果。
💡 关键词提示:globe lines3D 随机终点
⚠️ 备注:
- 讲选型理由:lines3D 是 globe 坐标系专用、effect.show 自带流光不用手写动画。2D lines 没世界地图 geo 撑不起来、linesGL 是另一套坐标系
- 承认终点随机是"效果数据"非真实业务地图,更诚实
- [需自行确认] "65条飞线(33+32)"按仓库 randomData 核对,别背死参数
追问①:3D 地球低配机卡怎么办?
降 displacementQuality、关 postEffect、降环境光计算量。
追问②:为什么终点用随机经纬度?
让每次刷新方向有变化、强调全球扩散动态感,是展示效果数据不是真实业务地图。
Q3: v-scale-screen 屏幕自适应 + SSR 兼容
面试官可能问:大屏怎么适配不同分辨率?
🗣️ 口述稿:
v-scale-screen 按设计稿 2560×1440 等比缩放,监听 resize 取宽高比例较小值做 transform:scale(),2K/4K/1080p 完整展示不破版。v-zoom-up 的居中反算正是靠这个 scale 系数。
💡 关键词提示:等比缩放 取小值 scale系数
⚠️ 备注:
- 最真实的坑是 Nuxt2 SSR:v-scale-screen 依赖 DOM,SSR 报错。用
<client-only>包裹只客户端渲染 + dv-loading 遮初始化 - 为什么不用 rem/百分比:等比保证逐像素一致绝不破版,大屏要所见即得
追问①:它跟 v-zoom-up 坐标什么关系?
正是 scale 缩放让 v-zoom-up 居中要反算。window.innerWidth/2560 是 scale 系数、diffX/scaleWidth 反算偏移。同一套心智两处贯通。
追问②:为什么不用 rem 百分比?
等比保证逐像素一致不破版;rem/百分比是自适应不是等比。大屏要所见即得。
Q4: 字幕雨(Matrix Rain)
面试官可能问:代码雨效果怎么实现?
🗣️ 口述稿:
Canvas 全屏 + requestAnimationFrame 逐帧。每帧先画半透明背景让旧字符逐渐消失成拖尾,再遍历每列 rainDropPositionArray[i]++ 画一个从字符池随机取的字符,触底 90% 概率重置该列从头下落。列数是 canvasWidth/fontSize,降帧 speed 控到约 30fps。
💡 关键词提示:Canvas rAF 90%重置
⚠️ 备注:
- 为什么 Canvas 不是 CSS:CSS 要为每列建 DOM,142 列×多字符下落海量节点,Canvas 一个元素全画
- rAF 做了 webkit/moz/o/ms 前缀兜底 setTimeOut(1000/60),因为工业大屏可能跑旧 Chrome
追问①:rAF 兼容性怎么处理?
手动做 webkit/moz/o/ms 前缀兜底到 setTimeOut(1000/60)。工业大屏可能跑旧 Chrome,兼容老环境意识。
Q5: 六边形背景动态闪烁
面试官可能问:顶部蜂巢背景怎么做的?
🗣️ 口述稿:
纯 CSS:clip-path: polygon(...) 切六边形,5 行×每行 120 个 flex 交错排列,generateGlitch 每 2s 遍历按 Math.random()>0.5 随机切亮,配合 transition 产生电路板闪烁。
💡 关键词提示:clip-path flex交错 随机切亮
⚠️ 备注:
- 为什么 CSS 不是 Canvas:clip-path+flex 原生适配宽度,虽然 600 个 DOM 有开销,用 content-visibility:auto 跳过屏外渲染 + mask 渐变淡出
追问①:600 个 DOM 会不会卡?
会有一点,所以用 content-visibility:auto 让浏览器跳过屏外渲染,只给可见区做 transition。
Q6: Nuxt2 静态生成 + 预压缩
面试官可能问:Nuxt2 部署和优化怎么做的?
🗣️ 口述稿:
target:'static' + npm run generate 出纯静态文件部署 Nginx,DataV 数据前端 Axios 实时拉所以不需要 SSR。nuxt-precompress 构建时生成 .gz+.br 双格式(gzip level9/brotli level11),Nginx gzip_static on 优先返 brotli。
💡 关键词提示:target:static nuxt-precompress gzip_static
⚠️ 备注:
- 为什么静态不 SSR:数据前端轮询拉不是渲染注入,静态+Nginx 免运维不用养 Node 进程
- [需自行确认] "brotli 比 gzip 高15-25%"是常识非本项目实测;端口按仓库 server.port 核对
追问①:gzip_static 和实时 gzip 差别?
静态预压缩构建期压好,请求时不 CPU 实时压、响应更快;实时 gzip 每次请求都压耗 CPU。
Q7: 表格自动滚动 + sessionStorage 缓存
面试官可能问:底部表格自动滚动和缓存怎么做的?
🗣️ 口述稿:
三个底部表格用 requestAnimationFrame 驱动 scrollTop+=1,触底 scrollTop=0 无限循环;鼠标悬浮暂停离开恢复。数据首次拉完 sessionStorage 缓存,切 tab 回来直接用不重新请求。
💡 关键词提示:rAF滚动 触底循环 sessionStorage
⚠️ 备注:
- 为什么 rAF 不 setInterval:和刷新率同步更平滑、后台自动暂停省资源、setInterval 后台降频
- 为什么 sessionStorage:v-if 切换每次重挂载,缓存避免重复请求。承认是体验优化非强一致方案
追问①:缓存会不会读到旧数据?
sessionStorage 当前标签页级、关页即清,数据又持续刷新,缓存只为避免切 tab 重请求,真实度要求不高够用。是体验优化不是强一致。
Q8: 全屏 API 跨浏览器兼容
面试官可能问:大屏全屏功能怎么兼容?
🗣️ 口述稿:
自封 Fullscreen API 兼容层:requestFullScreen || webkit || moz || ms,退出同理;老 IE 用 ActiveX WScript.Shell.SendKeys("F11") 模拟;screen.height-clientHeight<=17 + document.fullscreenElement 综合判断状态。
💡 关键词提示:Fullscreen兼容 IE的F11 多信号判断
⚠️ 备注:
- 为什么不用 screenfull.js:包体积敏感,全屏逻辑不到30行,自包还能专做 IE 兜底。讲"按体量砍依赖"
追问①:判断全屏为什么用分辨率差值兜底?
不同浏览器 fullscreenElement 支持不一,用 screen.height-clientHeight<=17 经验值兜底再叠 API 判断。多信号综合的鲁棒思路。
🎙️ 行为面试
为什么做这个项目?
中恒智造给纺织厂做智造,客户要挂工厂大厅/会议室的大屏,实时展示机台效率、水/汽/母液用量、环保数据。之前老板来视察只能看 Excel。我从 0 搭 Nuxt2 + DataV + ECharts 大屏。
💡 关键词:客户大屏 可视化 从0搭建
最大难点?
- v-zoom-up/地球的屏幕坐标反算——v-scale-screen 缩放后 getBoundingClientRect(屏幕像素)和 offsetLeft(缩放布局)两套概念,居中/引导线都要反算 scale
- echarts-gl 在低配机帧率低——降位移精度/关后处理才稳
- Nuxt2 SSR 和纯客户端库冲突——DataV/echarts-gl/v-scale-screen 都要 process.client + client-only,否则 window is not defined
💡 关键词:坐标反算 低配帧率 SSR冲突
遗憾/弯路?
- 用 setInterval 5s 轮询不是 WebSocket——延迟高带宽浪费、更新不及时
- factory/theory 内容页代码重复——都是 dv-border-box 包一层没抽公共组件
- 数据多是 Math.random() mock 没真接 IoT 传感器——该接 MQTT 实时流,实用价值打折
💡 关键词:setInterval轮询 代码重复 mock数据
DataV 和 ECharts 什么区别?
DataV(@jiaminghi/data-view)做装饰性可视化(边框/装饰线/翻牌器/loading),ECharts 做数据可视化(折线/柱状/雷达/3D 地球)。DataV 负责好看、ECharts 负责有数据,互补。
🃏 极简速记卡(面试前5分钟看)
- Q1 v-zoom-up:放大+引导线,scale反算坐标
- Q2 地球:globe+lines3D 随机终点
- Q3 适配:等比缩放+SSR用client-only
- Q4 字幕雨:Canvas rAF+半透明拖尾
- Q5 蜂窝:clip-path+自定义闪烁
- Q6 部署:静态+预压缩gz/br
- Q7 表格:rAF滚动+session缓存
- Q8 全屏:自封装+IE的F11兜底
- 行为 动机:客户大屏;难点:坐标反算+SSR;遗憾:5s轮询+mock数据
上一篇:07-EMI协同管控平台 下一篇:09-中恒智造官网