前言
玩 ESP8266 时总觉得少点温度 —— 多数项目不是控制 LED,就是显示温湿度,技术是有了,但少了点「人情味儿」。这次我试着把「硬件」和「文化」捏在一起:用 ESP8266 搭个网页服务器,把 21 篇中华山水散文(从长城到西湖,覆盖七大地区)存进芯片,手机连 WiFi 就能随时读,界面还带地区分类导航,不用装 APP,打开浏览器就用。
关键是成本不到 15 元,仅需 ESP8266+USB 线,不用额外传感器;代码还做了内存优化,用 PROGMEM 把 100KB + 的 HTML 存进 Flash,避免 ESP8266 内存不够崩溃。新手跟着做,1 小时就能跑通,文末附完整代码和避坑指南。
先看效果:手机电脑访问长这样
不用复杂操作,连 WiFi、输 IP,秒出界面 —— 左侧是「华北 / 东北 / 西北」等七大地区导航,右侧是散文内容,点击按钮秒切文章,排版是仿宋字体,还带作者和时间标注,像个随身的「山水散文集」:
比如点开《敦煌莫高窟记》,能看到「九层楼的飞檐在朝阳下投下阴影,檐角的铁马在风沙中轻响,声如梵呗」这样的细节描写;切到《三亚椰林记》,又能感受到「沙滩的细沙如碎玉,赤足踩上去温热柔软,海浪退去时,沙粒从趾缝间溜走」的画面感 —— 技术承载文化,大概就是这种感觉。(关键:这是自己的网站)
为什么这个项目值得做?
- 新手友好:不用焊线(仅 USB 供电),代码注释超详细,连 WiFi 连接失败的解决方法都写了;
- 技术实用:练会「ESP8266 网页服务器 + PROGMEM 内存优化 + JS 异步加载」,以后做物联网界面都能用;
- 有文化感:不是冷冰冰的代码,而是能带着走的「山水散文库」,给老人、孩子看都合适;
- 可扩展性强:加个 OLED 屏就能脱离手机,加个充电宝就是「便携文旅设备」,玩法很多。
一、物料准备:30 元搞定,不用复杂配件
这个项目的核心是「ESP8266 + 网页」,不用传感器、不用继电器,接线都省了,清单超简单:
| 物料名称 | 型号推荐 | 作用说明 | 参考价 |
|---|---|---|---|
| ESP8266 开发板 | NodeMCU 1.0(ESP-12E) | 核心芯片,跑网页服务器 | 25 元 |
| USB 数据线 | Micro-USB(带数据传输) | 供电 + 烧录代码 | 家里都会有,自备 |
| (可选)充电宝 | 5V/1A | 不是必须,便携供电,出门也能用 | 自备 |
划重点:选 NodeMCU 版型,不用自己焊排针,插 USB 就能用;别买 ESP-01(内存小,还得焊线),新手容易踩坑。
二、开发环境搭建:ESP8266+Arduino IDE
1. 安装 Arduino IDE
先下最新版Arduino IDE(Windows/macOS 通用),安装后打开,界面长这样:
2. 添加 ESP8266 板库(关键步骤)
ESP8266 不是 Arduino 官方板,得手动加板库地址:
- 点「文件」→「首选项」,在「附加开发板管理器网址」里贴这个链接:
http://arduino.esp8266.com/stable/package_esp8266com_index.json
(如果有多个网址,用英文逗号隔开) - 点「工具」→「开发板」→「开发板管理器」,搜索「ESP8266」,找到「esp8266 by ESP8266 Community」,选最新版(比如 3.1.2),点「安装」(等 2-5 分钟,需联网);
- 安装完成后,「工具」→「开发板」选「ESP8266 Boards」→「NodeMCU 1.0 (ESP-12E Module)」;
- 插 ESP8266 到电脑,「工具」→「端口」选对应的 COM 口(Windows 看设备管理器,macOS 看「关于本机」→「系统报告」→「USB」)。 6.选择工具,选择管理库安装ESP8266WiFi、ESP8266WebServer、pgmspace库
5.记得安装对应USB转串口的驱动(比如说CH340)。
3. 验证环境:烧个测试程序
随便写个串口打印的程序,测试是否能正常上传
void setup() {
Serial.begin(115200); // 波特率115200 }
void loop() {
Serial.println("ESP8266连接成功!");
delay(1000);
}
点击上传按键,耐心等一等,看见“Hash of data verified.Leaving... Hard resetting via RTS pin...”说明已经上传成功了!
打开串口监视器,波特率设置为115200,就可以看到串口数据了!到这一步已经成功一大半了!
三、核心逻辑:ESP8266 怎么存 21 篇散文?
这个项目的技术难点是「ESP8266 内存小(仅 80KB RAM),但 21 篇散文 + HTML 界面有 100KB+」,解决方法是用PROGMEM把内容存进 Flash(NodeMCU 有 4MB Flash,足够用),再用「异步加载」按需读取,不占内存。
1. 代码结构拆解
整个代码分 3 部分,逻辑很清晰:
- WiFi 模块:连接家庭 WiFi,打印 ESP8266 的 IP(手机要连同一个 WiFi);
- 网页服务器模块:用
ESP8266WebServer搭服务器,监听 80 端口,按「地区 - 文章」做路由(比如/greatwall对应《万里长城记》); - 内容存储模块:用
const char htmlXXX[] PROGMEM把每篇散文 + HTML 片段存进 Flash,加载时用server.send_P()读取。
2. 关键代码解析(挑重点讲,避免全贴)
PROGMEM 存储散文:解决内存不足
ESP8266 的 RAM 只有 80KB,直接存大字符串会崩溃,用 PROGMEM 把内容存到 Flash(相当于电脑的硬盘),读取时再调用:
// 用PROGMEM存《万里长城记》,R"rawliteral(...)rawliteral"保留HTML格式
const char htmlGreatWall[]
PROGMEM = R"rawliteral( <h1 class="article-title">万里长城记</h1>
<div class="article-meta">甲辰孟秋 | 于八达岭望烽燧</div> <div class="article-content">
<p>晨雾中的长城如灰色巨龙,从燕山深处蜿蜒而来,龙脊在晨光中泛着冷光...</p>
</div> )rawliteral";
四、实操步骤:从烧录到手机访问
改 WiFi 信息
打开完整代码,找到 WiFi 配置部分,替换成你的家庭 WiFi 名称和密码(注意是 2.4G WiFi,ESP8266 不支持 5G):
// 替换成你的WiFi信息
const char* ssid = "你的WiFi名称"; // 比如"TP-Link_1234" const char*
password = "你的WiFi密码";// 比如"12345678"
2. 烧录代码
- 复制完整代码到 Arduino IDE,选对开发板(NodeMCU 1.0)和端口;
- 点「上传」,等待完成(如果上传失败,按住 ESP8266 的 FLASH 键再点上传,松手后重试)。
3. 找 ESP8266 的 IP
1.打开「串口监视器」(波特率 115200),能看到 WiFi 连接日志:
开始连接WiFi
.....
WiFi连接成功!
访问地址: http://192.168.1.100
- 记下这个 IP(比如
192.168.1.100),这是手机电脑访问的地址。(注意:每一个人的ip都不一样,要看自己的)
4. 手机访问:秒变山水阅读器
-
手机连和 ESP8266 同一个 WiFi(比如你家的 2.4G WiFi);
-
打开手机浏览器,输入刚才的 IP(比如
192.168.1.100),就能看到界面:- 左侧:七大地区,21 个文章按钮;
- 右侧:默认加载《万里长城记》,点击其他按钮秒切文章;
- 排版:仿宋字体,段落间距舒适,电脑手机上读不刺眼。
五、避坑指南:新手常踩的 3 个坑
-
WiFi 连接失败,串口一直打点点
- 原因 1:WiFi 名称 / 密码错了(大小写敏感,比如 “TP-link” 和 “TP-Link” 不一样);
- 原因 2:连了 5G WiFi(ESP8266 只支持 2.4G,去路由器设置里把 5G 关掉,或改 WiFi 名称带 “2.4G” 标识);
- 解决:重新检查 WiFi 信息,重启 ESP8266 再试。
-
手机输入 IP 后打不开界面
- 原因 1:手机和 ESP8266 不在同一个 WiFi(比如手机连了 4G,或连了另一个 WiFi);
- 原因 2:IP 变了(ESP8266 重启后 IP 可能变,重新看串口监视器的最新 IP);
- 解决:确保手机连对 WiFi,重新获取 IP。
-
文章加载慢或乱码
- 原因 1:Flash 存储问题(选 NodeMCU 4MB Flash 的版型,别选 1MB 的);
- 原因 2:HTML 编码错了(代码里用了
meta charset="UTF-8",别改); - 解决:换 4MB Flash 的 ESP8266,重新烧录代码。
-
六、进阶扩展:这个项目还能玩出什么花样?
-
加 OLED 屏:脱离手机,按键切换
接个 0.96 寸 OLED 屏(I2C 接口,3 根线),加 2 个按键,不用手机也能操作:按按键切换地区,OLED 显示当前文章标题 + 片段。 -
加 SD 卡:存 100 篇散文都没问题
ESP8266 接 SD 卡模块,把更多散文存在 SD 卡里,用代码读取 SD 卡的 TXT 文件,实现「无限扩展内容」。 -
做便携文旅设备:带出门用
用充电宝给 ESP8266 供电,出门旅游时,手机连 ESP8266 的热点(不用家庭 WiFi),走到长城就看《万里长城记》,走到西湖就看《杭州西湖记》,比查攻略有感觉。 -
加 GPS:自动显示当地山水散文
接 GPS 模块,ESP8266 获取当前位置,自动加载对应地区的散文(比如在桂林,自动打开《桂林山水记》),适合带老人孩子出门玩。七、为什么做这个项目?不只是练技术
一开始只是想练 ESP8266 的网页服务器,后来觉得「技术不该只是冷冰冰的代码」—— 把爷爷喜欢的山水散文存进去,他用手机就能读,不用戴老花镜翻书;带孩子去长城,手机打开就能看《万里长城记》,比单纯拍照有意义。
其实 ESP8266 能做的不只是控制 LED,它可以是「老人的随身散文集」「孩子的地理科普器」,甚至是「文旅爱好者的小众装备」。技术的温度,大概就是把看似不相关的东西捏在一起,变成有用又有情怀的东西。
六、完整代码
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <pgmspace.h>
// WiFi配置
const char* ssid = "yanjie";
const char* password = "dahai@25";
ESP8266WebServer server(80);
// 华北地区
// 文章1:万里长城记
const char htmlGreatWall[] PROGMEM = R"rawliteral(
<h1 class="article-title">万里长城记</h1>
<div class="article-meta">甲辰孟秋 | 于八达岭望烽燧</div>
<div class="article-content">
<p>晨雾中的长城如灰色巨龙,从燕山深处蜿蜒而来,龙脊在晨光中泛着冷光。垛口间穿行的风带着古战场的气息,抚摸着城砖上深浅不一的刻痕——那是六百年风雨与千万人手掌共同雕琢的年轮。</p>
<p>拾级而上,每块城砖都沁着凉意。砖缝间长出的酸枣树挂着红果,根须却深深扎进砖缝,如古兵的手指紧抓着城墙。敌楼上的箭窗呈斜向排列,恰好将关外的旷野纳入视野,想象中羽箭破空的呼啸,似乎还回荡在空旷的拱券里。</p>
<p>正午时分,阳光直射城墙,砖面烫得灼手。登高远眺,长城在群山中起伏,烽燧如棋子般点缀其间,忽然懂得为何古人称其「万里长龙」。风掠过城垣,带着塞外的干燥气息,吹动了游客飘动的衣角,也吹动了箭楼上悬挂的红旗,旗角拍打着斑驳的砖墙,发出猎猎声响。</p>
<p>暮色降临前,残阳为城墙镀上金边。城砖的阴影被拉得很长,如列队的甲士。远处的群山渐渐隐入暮色,唯有长城的轮廓仍清晰可辨,像天地间一道深刻的裂痕。下山时回望,最后一缕阳光从敌楼的箭窗穿过,在地上投下细长的光斑,宛如时光留下的箭痕。</p>
</div>
)rawliteral";
// 文章2:故宫记
const char htmlForbiddenCity[] PROGMEM = R"rawliteral(
<h1 class="article-title">故宫记</h1>
<div class="article-meta">癸卯季冬 | 于太和殿前观瑞雪</div>
<div class="article-content">
<p>雪后的紫禁城,琉璃瓦顶覆着一层素白,檐角的瑞兽在落雪中更显威严。从午门而入,石板路上的积雪被扫向两侧,露出青灰色的地砖,砖缝间仍有残雪,踩上去咯吱作响,与飞檐下铜铃的轻响相和。</p>
<p>太和殿广场空旷如野,汉白玉台基上的雪被风吹成薄薄一层,栏杆上的云纹雕刻在雪中若隐若现。拾级而上,每级台阶都冻着薄冰,扶着雕花栏杆,能感到玉石的冰凉透过手套渗入掌心。大殿前的铜鹤与铜龟顶着积雪,仿佛千年未动的守护者。</p>
<p>乾清宫的「正大光明」匾额在殿内微光中泛着光泽,金砖铺就的地面光可鉴人,倒映着梁柱的影子。廊下的红墙在白雪映衬下,红得如凝固的火焰,墙角的腊梅顶着雪球绽放,暗香浮动,与殿内的檀香交织成时光的味道。</p>
<p>暮色中的角楼最为动人,九梁十八柱在落雪中勾勒出精巧的轮廓,飞檐翘角如鸟翼欲展。护城河上的冰面泛着青灰,倒映着角楼的剪影,雪片落入水中悄无声息,仿佛六百年的光阴都沉在这寂静里。</p>
</div>
)rawliteral";
// 文章3:北戴河记
const char htmlBeidaihe[] PROGMEM = R"rawliteral(
<h1 class="article-title">北戴河记</h1>
<div class="article-meta">甲辰孟夏 | 于老虎石听涛</div>
<div class="article-content">
<p>初夏的北戴河,沙滩仍带着凉意。老虎石群礁在晨雾中如卧海的巨兽,潮水退去后,礁石间的水洼里藏着小蟹,透明的虾子在水中窜动,留下细碎的波纹。海风带着咸涩,吹动岸边的槐树,落英飘落在湿漉漉的沙地上,如撒下的碎雪。</p>
<p>日头升高,雾散处见蓝海接天。栈桥延伸入海,木柱在水中的倒影被浪涛揉碎,又重新聚拢。岸边的遮阳伞如彩色的蘑菇,散落在绿草地上,孩子们追逐着退潮的浪花,笑声与涛声混在一起,惊起几只海鸥,贴着水面盘旋。</p>
<p>鸽子窝的日出最为壮观。赤轮初升时,海面被染成熔金,远处的渔船拖着橘红色的网,网中闪烁着银鳞。滩涂上的赶海人弯腰拾贝,身影被朝阳拉得很长,与停泊的渔船构成一幅剪影画。海风渐暖,带着水草的气息,拂过脸颊如丝绸般轻柔。</p>
<p>暮色中的联峰山,松涛与涛声遥相呼应。山顶的望海亭上,可见渔船归航,帆影点点,渐渐融入暮色。山下的灯火次第亮起,在海面上投下晃动的光斑,与天上的星子连成一片,分不清哪颗在波心,哪颗在云端。</p>
</div>
)rawliteral";
// 东北地区
// 文章4:长白山记
const char htmlChangbaishan[] PROGMEM = R"rawliteral(
<h1 class="article-title">长白山记</h1>
<div class="article-meta">壬寅孟夏 | 于天池畔观云</div>
<div class="article-content">
<p>登长白山时,云在脚下流动。盘山公路如银链缠绕翠峰,车窗外的岳桦林斜向生长,枝干被风雪塑造成奇特的弧线,树皮呈银灰色,如蒙上一层霜。海拔渐高,林木渐稀,最后只剩苔原上的低矮杜鹃,贴着地面绽放,紫花与残雪相映,有种倔强的美。</p>
<p>天池乍现时,众人皆屏息。湛蓝的湖水嵌在火山口,如天遗落的宝镜,四围的峰峦倒映水中,云影掠过湖面,快得让人来不及捕捉。水色随天光变幻,忽而是孔雀蓝,忽而是祖母绿,岸边的火山岩黝黑多孔,与湖水的剔透形成鲜明对比。</p>
<p>乘槎河从天池溢出,初如银线,跌落成长白瀑布,如银河倾泻,坠入深谷的轰鸣震耳欲聋。瀑下的温泉群冒着白汽,硫磺的气息混着草木清香,将鸡蛋浸在温泉中,不多时便熟透,蛋白带着淡淡的硫磺味,是山的味道。</p>
<p>下山时遇阵雨,雨过天晴处见双彩虹横跨峡谷,一头连着密林,一头扎进天池。岳桦林在夕阳中呈金黄色,树干的纹路被阳光勾勒得清晰,林间的松鼠捧着红果,见人不惊,反倒睁着黑亮的眼睛打量,尾巴蓬松如伞。</p>
</div>
)rawliteral";
// 文章5:哈尔滨冰雪大世界记
const char htmlHarbinIceWorld[] PROGMEM = R"rawliteral(
<h1 class="article-title">哈尔滨冰雪大世界记</h1>
<div class="article-meta">癸卯季冬 | 于松花江畔赏冰灯</div>
<div class="article-content">
<p>零下三十度的哈尔滨,呵气成霜。冰雪大世界的入口处,巨大的冰牌坊闪着蓝光,冰砖中的气泡在灯光下如碎钻般闪烁。脚下的冰路覆着薄雪,踩上去咯吱作响,呼出的白气在睫毛上凝结成霜,视线却被远处的冰雕群吸引,如误入水晶宫殿。</p>
<p>白天的冰雕更显清透。百米长的冰滑梯如巨龙伏卧,冰砖的纹理清晰可见,阳光透过冰层,在地上投下流动的光斑。工匠们仍在雕琢新的作品,冰屑在阳光下如金粉飞扬,凿冰的叮当声在寒空中格外清脆。雪雕群则更显温润,雪的肌理如羊脂玉,在阳光下泛着柔和的光泽。</p>
<p>暮色降临,万灯齐亮。冰雕被内部的灯光染成七彩,滕王阁的冰砌飞檐挂着冰灯,黄鹤楼的冰雕斗拱透着暖黄,百米高的冰塔通体透亮,如水晶砌成的通天柱。冰制的十二生肖神态各异,在灯光下栩栩如生,孩子们围着冰猴嬉笑,呼出的白气与冰雕的寒气交融成雾。</p>
<p>夜渐深,寒气更甚。马迭尔冰棍的甜香在寒风中格外清晰,咬一口冰爽彻骨,却越吃越暖。中央大街的面包石路上,冰尜在孩子们的鞭子下旋转,发出嗡嗡的声响,与远处传来的俄式歌声相和,在零下三十度的寒夜里,酿出一种热烈的温暖。</p>
</div>
)rawliteral";
// 西北地区
// 文章6:华山记
const char htmlHuashan[] PROGMEM = R"rawliteral(
<h1 class="article-title">华山记</h1>
<div class="article-meta">癸卯暮春 | 于东峰观日出</div>
<div class="article-content">
<p>夜登华山,石阶嵌在绝壁间,如天梯垂落。铁链上挂满同心锁,在月光下闪着细碎的光,锁环相碰的叮当声,与山风的呼啸、登者的喘息交织成曲。脚下是不见底的深渊,偶有夜行的山鼠窜过,带起的碎石坠入黑暗,许久才传来微弱的回响。</p>
<p>东峰顶寒风刺骨,待至天际泛白,群峰在晨光中渐显轮廓。朝阳跃出云海时,金光如瀑布倾泻而下,将花岗岩的山体染成赤铜色,栈道上的铁链反射着冷光,如缠绕在山腰间的金带。下棋亭孤悬于三面绝壁之上,石桌石凳似天外飞来,传说是宋太祖与陈抟对弈之处。</p>
<p>行至长空栈道,才知「奇险天下第一山」绝非虚言。木板嵌在垂直的崖壁上,下临万丈深渊,仅容一人侧身通过。手抓铁链前行时,能感到岩石的震颤,山风从耳畔呼啸而过,带着松涛与云雾,让人分不清是风声还是自己的心跳。</p>
<p>西峰的莲花石在暮色中如含苞待放的莲蕊,周围的岩体层层叠叠,恰似花瓣。下山时经千尺幢,仰望仅见一线天光,石阶陡如直梯,两侧铁链上的包浆光滑如玉,是千百年登山者用手掌磨出的温润。回望暮色中的华山,群峰如剑插向苍穹,峰顶的云雾则如轻纱,温柔地裹着这些锋利的棱角。</p>
</div>
)rawliteral";
// 文章7:兵马俑记
const char htmlTerracottaArmy[] PROGMEM = R"rawliteral(
<h1 class="article-title">兵马俑记</h1>
<div class="article-meta">甲辰孟秋 | 于一号坑前怀古</div>
<div class="article-content">
<p>走进兵马俑坑,首先被那片灰黑色的方阵震撼。八千陶俑肃立坑中,甲胄分明,面容各异,连发丝都清晰可辨。坑顶的灯光斜照下来,在陶俑身上投下细长的阴影,仿佛这些沉默的士兵刚刚从两千年的睡梦中惊醒,正欲列队出征。</p>
<p>一号坑的军阵最为壮观。前锋的弩兵呈三列横队,战袍下摆随风的弧度被定格在陶土中,身后的战车与步兵相间排列,马俑的肌肉线条饱满,仿佛只需一声令下便会扬蹄嘶鸣。考古人员仍在坑边工作,毛刷轻扫陶片的声音,在空旷的大厅里格外清晰。</p>
<p>陈列馆中的跪射俑保存最完整,发髻偏向右侧,是秦人的典型发式,面部的颧骨高耸,眼神坚定,甲片的叠压层次分明,连鞋底的针脚都清晰可见。据说这尊俑出土时仍保留着淡淡的彩绘,在地下两千年的时光里,默默守护着那些早已褪色的色彩。</p>
<p>暮色中的秦始皇陵封土堆,如巨大的覆斗静卧在平原上。周围的石榴树结满红灯笼似的果实,风吹过树叶的沙沙声,与远处村庄的狗吠相和。想象着地下可能存在的水银江河,忽然明白,这位始皇帝不仅要统治人间,还要将整个宇宙带入永恒的黑暗。</p>
</div>
)rawliteral";
// 文章8:敦煌莫高窟记
const char htmlMogaoGrottoes[] PROGMEM = R"rawliteral(
<h1 class="article-title">敦煌莫高窟记</h1>
<div class="article-meta">辛丑孟夏 | 于九层楼前听风</div>
<div class="article-content">
<p>鸣沙山的晨光中,莫高窟的洞窟如蜂巢嵌在断崖上。栈道蜿蜒其上,木质的台阶被千年的脚步磨得光滑,扶手的栏杆包浆温润,触之如触古玉。九层楼的飞檐在朝阳下投下阴影,檐角的铁马在风沙中轻响,声如梵呗。</p>
<p>第323窟的「张骞出使西域图」色彩仍鲜,张骞持节西行的身影在青绿山水间穿行,线条流畅如行云。讲解员用冷光手电照亮壁画,光斑所及处,北魏的飞天衣带当风,唐代的菩萨丰腴含笑,供养人的衣饰纹样清晰可辨,连鞋履的细节都栩栩如生。</p>
<p>藏经洞虽已空,石壁上仍留有当年藏经的痕迹。狭小的洞窟曾藏有五万件珍宝,如今只剩四壁的经文残片,在昏暗的光线下如神秘的密码。洞外的沙枣树开着细碎的白花,香气清淡,与洞内的尘土气息交织,仿佛时光在此凝固。</p>
<p>傍晚的榆林窟更显静谧。夕阳为佛窟镀上金边,第3窟的水月观音在暮色中更显慈悲,背景的山水用没骨法绘成,墨色浓淡相宜,如米家山水。守窟人锁门时,钥匙碰撞的声响在峡谷中回荡,远处的祁连雪山在暮色中呈青紫色,与洞窟的赭红色崖壁相映,美得让人屏息。</p>
</div>
)rawliteral";
// 西南地区
// 文章9:布达拉宫记
const char htmlPotala[] PROGMEM = R"rawliteral(
<h1 class="article-title">布达拉宫记</h1>
<div class="article-meta">辛丑孟夏 | 于红山之麓仰望</div>
<div class="article-content">
<p>拉萨河谷的晨雾尚未散尽,布达拉宫已从红山之巅升起。白宫的墙垣在朝阳下泛着乳白,红宫的宫殿则如火焰般燃烧,金顶在海拔三千七百米的阳光下,亮得几乎让人睁不开眼。转经的老阿妈摇着经筒,脚步与石阶相叩,发出规律的声响,如时光的脉搏。</p>
<p>拾级而上,白宫的墙是用酥油、蜂蜜、石灰与牦牛奶混合夯筑而成,指尖触处,能感到一种温润的坚硬。廊道两侧的壁画记录着千年往事,色彩在酥油灯的映照下依然鲜艳,颜料中混合的珍珠粉与金箔,让画面在暗处也泛着微光。</p>
<p>红宫的灵塔殿里,檀香与酥油的气息交织成厚重的云雾。五世达赖的灵塔裹着厚厚的金箔,塔顶的珍珠塔刹在灯光下流转着七彩光晕,周围的酥油灯排成银河,灯芯爆裂的轻响与喇嘛的诵经声相和。凭栏远眺,拉萨城如棋盘铺展,大昭寺的金顶在远处闪烁,如另一颗星辰。</p>
<p>暮色中的布达拉宫渐渐隐入深蓝,唯有金顶仍浮在夜色里,与天上的星子连成一片。转经道上的信徒仍在绕行,他们的身影被路灯拉得很长,如流动的经幡。山脚下的拉萨河泛着暗光,倒映着宫墙的轮廓,仿佛把这座宫殿又藏进了水底,成为另一个世界的信仰。</p>
</div>
)rawliteral";
// 文章10:黄果树瀑布记
const char htmlHuangguoshu[] PROGMEM = R"rawliteral(
<h1 class="article-title">黄果树瀑布记</h1>
<div class="article-meta">甲辰孟夏 | 于水帘洞听涛</div>
<div class="article-content">
<p>未近瀑布,先闻雷鸣。穿过天星桥的石林,水雾便扑面而来,带着草木的清香与湿润的凉意。忽见白水河从断崖处纵身跃下,如银河倾泻,在阳光中架起七彩长虹,虹影随水雾流动,似能伸手触摸。</p>
<p>沿栈道绕行至瀑布背后的水帘洞,水珠如暴雨般从洞顶坠落,在身前织成晶莹的帘幕。透过水幕看瀑布外的世界,青山绿树都蒙着一层水晕,恍如仙境。洞壁的岩石被水流冲刷得圆润光滑,却依然能感到水流撞击的震颤,轰鸣之声灌满耳洞,说话需附耳相告。</p>
<p>正午时分,阳光直射瀑布,水雾中浮现出多重彩虹,赤橙黄绿青蓝紫,层次分明得如同调色盘。犀牛潭的水面翻滚着白色浪花,潭边的古榕树枝繁叶茂,树根深深扎进岩石缝隙,汲取着带着矿物质的泉水,枝丫间的白鹭被水雾惊扰,振翅掠过水面,翅尖带起的水珠在阳光下如碎钻般闪烁。</p>
<p>暮色中的瀑布更显磅礴,水流在昏暗天光下呈青灰色,如巨幅绸缎垂落。潭边的观景台渐空,唯有水流的轰鸣依旧。坐看暮色渐浓,彩虹隐去,水雾在暮色中泛着微光,忽然明白为何徐霞客会在此驻足三日——这不息的水流里,藏着天地初开时的声音。</p>
</div>
)rawliteral";
// 文章11:抚仙湖记
const char htmlFuxianLake[] PROGMEM = R"rawliteral(
<h1 class="article-title">抚仙湖记</h1>
<div class="article-meta">癸卯盛夏 | 于孤山岛望清波</div>
<div class="article-content">
<p>晨光中的抚仙湖如一块巨大的蓝宝石,湖水清得能看见水下十米处的鹅卵石。岸边的芦苇带着露水,风过时沙沙作响,惊起的蜻蜓贴着水面低飞,翅尖划起细碎的波纹。渔民的木船静泊在岸边,船板被湖水浸泡得发黑,船头的鱼鹰缩着脖子打盹,偶尔抖落一身水珠。</p>
<p>乘渔舟往湖心岛去,船桨搅起的浪花泛着绿意,如打碎了满湖的翡翠。湖水在船舷边流淌,透明得几乎看不见,唯有手伸入水中,才感到那份沁骨的清凉与流动。远处的笔架山倒映水中,山影随波晃动,如写意的水墨画。</p>
<p>登孤山岛时,正午的阳光把湖面晒得滚烫。岛上的古柏已有百年树龄,浓荫如盖,树下的石凳带着凉意。凭栏远眺,湖岸线如优美的弧线,将湖水拥入怀中。浅滩处的湖水呈碧绿色,深处则渐变为墨绿,渔船驶过留下的水痕,许久才慢慢平复,如时光擦过水面。</p>
<p>暮色中的抚仙湖浸在紫金色的霞光里。归航的渔船带着满舱银白的抗浪鱼,渔民的歌声随风飘来,调子简单而悠长。岸边的炊烟与湖面的水雾交融,远处的村落亮起灯火,星星点点地散落在湖岸,与天上的星子遥相呼应。掬一捧湖水,凉得像夏夜的月光,带着一丝不易察觉的甜。</p>
</div>
)rawliteral";
// 文章12:丽江古城记
const char htmlLijiangOldTown[] PROGMEM = R"rawliteral(
<h1 class="article-title">丽江古城记</h1>
<div class="article-meta">甲辰暮春 | 于四方街听流水</div>
<div class="article-content">
<p>晨雾中的丽江古城,青石板路还带着露水。玉泉河的流水穿城而过,水声潺潺如琴弦轻拨,水藻在清澈的水中随波摇曳,几尾红鱼倏忽游过,惊起细碎的水花。纳西族的木楼依山而建,飞檐翘角如鸟翼,屋檐下的红灯笼在雾中若隐若现,像未醒的梦。</p>
<p>日头升高,四方街渐渐热闹起来。纳西族的老婆婆坐在石阶上绣花,扎染的桌布在阳光下泛着靛蓝,绣针穿过布面的声音,与远处的东巴鼓声相和。巷子里飘来粑粑的香气,混着青梅酒的清冽,让人忍不住驻足。流水穿过街心的水榭,有人蹲在水边洗菜,衣袖被水打湿,却笑得自在。</p>
<p>登狮子山俯瞰古城,灰瓦的屋顶如波浪起伏,玉泉河的支流如银链穿梭其间,岸边的柳树新绿如烟。远处的玉龙雪山在阳光下闪烁,山顶的积雪终年不化,与古城的烟火气相映成趣。山腰的万古楼飞檐斗拱,挂着的铜铃在风中轻响,声传数里。</p>
<p>暮色中的酒吧街亮起灯笼,红灯笼的影子映在水中,随波晃动如流动的火焰。纳西古乐在夜色中响起,三弦的调子苍凉悠远,与流水声交织成网,将整个古城笼罩。坐在水边的石阶上,看灯笼的光晕在水面扩散,忽然懂得,这座古城的灵魂,原是在这穿城而过的流水里。</p>
</div>
)rawliteral";
// 中南地区
// 文章13:张家界山记
const char htmlZhangjiajie[] PROGMEM = R"rawliteral(
<h1 class="article-title">张家界山记</h1>
<div class="article-meta">甲辰暮春 | 于天子阁观峰林</div>
<div class="article-content">
<p>雨雾中的张家界,三千奇峰如破土而出的石笋,在乳白色的雾霭中时隐时现。金鞭溪的流水绕着峰脚蜿蜒,水声清脆如环佩相击,溪底的卵石上长满青苔,绿得能挤出汁水。偶尔有猕猴从枝头跃过,带起的雨珠落在溪面,激起一圈圈涟漪。</p>
<p>乘百龙天梯直上袁家界,梯外的峰林如剑如戟,垂直的岩壁上生长着黄山松,根系沿着岩缝深入,枝叶却倔强地向外舒展。登顶时云雾恰好散开,群峰在阳光下露出峥嵘,石英砂岩的峰体呈淡红色,垂直的崖壁如刀削斧劈,却在顶端生长着倔强的绿色。</p>
<p>行走在玻璃栈道上,脚下是百米深渊,栈道与山体相接处几乎看不见支撑,仿佛凭空悬在半空。云雾从谷底升起,漫过栈道,让人如在云端行走。对面的「乾坤柱」孤峰独立,柱顶的松树在风中摇曳,据说便是《阿凡达》中哈利路亚山的原型。</p>
<p>暮色中的天子山,峰林被染成金红色。云涛在峰林间流动,如大海涨潮,淹没低处的峰峦,只露出高处的峰顶,如海中仙岛。山风渐起,松涛阵阵,与远处的溪流声相和。下山时回望,最后一缕阳光从峰林间穿过,在云海上投下细长的光柱,宛如天地间的琴弦。</p>
</div>
)rawliteral";
// 文章14:漓江烟雨记
const char htmlLijiangRiver[] PROGMEM = R"rawliteral(
<h1 class="article-title">漓江烟雨记</h1>
<div class="article-meta">辛丑暮春 | 于竹筏观雨</div>
<div class="article-content">
<p>乘竹筏泛漓江时,细雨刚落。两岸的山峰裹在乳白色的雾里,只露青灰色的轮廓,像米家山水的淡墨笔触。竹篙点水的声响惊起鸬鹚,黑色的翅膀划破雨帘,带起的水珠落在水面,与雨丝撞成细碎的银花。</p>
<p>雨渐密时,江面腾起薄雾。象鼻山的倒影在水中漾开,鼻端与山体之间的圆洞积着云气,似皓月浮空。岸边的凤尾竹垂向水面,竹叶上的雨珠串串坠落,在江面上敲出一圈圈涟漪,与远处渔翁的蓑衣相映,成一幅水墨淋漓的小品。</p>
<p>午后雨歇,阳光从云隙漏下。九马画山的崖壁被雨水洗得发亮,青灰色的岩石上隐现赭红纹路,真如群马或立或奔。竹筏划过浅滩,水底的鹅卵石清晰可见,几尾青鱼倏忽游过,尾鳍搅起细沙,在阳光下如撒金粉。</p>
<p>暮色里过黄布滩,江面平如镜。两岸的山峰倒映水中,与实景连成完整的画框,渔火渐次亮起,在水中碎成点点红星。撑筏的老农用桂柳话哼起古谣,竹篙轻点,筏子载着满舱暮色,向烟雨深处漂去,身后的涟漪里,还浮着半轮未沉的夕阳。</p>
</div>
)rawliteral";
// 文章15:岳阳楼记
const char htmlYueyangTower[] PROGMEM = R"rawliteral(
<h1 class="article-title">岳阳楼记</h1>
<div class="article-meta">甲辰孟秋 | 于洞庭湖畔感怀</div>
<div class="article-content">
<p>秋晴日登岳阳楼,洞庭波平如镜。楼前的洞庭湖衔远山,吞长江,水天一色处,白帆点点如鸥鸟。木质的楼体散发着樟木的清香,朱漆的栏杆被游人的手掌磨得光滑,三楼的「岳阳楼」匾额在阳光下泛着光泽,笔力遒劲如铁画银钩。</p>
<p>范仲淹的《岳阳楼记》碑刻在二楼,字迹清晰可辨,"先天下之忧而忧"的句子被无数人抚摸,石刻已微微凹陷。凭栏远眺,君山如青螺浮在水中,岛上的湘妃竹影影绰绰,传说中娥皇女英的泪痕,化作竹上的斑点,在阳光下若隐若现。</p>
<p>午后风起,湖面渐起波澜。白浪拍打着岸边的岩石,溅起的水花带着湖草的气息,掠过脸颊沁凉。远处的渔船收起白帆,如雁阵般归航,渔民的号子在风中回荡,与楼角的铜铃相和。岸边的芦苇荡里,白鹭惊起,翅尖划水的声音,清晰可闻。</p>
<p>暮色中的洞庭湖,水色渐变为墨蓝。远处的城郭亮起灯火,在湖面投下晃动的光带,与天上的星子连成一片。守楼人开始清场,木楼梯上传来咚咚的脚步声,在空旷的楼里回荡。临行回望,岳阳楼的剪影在暮色中更显古朴,仿佛千年前的忧乐情怀,仍萦绕在飞檐斗拱间。</p>
</div>
)rawliteral";
// 华东地区
// 文章16:杭州西湖记
const char htmlWestLake[] PROGMEM = R"rawliteral(
<h1 class="article-title">杭州西湖记</h1>
<div class="article-meta">己亥孟夏 | 于苏堤远眺</div>
<div class="article-content">
<p>西湖之美,在水,在山,在四时之景不同。晨雾未散时,湖面如蒙薄纱,三潭印月的石塔只露半角,似水墨画卷中未干的笔触。苏堤的柳丝垂入水中,蘸着清波写些无人能懂的诗行,偶有画舫推开涟漪,惊起几只白鹭,翅尖划水的声音,比寺中的晨钟更轻。</p>
<p>日头渐高,雾散处见断桥横卧。并非真断,而是冬雪初霁时,阳面雪融而阴面残雪未消,远远望去如桥身中断,故得此名。此时节却无雪,桥畔桃花开得正好,花瓣落进湖面,随绿水绕堤而行,与雷峰塔的倒影相撞,碎成满湖的胭脂。</p>
<p>行至曲院风荷,暑气顿消。大片荷叶亭亭如盖,粉白的荷花躲在叶后,偶尔探出头来,引得蜻蜓栖在花苞上。风过处,叶浪翻滚,送来荷香阵阵,混着远处龙井茶园飘来的茶香,酿成一杯名为「江南」的酒,醉了岸边的游人,也醉了水中的游鱼。</p>
<p>暮色临湖时,最好是坐在平湖秋月的栏杆上。夕阳把保俶塔的影子拉得很长,斜斜地铺在湖面,像谁遗落了一条金带。岸边的灯次第亮起,倒映水中成串,与天上的星子分不清谁是真的。偶有笛声从画舫传来,曲不成调,却恰好应和了湖水拍岸的节奏——这是西湖的呼吸,不急不徐,已持续了千年。</p>
</div>
)rawliteral";
// 文章17:黄山云海记
const char htmlHuangshan[] PROGMEM = R"rawliteral(
<h1 class="article-title">黄山云海记</h1>
<div class="article-meta">庚子仲秋 | 于光明顶观云</div>
<div class="article-content">
<p>天未亮便拄杖登山,石阶覆着薄霜,踩上去咯吱作响。行至半山,忽有白雾从谷底涌来,初如轻纱漫卷,转瞬已成惊涛拍岸。脚下的石阶渐渐隐去,仿佛踏在云絮之上,身边的松树只露墨绿的梢头,如海中孤岛。</p>
<p>待至光明顶,东方已泛鱼肚白。云海在晨光中渐染金色,漫过天都峰的腰际,绕着莲花峰的尖顶,将群峰雕琢成浮于海面的玉簪。偶有山风穿谷而过,云涛骤起波澜,远处的始信峰忽隐忽现,似巨鲸摆尾,搅碎满海金光。</p>
<p>正午时分,云开处见奇松百态。迎客松伸着苍劲的长臂,松针上的露珠折射阳光,如缀满碎钻;黑虎松枝干盘曲,墨绿的针叶聚成一团,真如猛虎伏于岩上。岩缝中渗出的清泉滴落石潭,叮咚声与松涛相和,似有古琴在云端轻弹。</p>
<p>日暮时分,云海渐成绛紫色。霞光为飞来石镀上金边,石下的云絮翻涌如火焰,却又带着沁骨的凉意。山风渐紧,松枝乱舞,云海开始退潮,露出深褐色的峡谷,残留的云缕挂在崖壁,如仙人遗落的纱巾。下山时回望,峰顶的灯塔已亮起,在暮色中如孤星闪烁。</p>
</div>
)rawliteral";
// 文章18:武功山记
const char htmlWugongshan[] PROGMEM = R"rawliteral(
<h1 class="article-title">武功山记</h1>
<div class="article-meta">癸卯孟秋 | 于金顶望草甸</div>
<div class="article-content">
<p>初秋的武功山,万亩草甸已染上金边。从沈子村出发,山路穿行在密林中,腐叶的气息混着松脂的清香,石阶上长满青苔,雨后湿滑如抹油。行至半山腰,眼前忽然开阔——漫山遍野的茅草在风中起伏,如金色的海洋,远处的山峰如岛屿般浮在草海之上。</p>
<p>正午时分抵达发云界,草甸在阳光下泛着金属光泽。山风掠过草尖,发出海浪般的声响,几头黄牛低头啃草,铃铛声随着风飘得很远。躺在柔软的草甸上,看天上的白云以肉眼可见的速度流动,云影在草坡上追逐,忽明忽暗,如大地的呼吸。</p>
<p>向金顶进发的路上,草甸与怪石相映成趣。巨大的花岗岩卧在草坡上,表面被风雨打磨得光滑,却依然保持着棱角分明的姿态。草甸从石缝中生长出来,黄绿相间,如大地编织的毛毯。远处的云海漫过天际线,与草甸的金色相接,分不清哪里是天,哪里是地。</p>
<p>夜宿金顶帐篷,繁星如钻石般铺满夜空。草甸上的风带着凉意,远处的山影在月光下呈黛青色。凌晨的日出将草甸染成赤金色,云海在脚下翻滚,阳光穿过云层形成光柱,照在远处的山峦上,如神佛显圣。这一刻忽然懂得,为何徐霞客会三访武功山——这草甸与云海之间,藏着天地最本真的色彩。</p>
</div>
)rawliteral";
// 文章19:苏州园林记
const char htmlSuzhouGardens[] PROGMEM = R"rawliteral(
<h1 class="article-title">苏州园林记</h1>
<div class="article-meta">甲辰暮春 | 于拙政园品茗</div>
<div class="article-content">
<p>暮春的拙政园,细雨打湿了青石板路。跨进「别有洞天」月洞门,眼前豁然开朗——池中荷叶刚露尖角,几尾红鲤在新绿间游弋,岸边的垂柳蘸着池水,如少女梳理青丝。亭台楼阁沿池而建,粉墙黛瓦在细雨中更显清丽,窗棂的雕花将天光剪碎,投在青石板上如流动的画。</p>
<p>卅六鸳鸯馆内,古筝声断断续续。临水的窗敞开着,雨丝斜斜地飘入,打湿了窗台上的文竹。透过雕花窗棂看对面的香洲,如一艘泊在岸边的画舫,舱内的美人靠空着,仿佛刚有人在此凭栏远眺。廊下的雨滴顺着瓦当坠落,在青石板上敲出清脆的声响,与琴声相和。</p>
<p>留园的冠云峰最为奇特。太湖石瘦、透、漏、皱,石孔在雨中冒着白汽,如仙人吐纳。石旁的古柏虬曲苍劲,枝干斜向石顶,仿佛要与奇石共语。池中的倒影将石与树连成一体,虚实相生,分不清哪是实景,哪是幻影。雨停时,水珠从石孔滴落,在池面激起一圈圈涟漪,将倒影揉碎又重圆。</p>
<p>暮色中的网师园,灯笼次第亮起。月洞门内的竹影映在粉墙上,随风摇曳如墨竹图。听松风处传来评弹声,琵琶的弦音与吴侬软语交织,如流水般漫过亭台楼阁。坐在殿春簃的窗前,看池中灯火的倒影,忽然明白,这园林的妙处,正在于将天地山水,都收进这一方小院里。</p>
</div>
)rawliteral";
// 华南地区
// 文章20:三亚椰林记
const char htmlSanyaCoconutGrove[] PROGMEM = R"rawliteral(
<h1 class="article-title">三亚椰林记</h1>
<div class="article-meta">壬寅孟冬 | 于亚龙湾听浪</div>
<div class="article-content">
<p>初冬的三亚,阳光仍带着暖意。亚龙湾的椰林如绿色的屏障,椰叶在海风中沙沙作响,成熟的椰子挂在枝头,青皮泛着油光,偶尔有熟透的果子坠落,砸在沙滩上发出闷响。沙滩的细沙如碎玉,赤足踩上去温热柔软,海浪退去时,沙粒从趾缝间溜走,带着微凉的海水。</p>
<p>正午的阳光烈得晃眼,躲在椰树荫下,看远处的海水由浅绿渐变为深蓝,如巨大的绸缎铺向天际。白帆在远处的海面上移动,如白鸟掠过水面,冲浪者的身影在浪尖起伏,与海浪嬉戏。卖椰子的小贩剖开椰壳,清甜的椰汁带着凉意,喝一口沁人心脾,椰肉雪白如凝脂,嚼起来带着奶香。</p>
<p>傍晚的鹿回头,夕阳为椰林镀上金边。礁石上的仙人掌开着黄花,与远处的渔火相映。海风带着咸湿的气息,吹动黎族姑娘的筒裙,银饰的叮当声与海浪拍岸的声响相和。凭栏远眺,三亚湾的渔排如水上村落,灯火点点,与天上的星子连成一片。</p>
<p>夜色中的蜈支洲岛,椰影婆娑。沙滩上的篝火旁,黎族小伙子敲着木鼓,姑娘们跳起竹竿舞,节奏明快如海浪。躺在吊床上看星空,银河清晰可见,偶尔有流星划过,坠入远处的海面,惊起几只夜鸟。海浪的声音如催眠曲,让人忘了今夕何夕。</p>
</div>
)rawliteral";
// 文章21:桂林山水记
const char htmlGuilinLandscape[] PROGMEM = R"rawliteral(
<h1 class="article-title">桂林山水记</h1>
<div class="article-meta">甲辰仲春 | 于象鼻山前赏春</div>
<div class="article-content">
<p>仲春的桂林,烟雨濛濛。象鼻山的倒影在漓江水中漾开,鼻与身之间的水月洞如一轮满月,洞中积着薄雾,游船穿过时,如入仙境。岸边的桃花开得正好,粉白的花瓣落在绿水上,随波逐流,与水中的青荇相缠,分不清是花是草。</p>
<p>芦笛岩的钟乳石在灯光下如水晶琉璃。「水晶宫」的石柱顶天立地,石笋如雨后春笋,灯光变换间,忽而是龙宫宝殿,忽而是瑶池仙境。水滴从岩顶坠落,在地上的水潭中激起涟漪,回声在溶洞中回荡,如天籁梵音。岩壁上的古题刻已模糊,却依然能辨认出千年前游人的赞叹。</p>
<p>阳朔西街的傍晚,灯笼初上。青石板路被雨水打湿,倒映着店铺的幌子,酒吧里传来吉他声,与远处的渔歌相和。街边的米粉店飘出酸笋的香气,让人垂涎。租一辆自行车沿遇龙河而行,两岸的凤尾竹如绿色的帘幕,竹影在水中摇曳,偶有竹筏从河上漂过,撑筏人的斗笠在夕阳中呈金色。</p>
<p>兴坪古镇的晨雾最是动人。江面的雾如白纱,渔船的剪影在雾中若隐若现,渔翁站在船头,抛出的渔网在空中划出优美的弧线,落入水中时溅起的水花在晨光中如碎银。远处的九马画山在雾中只露轮廓,如泼墨山水画,让人想起徐悲鸿的骏马图。</p>
</div>
)rawliteral";
// 主页面框架(包含导航按钮和文章容器)
const char htmlIndex[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>中华山水记</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'SimSun', 'STSong', serif;
}
html, body {
height: 100vh;
overflow: hidden;
background-color: #f5f5f5;
}
.container {
display: flex;
width: 100%;
height: 100%;
}
.nav-panel {
width: 180px;
background-color: #2c3e50;
padding: 20px 10px;
overflow-y: auto;
}
.region-title {
color: #1abc9c;
font-size: 0.9rem;
margin: 15px 0 5px 5px;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: bold;
}
.nav-btn {
width: 100%;
padding: 10px 10px;
margin-bottom: 4px;
background-color: #34495e;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 0.9rem;
text-align: left;
transition: all 0.3s;
}
.nav-btn:hover, .nav-btn.active {
background-color: #1abc9c;
transform: translateX(5px);
}
.content-panel {
flex: 1;
padding: 3rem 5%;
overflow-y: auto;
}
.article-title {
font-size: 2.5rem;
margin-bottom: 1.5rem;
color: #2c3e50;
text-align: center;
font-weight: bold;
}
.article-meta {
color: #666;
font-size: 1rem;
text-align: center;
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 1px solid #ddd;
}
.article-content {
font-size: 1.2rem;
line-height: 2;
text-align: justify;
color: #333;
}
.article-content p {
margin-bottom: 1.5rem;
}
.footer {
margin-top: 3rem;
padding-top: 1rem;
border-top: 1px solid #ddd;
text-align: center;
color: #666;
font-size: 0.9rem;
}
</style>
<script>
// 全屏显示
window.onload = function() {
const docEl = document.documentElement;
if (docEl.requestFullscreen) docEl.requestFullscreen();
else if (docEl.mozRequestFullScreen) docEl.mozRequestFullScreen();
else if (docEl.webkitRequestFullscreen) docEl.webkitRequestFullscreen();
else if (docEl.msRequestFullscreen) docEl.msRequestFullscreen();
// 加载默认文章
loadArticle('greatwall');
}
// 切换文章并更新按钮状态
function loadArticle(article) {
// 移除所有按钮的active类
const buttons = document.getElementsByClassName('nav-btn');
for (let i = 0; i < buttons.length; i++) {
buttons[i].classList.remove('active');
}
// 为当前点击的按钮添加active类
const activeButton = document.querySelector(`[onclick="loadArticle('${article}')"]`);
if (activeButton) activeButton.classList.add('active');
// 加载文章内容
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
document.getElementById('article-container').innerHTML = xhr.responseText;
}
};
xhr.open('GET', '/' + article, true);
xhr.send();
}
</script>
</head>
<body>
<div class="container">
<!-- 左侧导航按钮(按地区分组) -->
<div class="nav-panel">
<div class="region-title">华北地区</div>
<button class="nav-btn" onclick="loadArticle('greatwall')">万里长城</button>
<button class="nav-btn" onclick="loadArticle('forbiddencity')">故宫</button>
<button class="nav-btn" onclick="loadArticle('beidaihe')">北戴河</button>
<div class="region-title">东北地区</div>
<button class="nav-btn" onclick="loadArticle('changbaishan')">长白山</button>
<button class="nav-btn" onclick="loadArticle('harbiniceworld')">哈尔滨冰雪大世界</button>
<div class="region-title">西北地区</div>
<button class="nav-btn" onclick="loadArticle('huashan')">华山</button>
<button class="nav-btn" onclick="loadArticle('terracottaarmy')">兵马俑</button>
<button class="nav-btn" onclick="loadArticle('mogaogrottoes')">敦煌莫高窟</button>
<div class="region-title">西南地区</div>
<button class="nav-btn" onclick="loadArticle('potala')">布达拉宫</button>
<button class="nav-btn" onclick="loadArticle('huangguoshu')">黄果树瀑布</button>
<button class="nav-btn" onclick="loadArticle('fuxianlake')">抚仙湖</button>
<button class="nav-btn" onclick="loadArticle('lijiangoldtown')">丽江古城</button>
<div class="region-title">中南地区</div>
<button class="nav-btn" onclick="loadArticle('zhangjiajie')">张家界</button>
<button class="nav-btn" onclick="loadArticle('lijiang')">漓江烟雨</button>
<button class="nav-btn" onclick="loadArticle('yueyangtower')">岳阳楼</button>
<div class="region-title">华东地区</div>
<button class="nav-btn" onclick="loadArticle('westlake')">杭州西湖</button>
<button class="nav-btn" onclick="loadArticle('huangshan')">黄山云海</button>
<button class="nav-btn" onclick="loadArticle('wugongshan')">武功山</button>
<button class="nav-btn" onclick="loadArticle('suzhougardens')">苏州园林</button>
<div class="region-title">华南地区</div>
<button class="nav-btn" onclick="loadArticle('sanyacoconutgrove')">三亚椰林</button>
<button class="nav-btn" onclick="loadArticle('guilinlandscape')">桂林山水</button>
</div>
<!-- 右侧文章容器 -->
<div class="content-panel">
<div id="article-container"></div>
<div class="footer">
由 ESP8266 Web服务器 提供支持 | 锦绣中华,山水有情 作者:
</div>
</div>
</div>
</body>
</html>
)rawliteral";
void setup() {
Serial.begin(115200);
Serial.println("\n开始连接WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi连接成功!");
Serial.print("访问地址: http://");
Serial.println(WiFi.localIP());
// 路由配置
server.on("/", []() {
server.send_P(200, "text/html", htmlIndex);
});
server.on("/greatwall", []() {
server.send_P(200, "text/html", htmlGreatWall);
});
server.on("/forbiddencity", []() {
server.send_P(200, "text/html", htmlForbiddenCity);
});
server.on("/beidaihe", []() {
server.send_P(200, "text/html", htmlBeidaihe);
});
server.on("/changbaishan", []() {
server.send_P(200, "text/html", htmlChangbaishan);
});
server.on("/harbiniceworld", []() {
server.send_P(200, "text/html", htmlHarbinIceWorld);
});
server.on("/huashan", []() {
server.send_P(200, "text/html", htmlHuashan);
});
server.on("/terracottaarmy", []() {
server.send_P(200, "text/html", htmlTerracottaArmy);
});
server.on("/mogaogrottoes", []() {
server.send_P(200, "text/html", htmlMogaoGrottoes);
});
server.on("/potala", []() {
server.send_P(200, "text/html", htmlPotala);
});
server.on("/huangguoshu", []() {
server.send_P(200, "text/html", htmlHuangguoshu);
});
server.on("/fuxianlake", []() {
server.send_P(200, "text/html", htmlFuxianLake);
});
server.on("/lijiangoldtown", []() {
server.send_P(200, "text/html", htmlLijiangOldTown);
});
server.on("/zhangjiajie", []() {
server.send_P(200, "text/html", htmlZhangjiajie);
});
server.on("/lijiang", []() {
server.send_P(200, "text/html", htmlLijiangRiver);
});
server.on("/yueyangtower", []() {
server.send_P(200, "text/html", htmlYueyangTower);
});
server.on("/westlake", []() {
server.send_P(200, "text/html", htmlWestLake);
});
server.on("/huangshan", []() {
server.send_P(200, "text/html", htmlHuangshan);
});
server.on("/wugongshan", []() {
server.send_P(200, "text/html", htmlWugongshan);
});
server.on("/suzhougardens", []() {
server.send_P(200, "text/html", htmlSuzhouGardens);
});
server.on("/sanyacoconutgrove", []() {
server.send_P(200, "text/html", htmlSanyaCoconutGrove);
});
server.on("/guilinlandscape", []() {
server.send_P(200, "text/html", htmlGuilinLandscape);
});
server.begin();
Serial.println("Web服务器已启动,支持多地区文章切换");
}
void loop() {
server.handleClient();//
}
上面就是完整代码,复制到Arudino,上传程序,大功告成!再打开浏览器,输入串口中发送的IP地址,回车,就可以浏览自己的网站了。