12KB的flotr2:轻量级Canvas图表库实战指南
简介这份资源面向需要在网页中实现数据可视化的前端开发者与初学者提供Flotr2图表库的核心压缩文件及配套入门示例。Flotr2支持折线图、柱状图、饼图、散点图等多种图表类型可与HTML、CSS和JavaScript结合满足报表展示、数据分析等场景的绘图需求。压缩包共3个文件包含1个js核心库、1个html演示页面和1个txt说明文档整体约33KB体积轻量适合直接引入生产环境使用。其中min.js为压缩混淆版本加载速度快演示页面则完整呈现数据组织、图表类型选择、颜色与轴刻度配置、图例设置等基本流程帮助读者快速理解API调用方式。目前已有355人学习下载。通过研读示例并对照官方Demo地址读者可进一步掌握响应式重绘、事件交互与大数据集性能优化等进阶知识点为项目中的数据可视化界面开发提供实用参考。1. 别急着上 ECharts一个 12KB 的 flotr2.min.js 能顶住多少图表需求上周帮一个做后台管理系统的朋友看页面性能他那个监控面板加载了 ECharts 全量包光图表库就吃掉 800 多 KB首屏白屏快两秒。我问他这些图表复杂吗无非是几条折线、几个柱状图、一个饼图。他愣了一下说那还能用啥我把 flotr2.min.js 丢给他压缩后 12KB 左右Canvas 渲染不依赖 jQuery老项目直接 script 标签引进去就能跑。他换完之后首屏直接快了一截代码量还少了一半。flotr2 这个库在图表圈里算是个老资历但一直没被淘汰原因很简单它把「画图」这件事做得足够纯粹。没有虚拟 DOM没有响应式系统没有一堆你永远用不上的交互插件。你给它一个 div 容器、一组数据、一份配置它就在 Canvas 上把图画出来。适合谁适合那些页面以数据展示为主、不需要 3D 或地图、对包体积敏感、或者维护着 jQuery 时代老项目的开发者。如果你正在做一个内部工具、监控看板、报表页面或者单纯想给一个静态页面加两张图这个包值得你花十分钟试一下。2. flotr2 的渲染机制与最小可用配置从 Canvas 坐标系到第一个折线图2.1 为什么是 Canvas 而不是 SVG选型背后的取舍flotr2 底层用的是 HTML5 Canvas这和 ECharts 默认的 Canvas 渲染、D3 常用的 SVG 路线有本质区别。Canvas 是像素级绘制图表一旦画上去就是一张位图浏览器不需要为每个数据点维护 DOM 节点。这意味着两件事第一数据量大时性能衰减比 SVG 慢得多几千个点依然能保持流畅第二交互需要自己算坐标因为 Canvas 不提供元素级的命中检测。flotr2 帮你把这层交互封装好了。鼠标移到数据点上显示 tooltip、框选区域缩放、点击图例切换系列显隐这些它都内置了。你不需要写 Canvas 的getImageData或者手动做坐标映射。但代价是它的交互风格偏「工具型」没有 ECharts 那种平滑动画和精致的过渡效果。如果你的产品对视觉动效要求极高flotr2 可能不够炫但如果你的目标是「把数据说清楚」它的默认样式已经够用。另一个选型理由是依赖。flotr2 不依赖任何第三方库独立运行。你不需要先引 jQuery 再引图表库也不需要处理 npm 包之间的 peer dependency 冲突。对于老项目或者简单的静态页面这种零依赖特性省掉了很多构建配置的麻烦。2.2 引入与初始化一个完整的可运行页面先看最小可运行示例。新建一个 HTML 文件把 flotr2.min.js 放在同目录或者你的静态资源路径下然后按下面的结构写!DOCTYPE html html langzh-CN head meta charsetUTF-8 titleflotr2 最小示例/title !-- 引入 flotr2 压缩包路径按实际存放位置调整 -- script src./flotr2.min.js/script style /* 容器必须有明确的宽高否则 Canvas 无法确定绘制区域 */ #chart-container { width: 600px; height: 400px; border: 1px solid #e0e0e0; } /style /head body div idchart-container/div script // 准备数据flotr2 接受的数据格式是 [[x1, y1], [x2, y2], ...] var rawData [ [0, 12], [1, 18], [2, 15], [3, 22], [4, 28], [5, 24], [6, 30], [7, 35], [8, 32], [9, 40] ]; // 调用 Flotr.draw 绘制第一个参数是 DOM 容器第二个是数据系列第三个是配置 Flotr.draw( document.getElementById(chart-container), [{ data: rawData, label: 访问量, lines: { show: true }, points: { show: true } }], { title: 近十天访问趋势, xaxis: { title: 日期, tickDecimals: 0 }, yaxis: { title: 次数, min: 0 }, grid: { color: #cccccc, verticalLines: false }, legend: { position: ne }, mouse: { track: true, relative: true } } ); /script /body /html这段代码的逻辑很直白。Flotr.draw是全局入口接收三个参数容器元素、数据系列数组、配置对象。数据系列里每个对象代表一条线或一组柱data是二维数组label用于图例显示lines和points控制是否显示线和点。配置对象里xaxis和yaxis定义轴标题和刻度格式grid控制网格线样式legend决定图例位置mouse.track开启鼠标追踪后 tooltip 才会出现。参数说明几个容易踩坑的地方。tickDecimals: 0表示 x 轴刻度不显示小数如果你的 x 轴是日期或整数序号这个必须设否则会出现 0.5、1.5 这种没意义的刻度。yaxis.min: 0强制 y 轴从零开始不设的话 flotr2 会自动计算最小值有时候会让柱状图的柱子看起来「悬空」。grid.verticalLines: false去掉竖网格线页面会干净很多这个看个人审美。2.3 数据格式与系列配置多折线、柱状与饼图的写法flotr2 支持同一张图上叠加多种图表类型。比如你想同时画柱状图和折线图数据系列里分别指定bars: { show: true }和lines: { show: true }就行。下面是一个多系列混合的配置片段var salesData [ [1, 120], [2, 150], [3, 130], [4, 180], [5, 200] ]; var profitData [ [1, 30], [2, 45], [3, 38], [4, 52], [5, 60] ]; Flotr.draw( document.getElementById(chart-container), [ { data: salesData, label: 销售额, bars: { show: true, barWidth: 0.5, fillColor: #4a90d9 } }, { data: profitData, label: 利润, lines: { show: true, lineWidth: 2 }, points: { show: true, radius: 4 }, color: #e67e22 } ], { xaxis: { ticks: [[1,一月],[2,二月],[3,三月],[4,四月],[5,五月]] }, yaxis: { min: 0 }, legend: { position: nw }, grid: { verticalLines: false } } );这里bars.barWidth控制柱宽取值是相对刻度间距的比例0.5 表示柱子占一半宽度。xaxis.ticks允许你自定义刻度标签传入[值, 显示文本]的数组做月份、季度这种中文标签时很实用。color属性可以覆盖系列颜色不设的话 flotr2 会从默认色板里取。饼图的数据格式略有不同它不需要 x 轴数据是[label, value]的形式var pieData [ [直接访问, 335], [搜索引擎, 420], [社交媒体, 180], [外部链接, 95] ]; Flotr.draw( document.getElementById(chart-container), [{ data: pieData, type: pie, label: 流量来源 }], { pie: { show: true, explode: 10 }, legend: { position: se } } );pie.explode控制饼图扇区分离的距离设 10 会有一点「炸开」的效果设 0 就是紧贴的圆饼。饼图不需要xaxis和yaxis配置设了也不会生效。3. 把 flotr2 接进真实项目动态更新、事件响应与老项目兼容3.1 动态数据刷新定时器与重绘的正确姿势后台监控面板的数据通常需要定时刷新。flotr2 没有提供「更新数据」的 API每次刷新都要重新调用Flotr.draw。但直接重复调用会不断往容器里追加 Canvas 元素导致内存泄漏。正确的做法是先清空容器再重绘var container document.getElementById(chart-container); function renderChart(data) { // 清空容器内所有子元素避免 Canvas 叠加 container.innerHTML ; Flotr.draw(container, [{ data: data, lines: { show: true } }], { yaxis: { min: 0 }, grid: { verticalLines: false } }); } // 模拟每 5 秒拉一次数据 setInterval(function () { // 实际项目中这里换成 fetch 或 ajax 请求 var newData generateRandomData(); renderChart(newData); }, 5000);container.innerHTML 这一行是关键。flotr2 每次 draw 都会在容器内创建一个新的 Canvas不清空的话旧 Canvas 还在 DOM 里虽然看不见但占着内存。如果你的刷新频率很高比如每秒一次建议把间隔拉到 3 秒以上或者用requestAnimationFrame做节流。Canvas 重绘本身不慢但频繁的 DOM 操作和内存分配会累积。另一个细节是数据量。如果每次刷新返回的数据点超过 500 个建议在服务端做降采样或者在前端用滑动窗口只保留最近 N 个点。flotr2 虽然比 SVG 方案能扛但也不是无限的几千个点加上 tooltip 追踪低端设备上会感觉到卡顿。3.2 事件绑定点击数据点与区域选择flotr2 提供了几个回调钩子最常用的是mouse配置里的track和click。track控制 tooltip 显示click可以拿到点击位置对应的数据点信息Flotr.draw( document.getElementById(chart-container), [{ data: rawData, lines: { show: true }, points: { show: true } }], { mouse: { track: true, trackAll: true, click: function (e, pos, item) { if (item) { // item 包含 seriesIndex、dataIndex、x、y 等信息 console.log(点击了第 item.seriesIndex 条线的第 item.dataIndex 个点); console.log(坐标, item.x, item.y); // 可以在这里弹窗、跳转或做其他业务逻辑 } } } } );trackAll: true表示鼠标移动时显示所有系列在该 x 位置的值不设的话只显示最近的那个点。click回调的第三个参数item在点击到数据点时才有值点空白区域是null所以必须做判空。这个回调在移动端也能用但触摸事件的坐标精度不如鼠标点击热区偏小如果面向移动端建议把points.radius调大一点或者额外加一个「点击区域」的透明层。3.3 与 jQuery 老项目共存命名冲突与加载顺序很多维护中的老系统还在用 jQueryflotr2 和它并不冲突但要注意加载顺序。flotr2 不依赖 jQuery所以谁先谁后都行但如果你用了 jQuery 的$(document).ready来初始化图表要确保 flotr2.min.js 在 ready 回调执行前已经加载完毕。常见做法是把 script 标签放在 body 底部或者用defer属性script src./jquery.min.js/script script src./flotr2.min.js defer/script script // 如果用 defer这段内联脚本会在 flotr2 加载后执行 window.addEventListener(DOMContentLoaded, function () { Flotr.draw(document.getElementById(chart-container), data, options); }); /script如果你的项目用了 AMD 或 CommonJS 模块化flotr2 也支持。它检测到define或module.exports时会走模块导出否则挂到window.Flotr上。在 webpack 项目里可以直接require(./flotr2.min.js)但要注意它没有 TypeScript 类型声明需要自己补一个.d.ts或者用// ts-ignore绕过。4. 避坑与排查flotr2 实际使用中的五个血泪教训4.1 容器宽高为 0 导致图表不显示现象页面加载后容器区域一片空白控制台没有报错Canvas 元素存在但尺寸是 0×0。原因flotr2 在 draw 时读取容器的offsetWidth和offsetHeight如果容器被隐藏display: none或者父级没有确定宽高读到的就是 0。Canvas 按 0 尺寸绘制自然什么都看不到。解决确保容器在 draw 之前已经渲染并且有明确的宽高。如果图表在 tab 切换或弹窗里等容器显示后再调用 draw。可以用setTimeout延迟一帧或者在 tab 切换的回调里触发重绘。4.2 数据点为空或格式错误导致整图不渲染现象某条线的数据为空数组或者数据里混入了null、undefined、字符串整个图表都不画了。原因flotr2 对数据格式的容错性一般遇到非法值会直接中断绘制流程而且不一定会抛出明确的错误信息。解决在传入之前做一次清洗。用filter去掉空值用Number()确保每个坐标都是数字。如果某条线暂时没有数据传空数组[]是可以的但不要传null或undefined作为整个系列。4.3 tooltip 显示但数值精度失控现象鼠标悬停时 tooltip 里的数字出现12.000000000000002这种浮点误差或者日期显示成时间戳。原因JavaScript 浮点运算的固有问题加上 flotr2 默认不对数值做格式化。解决在mouse配置里用trackFormatter自定义 tooltip 内容mouse: { track: true, trackFormatter: function (obj) { // obj 包含 series 和 data 信息自行控制精度 return obj.series.label : obj.y.toFixed(2); } }toFixed(2)保留两位小数日期的话用new Date(obj.x).toLocaleDateString()转换。4.4 图例遮挡数据区域现象图例放在右上角正好盖住了最后几个数据点用户看不到完整趋势。原因flotr2 的图例是浮动在 Canvas 上的不参与布局计算默认位置可能和你的数据区域重叠。解决调整legend.position可选nw、ne、sw、se。如果四个角都挡可以把图例放到容器外面用 HTML 自己写一个图例通过Flotr.draw返回的图表对象拿到系列颜色手动渲染。或者给yaxis.max设一个比实际最大值大 20% 的值给图例留出空间。4.5 在 Vue/React 组件里重复初始化导致内存泄漏现象单页应用切换路由再回来图表越画越多页面越来越卡DevTools 里能看到大量游离的 Canvas 元素。原因组件销毁时没有清理 flotr2 创建的 Canvas 和事件监听。flotr2 内部绑定了mousemove、click等事件到 Canvas 上组件卸载后这些监听还在。解决在组件的beforeDestroy或useEffect的清理函数里手动清空容器并移除事件。最简单的方式还是container.innerHTML 同时把容器引用置空。如果用了mouse.track建议在销毁前把Flotr.draw返回对象上的mouse相关引用也清掉。React 里可以在useEffect返回的函数中执行清理Vue 里在beforeDestroy钩子处理。5. 进阶技巧用 flotr2 的 API 做自定义渲染与性能验证flotr2 除了Flotr.draw这个入口还暴露了一些底层 API允许你在图表绘制完成后做二次加工。比如Flotr.draw返回的对象包含axes、series、canvas等属性你可以拿到 Canvas 上下文自己画标注线或水印var chart Flotr.draw(container, data, options); // 在图表上画一条水平参考线 var ctx chart.canvas.getContext(2d); var yAxis chart.axes.y; var refValue 25; var pixelY yAxis.d2p(refValue); // 数据值转像素坐标 ctx.save(); ctx.strokeStyle #ff0000; ctx.setLineDash([5, 5]); ctx.beginPath(); ctx.moveTo(chart.axes.x.d2p(0), pixelY); ctx.lineTo(chart.axes.x.d2p(9), pixelY); ctx.stroke(); ctx.restore();d2p是 flotr2 轴对象上的方法把数据值映射到 Canvas 像素坐标。这个在画阈值线、目标线的时候很有用。注意要在Flotr.draw执行完之后再操作否则chart.canvas还是空的。性能验证方面我一般会做一个简单的压测生成 1000、2000、5000 个数据点分别测Flotr.draw的耗时。在普通办公笔记本上1000 个点大约 3050ms2000 个点 80120ms5000 个点会到 300ms 以上这时候就需要考虑降采样或者换用增量渲染方案。测试代码很简单function benchmark(pointCount) { var data []; for (var i 0; i pointCount; i) { data.push([i, Math.sin(i / 10) * 50 50]); } var start performance.now(); Flotr.draw(container, [{ data: data, lines: { show: true } }], { xaxis: { showLabels: false }, yaxis: { showLabels: false } }); var end performance.now(); console.log(pointCount 个点耗时 (end - start).toFixed(1) ms); }关掉轴标签可以减少绘制开销让测试更聚焦在数据渲染本身。如果 5000 个点在你的目标设备上超过 200ms建议在数据源头做聚合比如按分钟或小时取平均值把点数压到 1000 以内。还有一个技巧是复用容器。如果你的页面有多个图表不要每个图表都新建一个 div可以共用一个容器切换时清空重绘。这样 DOM 节点数少内存占用低。但要注意每次重绘前必须清空否则 Canvas 会叠加。从那以后我每次在项目里引入图表库之前都会先问一句数据量多大、交互多复杂、包体积预算多少。如果三个答案都是「不大、不复杂、越小越好」我就直接上 flotr2十分钟搞定不折腾。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

基于YOLOv12的无人机河道巡检水面垃圾检测实战解析

基于YOLOv12的无人机河道巡检水面垃圾检测实战解析

开头无人机 AI 视觉识别已经不是什么新鲜概念了,但真把一套 YOLOv12 模型跑在河道巡检这种实际业务场景里,踩过的坑和趟过的路还是比较有代表性。这个项目做的就是“智慧河道巡检:基于 YOLOv12 的大疆无人机河面塑料垃圾检测”,核…

2026/10/18 1:44:49 阅读更多 →
从文字到成片:ComfyUI-LTXVideo 的 7 类 AI 视频生成落地教程

从文字到成片:ComfyUI-LTXVideo 的 7 类 AI 视频生成落地教程

从文字到成片:ComfyUI-LTXVideo 的 7 类 AI 视频生成落地教程 【免费下载链接】ComfyUI-LTXVideo LTX-Video Support for ComfyUI 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-LTXVideo 拿一张产品图做首帧,用提示词描述动作&…

2026/10/18 1:44:49 阅读更多 →
YOLO26涨点改进 | 全网独家首发,卷积创新改进篇 | TGRS 2025 | 引入FSConv频率–空间卷积模块、基于小波分解高低频双域解耦增强、聚焦高频细节边缘强化、平衡全局空域结构特征、助力

YOLO26涨点改进 | 全网独家首发,卷积创新改进篇 | TGRS 2025 | 引入FSConv频率–空间卷积模块、基于小波分解高低频双域解耦增强、聚焦高频细节边缘强化、平衡全局空域结构特征、助力

目录 一、研究背景与YOLO26传统纯空域卷积固有缺陷 二、FSConv频率–空间卷积模块核心创新原理 2.1 四大核心子单元架构详解 2.1.1 小波频域精准解耦单元(核心基础) 2.1.2 高频细节增强与降噪单元(核心创新) 2.1.3 低频结构优化单元 2.1.4 空频双域自适应融合单元 …

2026/10/18 1:44:49 阅读更多 →

最新新闻

Deep Agents框架:AI代理核心任务规划与分解实战解析

Deep Agents框架:AI代理核心任务规划与分解实战解析

先聊个我最近遇到的典型场景。某次我给一个自己搭的Agent下达任务:“帮我整理本周行业资讯,输出一份简报”。结果它整整回复了八百字,格式工整、措辞得体,可仔细一看,全是通用建议——没有真正的资讯来源,没…

2026/10/18 2:38:02 阅读更多 →
Spring Boot整合Redis实战:序列化、缓存穿透与高并发踩坑复盘

Spring Boot整合Redis实战:序列化、缓存穿透与高并发踩坑复盘

写这篇文章之前,先说个我最近帮一个同事排查问题的场景。他负责的接口加上了 Redis 缓存,但并发一高,数据库还是被冲垮了。我登上去一看,缓存 key 是一串 \xAC\xED 开头的二进制乱码,value 也是 JDK 序列化对象&#x…

2026/10/18 2:38:02 阅读更多 →
AI辅助教材编写如何降低查重率?从初稿到改稿的完整实践方法

AI辅助教材编写如何降低查重率?从初稿到改稿的完整实践方法

写教材这事,听起来是专家干的活,但这两年,越来越多的老师、培训讲师、课程开发者开始用AI辅助编写教材和讲义。我的感受是,AI写初稿是真快,但交出去的稿子质量和查重率往往让人头大。初稿太像“翻译腔”或“论文摘要合…

2026/10/18 2:38:02 阅读更多 →
游戏开发必知的10大测试术语揭秘

游戏开发必知的10大测试术语揭秘

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

2026/10/18 2:38:02 阅读更多 →
用游戏讲透环境变量的神奇作用

用游戏讲透环境变量的神奇作用

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

2026/10/18 2:38:02 阅读更多 →
回归预测可视化指南:用sklearn和matplotlib绘制真实值与预测值对比图

回归预测可视化指南:用sklearn和matplotlib绘制真实值与预测值对比图

回归模型跑完之后,很多人第一件事就是看R和MSE,数字漂亮就认为万事大吉。但我一直觉得,指标只是结果的高度浓缩,真正能暴露模型问题的,是把测试集真实值和模型预测值画在同一张图上,看曲线走势、看偏差分布…

2026/10/18 2:37:02 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/16 14:23:36 阅读更多 →