news 2026/10/9 5:40:57

《HTML + ECharts 打造外卖优惠数据可视化大屏》(附源码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《HTML + ECharts 打造外卖优惠数据可视化大屏》(附源码)

一、项目概述

技术栈:

  • 可视化库:Apache ECharts 5.5(CDN 引入)
  • 页面骨架:原生 HTML + CSS Grid + Flexbox
  • 边框装饰:手写 CSS/SVG(仿 DataV 边框盒,无需引入 DataV 依赖)
  • 部署方式:单文件,双击即可运行,无需 Node 环境

为什么不用 Vue3 + DataV?

原博客用 Vue3 +@kjgl77/datav-vue3搭建,工程化更规范。但如果只是要一张能跑起来的大屏,单文件 HTML 有三个优势:

  1. 双击就能打开,演示、截图、交作业零门槛;
  2. 没有npm install和构建流程,改一行刷新即生效;
  3. DataV 的边框盒本质上是 SVG 装饰,用 CSS 二十几行就能仿个七成像。

展示效果:

二、数据准备

大屏的灵魂是数据。我全部采用可追溯的公开数据,并在页面页脚标注来源——这一点在课程作业和正式汇报里都非常加分。

指标数据来源
在线外卖市场规模2020:7463 亿 → 2025:22850 亿元(+24.47%)网经社《2025 年度中国数字生活市场数据报告》
外卖用户规模2020:4.72 亿 → 2025:6.30 亿人CNNIC《中国互联网络发展状况统计报告》
2025 全行业补贴1730 亿元(三大平台累计)公开报道
日均订单战前 8000 万单 → 峰值 2.5 亿单公开报道
堂食/外卖占比外卖 12.9%(2019)→ 24.1%(2025E)红餐产业研究院

两点诚信声明(建议大家都写上):

  • 2026 年为预测值,在图例和页脚明确标注“2026E”;
  • 省份“优惠力度指数”为示意数据,页面页脚写明“非官方统计”,避免把演示数据当成真实统计。

对应到代码里,就是把数据集中定义在一个区块,方便替换成自己的数据:

/* ---------- 通用常量 ---------- */ const YEARS = ['2020', '2021', '2022', '2023', '2024', '2025', '2026E']; const AXIS_C = '#00bfff'; // 霓虹蓝坐标轴 const SPLIT_C = 'rgba(0, 150, 255, 0.12)'; const PALETTE = ['#00DDFF', '#37A2FF', '#80FFA5', '#FFBF00', '#FF0087', '#9B6BFF']; /* 核心数据集(替换成自己的业务数据即可) */ const MARKET = [7463, 9740, 12470, 15263, 18357, 22850, 24800]; // 市场规模 亿元 const GROWTH = [30.51, 30.51, 28.02, 22.39, 20.27, 24.47, 8.53]; // 同比增速 % const USERS = [4.72, 5.44, 5.21, 5.45, 5.92, 6.30, 6.55]; // 用户规模 亿人 const ORDERS = [4200, 5200, 6100, 7000, 8000, 16500, 12000]; // 日均订单 万单

三、环境搭建

不需要脚手架,新建一个文件夹放两个文件即可:

takeout-dashboard/ ├── index.html # 大屏本体(全部代码都在这一个文件里) └── preview.png # 效果截图

在<body>末尾引入 ECharts。这里做了双 CDN 容错——jsdelivr 挂了自动切 unpkg,避免演示现场白屏:

<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script> <script> if (typeof echarts === 'undefined') { document.write('<script src="https://unpkg.com/echarts@5.5.0/dist/echarts.min.js"><\/script>'); } </script>

四、代码展示

4.1 页面骨架:三栏布局

版式完全对齐原博客:顶部标题栏 +3fr : 6fr : 3fr三栏,左右各叠 3 个面板,中间是“指标卡 + 中国地图”。

<div id="app"> <header class="top"> ... </header> <main class="bottom"> <div class="col left"> <section class="panel"> <span class="c c-tl"></span><span class="c c-tr"></span> <span class="c c-bl"></span><span class="c c-br"></span> <div class="panel-hd"><i></i>在线外卖市场规模(亿元)<span class="tag">网经社口径</span></div> <div class="panel-bd"><div id="c_market" class="chart"></div></div> </section> </div> <div class="col center"> <div class="kpis"> ... </div> <section class="panel"> <div class="panel-hd"><i></i>各省外卖消费热度与优惠力度指数</div> <div class="panel-bd"><div id="c_map" class="chart"></div></div> </section> </div> <div class="col right"> ... </div> </main> <div class="foot"> ... </div> </div>

对应的 CSS 只需要几行 Grid:

#app { display: flex; flex-direction: column; width: 100vw; height: 100vh; } /* 主体三栏 3fr : 6fr : 3fr / .bottom { flex: 1; display: grid; grid-template-columns: 3fr 6fr 3fr; gap: 10px; min-height: 0; } .col { display: grid; gap: 10px; min-height: 0; } .left, .right { grid-template-rows: repeat(3, 1fr); } / 左右各叠 3 块 / .center { grid-template-rows: 118px 1fr; } / 指标卡固定高,地图占满剩余 */

关键点:min-height: 0。Grid 子项默认min-height: auto,内容一撑开就溢出容器,图表会被压扁或撑破布局。加上它,面板高度才能被严格约束。

4.2 科技风样式:手写仿 DataV 边框盒

DataV 的dv-border-box-1本质就是“四角亮色 L 形 + 半透明面板 + 内发光”。用 CSS 伪元素 + 4 个角标 span 即可复刻:

.panel { position: relative; background: linear-gradient(180deg, rgba(8,40,96,.42), rgba(3,16,44,.62)); box-shadow: inset 0 0 22px rgba(0,110,255,.28), 0 0 0 1px rgba(0,160,255,.16); border-radius: 4px; display: flex; flex-direction: column; } /* 四角 L 形亮边 */ .c { position: absolute; width: 13px; height: 13px; z-index: 2; } .c-tl { top: -1px; left: -1px; border-top: 2px solid #23d8ff; border-left: 2px solid #23d8ff; box-shadow: -1px -1px 8px rgba(35,216,255,.6); } .c-tr { top: -1px; right: -1px; border-top: 2px solid #23d8ff; border-right: 2px solid #23d8ff; box-shadow: 1px -1px 8px rgba(35,216,255,.6); } .c-bl { bottom: -1px; left: -1px; border-bottom: 2px solid #23d8ff; border-left: 2px solid #23d8ff; box-shadow: -1px 1px 8px rgba(35,216,255,.6); } .c-br { bottom: -1px; right: -1px; border-bottom: 2px solid #23d8ff; border-right: 2px solid #23d8ff; box-shadow: 1px 1px 8px rgba(35,216,255,.6); }

页面背景用网格底纹 + 顶部径向光晕,是大屏“科技感”的来源:

body { background: #000; background-image: radial-gradient(ellipse at 50% 0%, rgba(0,110,255,.18), transparent 60%), linear-gradient(rgba(0,178,255,.045) 1px, transparent 1px), linear-gradient(90deg, rgba(0,178,255,.045) 1px, transparent 1px); background-size: 100% 100%, 40px 40px, 40px 40px; }

标题的“渐变字 + 霓虹发光”:

.top-title { font-size: 26px; font-weight: 700; letter-spacing: 4px; background: linear-gradient(180deg, #fff 10%, #7ce7ff 55%, #00a2ff 100%); -webkit-background-clip: text; background-clip: text; color: transparent; text-shadow: 0 0 18px rgba(0, 200, 255, .55); } .top-title .hl { color: #ffd873; -webkit-text-fill-color: #ffd873; } /* 高亮“外卖优惠” */

顶部标题栏效果:

4.3 实时时钟与全屏按钮

原博客在标题栏放了实时时钟,这里用 10 行原生 JS 实现,另加一个全屏按钮方便演示:

function pad(n) { return String(n).padStart(2, '0'); } function tick() { const now = new Date(); document.getElementById('clock').textContent = `${now.getFullYear()}-${pad(now.getMonth()+1)}-${pad(now.getDate())} ` + `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`; } tick(); setInterval(tick, 1000); document.getElementById('fsBtn').addEventListener('click', () => { if (!document.fullscreenElement) document.documentElement.requestFullscreen(); else document.exitFullscreen(); });

4.4 图表通用配置:统一配色与 Tooltip

七个图表共用一套视觉语言,抽成公共对象,改主题色只动一处:

const TOOLTIP = { backgroundColor: 'rgba(2, 16, 40, 0.92)', borderColor: '#00bfff', borderWidth: 1, textStyle: { color: '#e6f6ff', fontSize: 12 }, extraCssText: 'box-shadow:0 0 16px rgba(0,180,255,.45);' }; /* 坐标轴统一样式 */ function axis(name) { return { axisLine: { lineStyle: { color: AXIS_C } }, axisLabel: { color: AXIS_C, fontSize: 10 }, axisTick: { show: false }, splitLine: { lineStyle: { color: SPLIT_C } }, name, nameTextStyle: { color: '#6fa8d4', fontSize: 10 } }; } /* 统一注册 + 统一 resize */ const charts = {}; function reg(id, opt) { const inst = echarts.init(document.getElementById(id)); inst.setOption(opt); charts[id] = inst; return inst; } window.addEventListener('resize', () => Object.values(charts).forEach(c => c.resize()));

4.5 左上:市场规模(柱状图 + 折线双轴)

一个图讲两个维度:柱子看规模,黄线看增速。柱子用线性渐变,这是大屏质感的关键。

reg('c_market', { color: PALETTE, tooltip: Object.assign({ trigger: 'axis', axisPointer: { type: 'shadow' } }, TOOLTIP), grid: { left: 6, right: 6, top: 34, bottom: 4, containLabel: true }, legend: { data: ['市场规模', '同比增速'], right: 8, top: 0, itemWidth: 12, itemHeight: 7, textStyle: { color: AXIS_C, fontSize: 10 } }, xAxis: Object.assign({ type: 'category', data: YEARS }, axis()), yAxis: [ Object.assign({ type: 'value', name: '亿元' }, axis()), Object.assign({ type: 'value', name: '%', max: 60 }, axis()) ], series: [ { name: '市场规模', type: 'bar', data: MARKET, barWidth: '46%', itemStyle: { borderRadius: [3, 3, 0, 0], color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: '#4dfbff' }, { offset: 0.5, color: '#12b3ff' }, { offset: 1, color: 'rgba(0,80,200,0.25)' } ]) }, label: { show: true, position: 'top', color: '#7fe3ff', fontSize: 9.5 } }, { name: '同比增速', type: 'line', yAxisIndex: 1, data: GROWTH, smooth: true, symbol: 'circle', symbolSize: 6, lineStyle: { width: 2, color: '#FFBF00', shadowColor: '#FFBF00', shadowBlur: 10 }, itemStyle: { color: '#FFBF00', borderColor: '#fff', borderWidth: 1 }, label: { show: true, position: 'top', color: '#FFBF00', fontSize: 9, formatter: '{c}%' }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 5:40:56

企业AI Agent定制:条款指向附件,为何就查不到?

一份采购合同里写着&#xff0c;付款节点与违约责任详见附件三。员工向助手提问违约金的计算方式&#xff0c;得到的回答是资料中没有找到相关说明。打开合同原件可以看到&#xff0c;附件三确实随合同一并上传&#xff0c;内容里也写清了比例&#xff0c;只是助手没有把正文里…

作者头像 李华
网站建设 2026/10/9 5:38:57

多平台运营资源分散怎么破?一盘货+内容复用+统一数据口径

做了几年跨境&#xff0c;最深的感触是&#xff1a;多平台经营这件事&#xff0c;做对了是放大器&#xff0c;做不对就是吸血鬼。平台多确实意味着流量入口多&#xff0c;但也意味着人力、资金、库存、注意力被切得更碎。我见过不少同行&#xff0c;摊子从一个平台铺到五六个平…

作者头像 李华
网站建设 2026/10/9 5:38:53

『项目管理精要』第 0 章 导读与心智重塑:开发者到技术管理者的认知跃迁

导读概要:对于大多数软件工程师而言,走向技术管理(Tech Lead / 团队 Leader)往往意味着一次痛苦的认知重建。习惯了“输入代码 -> 输出功能”的确定性编程思维后,面对人际沟通、需求变更、资源争抢与双重汇报等非确定性环境,极易产生无所适从感。本章旨在帮助开发者完…

作者头像 李华
网站建设 2026/10/9 5:38:50

superpowers技能包:为Claude Code注入资深工程师工作流

最近有个词在开发者圈子里热度特别高&#xff0c;就是 superpowers。很多人第一次听说它的时候都挺懵&#xff1a;这到底是个新框架&#xff1f;新插件&#xff1f;还是某种炼丹技巧&#xff1f;如果你正在用或者准备入坑 Claude Code&#xff0c;那 superpowers 大概率是绕不开…

作者头像 李华
网站建设 2026/10/9 5:38:21

园区网关表免集中器怎么接?4G 母表带子表拓扑

园区网关表&#xff0c;通常指的是一台带 4G 上行的母表&#xff0c;经 RS485 带多台子表、替现场省掉独立集中器的方案。该方案适用于楼栋集中、不想动原有布线的老旧园区。摘要&#xff1a;本文介绍园区网关表方案——以一台带 4G 上行的母表经 RS485 带多台子表&#xff0c;…

作者头像 李华
网站建设 2026/10/9 5:38:17

Android 物联网组网实战:红外从零到落地

摘要:本文是一篇面向新手的 Android 红外遥控开发实战教程。文章从开发环境搭建与硬件选型讲起,逐步拆解红外通信原理与 NEC 协议编码逻辑,详解 ConsumerIrManager 的权限配置与核心发送代码实现,并完整演示万能遥控器应用的构建流程。内容涵盖红外码值库构建、学习模式与自…

作者头像 李华