first commit

This commit is contained in:
龙澳
2026-03-30 16:47:10 +08:00
parent 90efa60c0e
commit faeeea44d9
66 changed files with 167141 additions and 0 deletions

2989
content/卷一一.txt Normal file

File diff suppressed because it is too large Load Diff

2718
content/卷一七.txt Normal file

File diff suppressed because it is too large Load Diff

2955
content/卷一三.txt Normal file

File diff suppressed because it is too large Load Diff

2919
content/卷一九.txt Normal file

File diff suppressed because it is too large Load Diff

2857
content/卷一二.txt Normal file

File diff suppressed because it is too large Load Diff

2804
content/卷一五.txt Normal file

File diff suppressed because it is too large Load Diff

2602
content/卷一八.txt Normal file

File diff suppressed because it is too large Load Diff

2822
content/卷一六.txt Normal file

File diff suppressed because it is too large Load Diff

2822
content/卷一四.txt Normal file

File diff suppressed because it is too large Load Diff

2982
content/卷一零.txt Normal file

File diff suppressed because it is too large Load Diff

2491
content/卷三一.txt Normal file

File diff suppressed because it is too large Load Diff

2585
content/卷三七.txt Normal file

File diff suppressed because it is too large Load Diff

2741
content/卷三三.txt Normal file

File diff suppressed because it is too large Load Diff

2719
content/卷三九.txt Normal file

File diff suppressed because it is too large Load Diff

2657
content/卷三二.txt Normal file

File diff suppressed because it is too large Load Diff

2741
content/卷三五.txt Normal file

File diff suppressed because it is too large Load Diff

2453
content/卷三八.txt Normal file

File diff suppressed because it is too large Load Diff

2805
content/卷三六.txt Normal file

File diff suppressed because it is too large Load Diff

2831
content/卷三四.txt Normal file

File diff suppressed because it is too large Load Diff

2447
content/卷三零.txt Normal file

File diff suppressed because it is too large Load Diff

2449
content/卷二一.txt Normal file

File diff suppressed because it is too large Load Diff

2445
content/卷二七.txt Normal file

File diff suppressed because it is too large Load Diff

2473
content/卷二三.txt Normal file

File diff suppressed because it is too large Load Diff

2435
content/卷二九.txt Normal file

File diff suppressed because it is too large Load Diff

2515
content/卷二二.txt Normal file

File diff suppressed because it is too large Load Diff

2370
content/卷二五.txt Normal file

File diff suppressed because it is too large Load Diff

2487
content/卷二八.txt Normal file

File diff suppressed because it is too large Load Diff

2663
content/卷二六.txt Normal file

File diff suppressed because it is too large Load Diff

2295
content/卷二四.txt Normal file

File diff suppressed because it is too large Load Diff

2684
content/卷二零.txt Normal file

File diff suppressed because it is too large Load Diff

2353
content/卷五一.txt Normal file

File diff suppressed because it is too large Load Diff

2519
content/卷五七.txt Normal file

File diff suppressed because it is too large Load Diff

2641
content/卷五三.txt Normal file

File diff suppressed because it is too large Load Diff

2595
content/卷五九.txt Normal file

File diff suppressed because it is too large Load Diff

2319
content/卷五二.txt Normal file

File diff suppressed because it is too large Load Diff

2355
content/卷五五.txt Normal file

File diff suppressed because it is too large Load Diff

2587
content/卷五八.txt Normal file

File diff suppressed because it is too large Load Diff

2485
content/卷五六.txt Normal file

File diff suppressed because it is too large Load Diff

2439
content/卷五四.txt Normal file

File diff suppressed because it is too large Load Diff

2475
content/卷五零.txt Normal file

File diff suppressed because it is too large Load Diff

2397
content/卷六一.txt Normal file

File diff suppressed because it is too large Load Diff

2827
content/卷六三.txt Normal file

File diff suppressed because it is too large Load Diff

2361
content/卷六二.txt Normal file

File diff suppressed because it is too large Load Diff

2449
content/卷六零.txt Normal file

File diff suppressed because it is too large Load Diff

2805
content/卷四一.txt Normal file

File diff suppressed because it is too large Load Diff

2397
content/卷四七.txt Normal file

File diff suppressed because it is too large Load Diff

2619
content/卷四三.txt Normal file

File diff suppressed because it is too large Load Diff

2499
content/卷四九.txt Normal file

File diff suppressed because it is too large Load Diff

2533
content/卷四二.txt Normal file

File diff suppressed because it is too large Load Diff

2409
content/卷四五.txt Normal file

File diff suppressed because it is too large Load Diff

2493
content/卷四八.txt Normal file

File diff suppressed because it is too large Load Diff

2427
content/卷四六.txt Normal file

File diff suppressed because it is too large Load Diff

2635
content/卷四四.txt Normal file

File diff suppressed because it is too large Load Diff

2625
content/卷四零.txt Normal file

File diff suppressed because it is too large Load Diff

2803
content/卷零一.txt Normal file

File diff suppressed because it is too large Load Diff

2891
content/卷零七.txt Normal file

File diff suppressed because it is too large Load Diff

2994
content/卷零三.txt Normal file

File diff suppressed because it is too large Load Diff

2844
content/卷零九.txt Normal file

File diff suppressed because it is too large Load Diff

3116
content/卷零二.txt Normal file

File diff suppressed because it is too large Load Diff

2984
content/卷零五.txt Normal file

File diff suppressed because it is too large Load Diff

2958
content/卷零八.txt Normal file

File diff suppressed because it is too large Load Diff

2846
content/卷零六.txt Normal file

File diff suppressed because it is too large Load Diff

2982
content/卷零四.txt Normal file

File diff suppressed because it is too large Load Diff

43
content/卷零零.txt Normal file
View File

@@ -0,0 +1,43 @@
大唐双龙传
黄易 著
威锋出版社
尊重知识,尊重版权,请勿用於商业用途!
* * *
原文本为田戈制作。样式来源:很多人
内容简介
《大唐双龙传》共63卷是黄易先生最长的一部作品。讲述了隋末群雄割据年代寇仲及徐子陵两个小混混凭着初生之犊的勇气在乱世的洪流中力争上游。
该书把历史背景、用兵之道、悱恻爱情和武侠世界完美地结合起来,规模宏大,气势磅礴,情节跌宕起伏、景物描写引人入胜,为读者展开了隋末战火连绵、民不聊生、群雄纷争,有识之士出于对苍生的同情,为太平盛世而奋斗的感人画卷。加之作者语言词锋、情节设计已臻大家之境,且对白设计亲切引人而不失幽默,使人读之欲罢不能,有亲临其境之感,也不得不佩服作者出色的的笔韵和想象力。这部百万字的巨著囊括了军事、历史、天文、医术、科学、宗教、宇宙奥秘、艺术美学等中国几千年文化智慧的精髓,但更重要的——是对生命哲学的省思。这亦是中国古典文化知识与武侠的完美融合。
更值得一提的是,书中的众人物性格鲜明,众主人公魅力不凡。主人公寇仲在逆境中不畏挫折、绝处逢生、永不言弃、建立不世功业的奇迹;以及他玩世不恭、谈笑用兵、藐视王侯、睥睨天下、面对千军万马怡然不惧、泰山崩于前而色不变的气度加之诡变莫测的兵法和谋略、幽默的谈吐,都让读者为之心折。他是天生爱挑战的人,在他的智慧和勇气面前,无数不可能成为可能,谈笑间无数危机迎刃而解。这样的寇仲,加之他身边亦步亦趋的徐子陵的精灵通透、淡泊俊秀;跋锋寒的冷峻坚韧;侯希白的儒雅风流……使读者不知不觉中被他们吸引,和他们一起共历命运,欲罢不能。另外,书中主人公间不离不弃,超越世间一切感情的兄弟间战友间的大爱以及纯洁无瑕的亲情、爱情更是感人至深,荡气回肠。
但是有一点不得不说的是,在人物成功的基础上我们也必须认识到剧情的急促转折使人感觉太不合理、十分生硬,容易引起读者的误会,而且许多人物性格单一、大众化、没有特色也是小说的硬伤之一。同时,如此宏大的场面,却有着这样一个结局,不得不说,作者对于整个格调的驾驭还是有着一定的问题。但是这些都不能掩饰这部作品的成功和杰出。

237
data/vol01.json Normal file
View File

@@ -0,0 +1,237 @@
{
"volume": "卷一",
"chapters": ["第01章 相依为命", "第02章 大祸临头", "第03章 远离扬州", "第04章 纠缠不清", "第05章 晴天霹雳", "第06章 九玄大法", "第07章 和氏之璧", "第08章 痛不欲生", "第09章 再上征途", "第10章 奋不顾身", "第11章 追兵忽至"],
"locations": [
{ "id": "yangzhou", "name": "扬州", "aliases": ["江都"], "type": "city", "lat": 32.39, "lng": 119.43, "description": "隋朝南都,长江与运河交汇的重镇,寇仲徐子陵的出生地" },
{ "id": "grand_canal", "name": "大运河", "aliases": ["运河","通济渠"], "type": "waterway", "lat": 33.5, "lng": 118.0, "description": "贯通南北的水路交通线" },
{ "id": "yangtze", "name": "长江", "aliases": ["大江"], "type": "waterway", "lat": 32.2, "lng": 119.0, "description": "中国第一大河" },
{ "id": "danyang", "name": "丹阳", "type": "city", "lat": 32.0, "lng": 118.95, "description": "扬州上游最大城市,水城风光,运河要道" },
{ "id": "beipo", "name": "北坡县", "type": "town", "lat": 32.5, "lng": 119.3, "description": "扬州附近大县城,寇徐二人冒充宇文公子处" },
{ "id": "liyang", "name": "历阳", "type": "city", "lat": 31.7, "lng": 118.37, "description": "长江沿岸重镇,被杜伏威攻占" },
{ "id": "luoyang", "name": "洛阳", "aliases": ["东都"], "type": "city", "lat": 34.62, "lng": 112.45, "description": "隋朝东都,和氏璧传说出现之地" },
{ "id": "daxing", "name": "大兴", "aliases": ["长安","京师"], "type": "city", "lat": 34.26, "lng": 108.94, "description": "隋朝西京,帝国首都" },
{ "id": "xingyang", "name": "荥阳", "type": "city", "lat": 34.79, "lng": 113.38, "description": "瓦岗军翟让的根据地" },
{ "id": "cuishan", "name": "翠山镇", "type": "town", "lat": 29.5, "lng": 116.8, "description": "鄱阳湖东,新安郡南,寇徐隐居打工三月处" },
{ "id": "gaoyou", "name": "高邮", "type": "city", "lat": 32.78, "lng": 119.44, "description": "运河沿线城市,李靖约定的会合点" },
{ "id": "chengdu", "name": "成都", "aliases": ["西川"], "type": "city", "lat": 30.57, "lng": 104.07, "description": "独尊堡解晖的基地" },
{ "id": "gaoji", "name": "高鸡泊", "type": "town", "lat": 37.5, "lng": 115.7, "description": "窦建德的起义根据地" },
{ "id": "wagang", "name": "瓦岗寨", "type": "town", "lat": 35.25, "lng": 114.7, "description": "翟让起义之地" },
{ "id": "valley", "name": "无名山谷", "type": "landmark", "lat": 31.3, "lng": 118.0, "description": "傅君婥战死安葬之地,寇徐练功修炼之处" },
{ "id": "poyang", "name": "鄱阳湖", "type": "waterway", "lat": 29.1, "lng": 116.3, "description": "中国第一大淡水湖" }
],
"factions": [
{
"id": "sui",
"name": "隋朝",
"type": "朝廷",
"color": "#FFD700",
"leader": "杨广(隋炀帝)",
"territory": ["daxing", "luoyang", "yangzhou", "danyang", "gaoyou"],
"key_figures": ["杨广", "陈守备", "尉迟胜"],
"description": "当朝政权,控制三大重镇(大兴、洛阳、江都),但内忧外患,气数将尽"
},
{
"id": "yuwen",
"name": "宇文阀",
"type": "门阀",
"color": "#4169E1",
"leader": "宇文伤",
"territory": ["daxing"],
"key_figures": ["宇文伤", "宇文化及", "张士和"],
"description": "四姓门阀之一,胡人出身,暗中图谋复辟北周,宇文化及为禁卫总管"
},
{
"id": "li_clan",
"name": "李阀",
"type": "门阀",
"color": "#DC143C",
"leader": "李渊",
"territory": [],
"key_figures": ["李渊"],
"description": "四姓门阀之一,李渊为杨广姨表兄弟,广施恩德但受猜忌"
},
{
"id": "song_clan",
"name": "宋阀",
"type": "门阀",
"color": "#228B22",
"leader": "宋缺",
"territory": ["chengdu"],
"key_figures": ["宋缺", "宋智", "宋师道", "宋鲁", "宋玉华"],
"description": "四姓门阀之一,南方汉族正统,'天刀'宋缺为阀主,私盐贸易暴利"
},
{
"id": "dugu",
"name": "独孤阀",
"type": "门阀",
"color": "#9932CC",
"leader": "未提及",
"territory": [],
"key_figures": [],
"description": "四姓门阀之一,与隋朝有深厚姻亲关系"
},
{
"id": "wagang_army",
"name": "瓦岗军",
"type": "义军",
"color": "#FF6347",
"leader": "翟让",
"territory": ["xingyang", "wagang"],
"key_figures": ["翟让", "李密", "徐世绩", "翟娇"],
"description": "天下义军之首,翟让为大龙头,李密声势尤在其上,隐患重重"
},
{
"id": "du_fuwei",
"name": "杜伏威军",
"type": "义军",
"color": "#FF8C00",
"leader": "杜伏威",
"territory": ["liyang"],
"key_figures": ["杜伏威", "李子通"],
"description": "江淮义军,新近攻占历阳,截断长江交通"
},
{
"id": "dou_jiande",
"name": "窦建德军",
"type": "义军",
"color": "#8B4513",
"leader": "窦建德",
"territory": ["gaoji"],
"key_figures": ["窦建德"],
"description": "河北黑道霸主,十万之众据高鸡泊,势力贯黄河"
},
{
"id": "wang_bo",
"name": "王薄军",
"type": "义军",
"color": "#DAA520",
"leader": "王薄",
"territory": [],
"key_figures": ["王薄"],
"description": "长白派第一高手'鞭王',自称'知世郎',受山东民众支持"
},
{
"id": "wang_xuba",
"name": "漫天王军",
"type": "义军",
"color": "#696969",
"leader": "王须拔",
"territory": [],
"key_figures": ["王须拔", "焦邪"],
"description": "声势颇大的叛变民军,大将焦邪被傅君婥所杀"
},
{
"id": "goguryeo",
"name": "高丽",
"type": "外族",
"color": "#00CED1",
"leader": "高丽王",
"territory": [],
"key_figures": ["傅采林", "傅君婥"],
"description": "东北邻国,弈剑大师傅采林为武学三大宗师之一,派傅君婥南来刺杀杨广"
},
{
"id": "turks",
"name": "突厥",
"type": "外族",
"color": "#2F4F4F",
"leader": "未提及",
"territory": [],
"key_figures": ["毕玄"],
"description": "北方最大外患,'武尊'毕玄为武学三大宗师之一"
},
{
"id": "duzun",
"name": "独尊堡",
"type": "江湖势力",
"color": "#B8860B",
"leader": "解晖",
"territory": ["chengdu"],
"key_figures": ["解晖", "解文龙"],
"description": "西川大豪,与宋阀联姻结盟"
}
],
"character_routes": [
{
"character": "寇仲 & 徐子陵",
"color": "#FF4500",
"route": [
{ "location": "yangzhou", "chapter": 1, "event": "扬州城东废园中相依为命" },
{ "location": "yangzhou", "chapter": 2, "event": "偷得《长生诀》,被追捕" },
{ "lat": 32.3, "lng": 119.2, "chapter": 3, "event": "经暗渠出城,在溪边遇白衣女傅君婥" },
{ "lat": 32.25, "lng": 119.1, "chapter": 3, "event": "跳入长江逃命,被傅君婥救起" },
{ "location": "beipo", "chapter": 4, "event": "被傅君婥带到北坡县" },
{ "location": "beipo", "chapter": 5, "event": "冒充宇文家公子骗吃骗住,被傅君婥再次救走" },
{ "location": "danyang", "chapter": 5, "event": "到达丹阳城,遇宋师道" },
{ "lat": 31.8, "lng": 118.5, "chapter": 6, "event": "乘宋家盐船逆流西上,傅君婥传授九玄大法" },
{ "lat": 31.5, "lng": 118.2, "chapter": 8, "event": "傅君婥带二人逃离宋船,与宇文化及决战" },
{ "location": "valley", "chapter": 8, "event": "傅君婥战死于山谷,二人安葬义母" },
{ "location": "valley", "chapter": 9, "event": "山谷隐居练功,气机发动" },
{ "location": "cuishan", "chapter": 9, "event": "南下到翠山镇打工三月" },
{ "lat": 31.5, "lng": 117.8, "chapter": 10, "event": "北上途中遇杜伏威军强征,救下素素" },
{ "lat": 31.9, "lng": 118.5, "chapter": 11, "event": "与李靖同行,在丹阳近郊遭遇流氓追兵" }
]
},
{
"character": "宇文化及",
"color": "#4169E1",
"route": [
{ "lat": 33.5, "lng": 118.0, "chapter": 1, "event": "率五牙大舰沿运河南下" },
{ "location": "yangzhou", "chapter": 1, "event": "到石龙住处夺《长生诀》,击杀石龙" },
{ "location": "yangzhou", "chapter": 2, "event": "发动全城搜捕寇仲徐子陵" },
{ "lat": 32.0, "lng": 119.0, "chapter": 3, "event": "沿长江追击傅君婥与二人" },
{ "lat": 31.5, "lng": 118.2, "chapter": 8, "event": "追至山上与傅君婥决战,受重伤" }
]
},
{
"character": "傅君婥",
"color": "#FFFFFF",
"route": [
{ "lat": 32.5, "lng": 119.35, "chapter": 1, "event": "在扬州北郊杀焦邪一行" },
{ "lat": 32.3, "lng": 119.2, "chapter": 3, "event": "在溪边遇寇仲徐子陵" },
{ "lat": 32.25, "lng": 119.1, "chapter": 3, "event": "长江上救起二人" },
{ "location": "beipo", "chapter": 4, "event": "将二人送到北坡县" },
{ "location": "beipo", "chapter": 5, "event": "从县官手中救走二人" },
{ "location": "danyang", "chapter": 5, "event": "带二人到丹阳" },
{ "lat": 31.8, "lng": 118.5, "chapter": 7, "event": "在宋家船上传授九玄大法" },
{ "location": "valley", "chapter": 8, "event": "与宇文化及拼死一战,玉殒香消" }
]
},
{
"character": "宋师道",
"color": "#228B22",
"route": [
{ "location": "danyang", "chapter": 5, "event": "在丹阳酒楼初遇三人" },
{ "lat": 31.8, "lng": 118.5, "chapter": 6, "event": "率四艘盐船逆流西上,运盐往巴蜀" },
{ "location": "chengdu", "chapter": 7, "event": "目的地巴蜀独尊堡(计划)" }
]
},
{
"character": "李靖",
"color": "#00BFFF",
"route": [
{ "location": "liyang", "chapter": 10, "event": "随杜伏威军驻历阳" },
{ "lat": 31.5, "lng": 117.8, "chapter": 10, "event": "射杀作恶军头,救下众人" },
{ "lat": 31.9, "lng": 118.5, "chapter": 11, "event": "在丹阳近郊被杜伏威执法团重伤" }
]
}
],
"key_events": [
{ "chapter": 1, "location": "yangzhou", "event": "宇文化及击杀石龙,夺《长生诀》未果" },
{ "chapter": 2, "location": "yangzhou", "event": "寇仲徐子陵偷得《长生诀》" },
{ "chapter": 1, "location": "yangzhou", "event": "傅君婥杀焦邪(漫天王部将)" },
{ "chapter": 3, "location": "yangzhou", "event": "寇徐跳入长江逃命" },
{ "chapter": 3, "event": "宇文化及与傅君婥长江上首次交手", "lat": 32.0, "lng": 119.0 },
{ "chapter": 5, "location": "danyang", "event": "遇宋师道,得知和氏璧与杨公宝库传说" },
{ "chapter": 6, "event": "傅君婥传授九玄大法", "lat": 31.8, "lng": 118.5 },
{ "chapter": 7, "event": "宋鲁讲述和氏璧与慈航静斋", "lat": 31.8, "lng": 118.5 },
{ "chapter": 8, "location": "valley", "event": "傅君婥与宇文化及决战身亡" },
{ "chapter": 9, "location": "valley", "event": "寇徐依《长生诀》图像练功突破" },
{ "chapter": 10, "location": "liyang", "event": "杜伏威攻占历阳,截断长江交通" },
{ "chapter": 10, "event": "寇徐救素素,遇李靖", "lat": 31.5, "lng": 117.8 }
]
}

443
index.html Normal file
View File

@@ -0,0 +1,443 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>大唐双龙传 - 势力分布地图(卷一)</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Microsoft YaHei', 'SimSun', sans-serif; background: #1a1a2e; color: #e0e0e0; }
#map { width: 100%; height: 100vh; }
/* Title overlay */
.map-title {
position: absolute; top: 10px; left: 50%; transform: translateX(-50%);
z-index: 1000; background: rgba(20,20,40,0.9); padding: 8px 24px;
border-radius: 8px; border: 1px solid #c9a96e;
font-size: 20px; font-weight: bold; color: #c9a96e;
letter-spacing: 4px; text-shadow: 0 0 10px rgba(201,169,110,0.5);
pointer-events: none;
}
/* Legend panel */
.legend {
position: absolute; bottom: 20px; left: 10px; z-index: 1000;
background: rgba(20,20,40,0.92); padding: 12px 16px;
border-radius: 8px; border: 1px solid #555; max-width: 260px;
font-size: 13px; line-height: 1.6;
}
.legend h3 { color: #c9a96e; margin-bottom: 8px; font-size: 14px; border-bottom: 1px solid #444; padding-bottom: 4px; }
.legend-item { display: flex; align-items: center; margin: 3px 0; cursor: pointer; }
.legend-item:hover { opacity: 0.7; }
.legend-dot { width: 12px; height: 12px; border-radius: 50%; margin-right: 8px; flex-shrink: 0; border: 1px solid rgba(255,255,255,0.3); }
.legend-line { width: 20px; height: 3px; margin-right: 8px; flex-shrink: 0; border-radius: 2px; }
.legend-section { margin-top: 8px; }
/* Chapter slider */
.chapter-panel {
position: absolute; bottom: 20px; right: 10px; z-index: 1000;
background: rgba(20,20,40,0.92); padding: 12px 16px;
border-radius: 8px; border: 1px solid #555; width: 320px;
}
.chapter-panel h3 { color: #c9a96e; margin-bottom: 8px; font-size: 14px; border-bottom: 1px solid #444; padding-bottom: 4px; }
.chapter-slider { width: 100%; margin: 8px 0; accent-color: #c9a96e; }
.chapter-label { font-size: 12px; color: #aaa; text-align: center; }
.chapter-name { font-size: 13px; color: #e0e0e0; text-align: center; margin-top: 4px; }
/* Info panel */
.info-panel {
position: absolute; top: 60px; right: 10px; z-index: 1000;
background: rgba(20,20,40,0.92); padding: 12px 16px;
border-radius: 8px; border: 1px solid #555; width: 320px;
max-height: 50vh; overflow-y: auto; display: none;
}
.info-panel h3 { color: #c9a96e; margin-bottom: 6px; font-size: 15px; }
.info-panel .close-btn {
position: absolute; top: 8px; right: 12px; cursor: pointer;
color: #aaa; font-size: 16px;
}
.info-panel .close-btn:hover { color: #fff; }
.info-panel p { font-size: 13px; line-height: 1.6; margin: 4px 0; }
.info-panel .tag { display: inline-block; padding: 1px 6px; border-radius: 3px; font-size: 11px; margin-right: 4px; }
/* Custom popup */
.leaflet-popup-content-wrapper {
background: rgba(30,30,50,0.95) !important;
color: #e0e0e0 !important;
border: 1px solid #c9a96e !important;
border-radius: 6px !important;
}
.leaflet-popup-tip { background: rgba(30,30,50,0.95) !important; }
.leaflet-popup-content { font-size: 13px !important; line-height: 1.5 !important; }
.leaflet-popup-content b { color: #c9a96e; }
/* Route animation */
@keyframes dash { to { stroke-dashoffset: 0; } }
</style>
</head>
<body>
<div id="map"></div>
<div class="map-title">大唐双龙传 - 卷一势力分布图</div>
<div class="legend" id="legend">
<h3>势力图例</h3>
<div id="faction-legend"></div>
<div class="legend-section">
<h3>人物路线</h3>
<div id="route-legend"></div>
</div>
</div>
<div class="chapter-panel">
<h3>章节进度</h3>
<input type="range" class="chapter-slider" id="chapterSlider" min="1" max="11" value="11" step="1">
<div class="chapter-label"><span id="chapterNum">11</span> / 11 章</div>
<div class="chapter-name" id="chapterName">第11章 追兵忽至</div>
</div>
<div class="info-panel" id="infoPanel">
<span class="close-btn" onclick="document.getElementById('infoPanel').style.display='none'">&times;</span>
<div id="infoPanelContent"></div>
</div>
<script>
// ==================== DATA ====================
const chapters = [
"第01章 相依为命", "第02章 大祸临头", "第03章 远离扬州",
"第04章 纠缠不清", "第05章 晴天霹雳", "第06章 九玄大法",
"第07章 和氏之璧", "第08章 痛不欲生", "第09章 再上征途",
"第10章 奋不顾身", "第11章 追兵忽至"
];
const locations = [
{ id:"yangzhou", name:"扬州(江都)", type:"city", lat:32.39, lng:119.43, desc:"隋朝南都,运河与长江交汇的重镇。寇仲徐子陵出生地,宇文化及夺《长生诀》之地。", chapter:1 },
{ id:"danyang", name:"丹阳", type:"city", lat:32.0, lng:118.95, desc:"扬州上游最大城市,河道纵横的水城。三人遇宋师道之处。", chapter:5 },
{ id:"beipo", name:"北坡县", type:"town", lat:32.5, lng:119.3, desc:"扬州附近大县,寇徐冒充宇文家公子骗吃骗住。", chapter:4 },
{ id:"liyang", name:"历阳", type:"city", lat:31.7, lng:118.37, desc:"长江沿岸重镇,杜伏威大破隋军后占领,截断长江水路。", chapter:10 },
{ id:"luoyang", name:"洛阳(东都)", type:"city", lat:34.62, lng:112.45, desc:"隋朝东都,和氏璧传闻出现之地,寇徐目标目的地。", chapter:7 },
{ id:"daxing", name:"大兴(长安)", type:"city", lat:34.26, lng:108.94, desc:"隋朝西京,帝国首都。杨公宝库藏于京都跃马桥。", chapter:1 },
{ id:"xingyang", name:"荥阳", type:"city", lat:34.79, lng:113.38, desc:"瓦岗军翟让根据地。李密在此大败隋军、击杀张须陀。", chapter:10 },
{ id:"cuishan", name:"翠山镇", type:"town", lat:29.5, lng:116.8, desc:"鄱阳湖东,新安郡南的大镇。寇徐在老张饭馆打工三月。", chapter:9 },
{ id:"gaoyou", name:"高邮", type:"city", lat:32.78, lng:119.44, desc:"运河沿线城市,李靖约定的北上会合点。", chapter:11 },
{ id:"chengdu", name:"成都", type:"city", lat:30.57, lng:104.07, desc:"独尊堡解晖的基地,宋阀私盐运往此处。", chapter:7 },
{ id:"gaoji", name:"高鸡泊", type:"town", lat:37.5, lng:115.7, desc:"窦建德据此为基地,势力贯黄河,拥兵十万。", chapter:10 },
{ id:"valley", name:"傅君婥墓(山谷)", type:"landmark", lat:31.3, lng:118.0, desc:"傅君婥战死安葬之地。寇徐在此隐居练功,突破气机。", chapter:8 }
];
const factions = [
{ id:"sui", name:"隋朝", color:"#FFD700", leader:"杨广(隋炀帝)", territories:["yangzhou","luoyang","daxing","danyang","gaoyou"], desc:"控制三大重镇,但内忧外患,叛乱四起" },
{ id:"yuwen", name:"宇文阀", color:"#4169E1", leader:"宇文伤 / 宇文化及", territories:["daxing"], desc:"四大门阀之首,暗图复辟北周。宇文化及为禁卫总管" },
{ id:"song_clan", name:"宋阀", color:"#228B22", leader:"天刀·宋缺", territories:["chengdu"], desc:"南方汉族正统,私盐贸易暴利,势力暗增" },
{ id:"wagang", name:"瓦岗军", color:"#FF6347", leader:"翟让 / 李密", territories:["xingyang"], desc:"天下义军之首。李密声势凌驾翟让,暗藏内讧之患" },
{ id:"du_fuwei", name:"杜伏威军", color:"#FF8C00", leader:"杜伏威", territories:["liyang"], desc:"江淮义军,新占历阳,截断长江交通" },
{ id:"dou_jiande", name:"窦建德军", color:"#8B4513", leader:"窦建德", territories:["gaoji"], desc:"河北霸主,十万之众,势力直贯黄河" },
{ id:"li_clan", name:"李阀", color:"#DC143C", leader:"李渊", territories:[], desc:"四姓门阀之一,受杨广猜忌,尚未起事" },
{ id:"goguryeo", name:"高丽", color:"#00CED1", leader:"傅采林", territories:[], desc:"东北邻国,派傅君婥刺杀杨广" },
{ id:"turks", name:"突厥", color:"#2F4F4F", leader:"武尊·毕玄", territories:[], desc:"北方最大外患" }
];
const routes = [
{
name: "寇仲 & 徐子陵", color: "#FF4500", dashArray: null,
points: [
{ lat:32.39, lng:119.43, ch:1, label:"扬州:相依为命" },
{ lat:32.3, lng:119.2, ch:3, label:"经暗渠出城" },
{ lat:32.25, lng:119.1, ch:3, label:"跳入长江" },
{ lat:32.5, lng:119.3, ch:4, label:"北坡县冒充公子" },
{ lat:32.0, lng:118.95, ch:5, label:"丹阳遇宋师道" },
{ lat:31.8, lng:118.5, ch:6, label:"宋船上学九玄大法" },
{ lat:31.5, lng:118.2, ch:8, label:"逃离宋船" },
{ lat:31.3, lng:118.0, ch:8, label:"山谷:傅君婥战死" },
{ lat:29.5, lng:116.8, ch:9, label:"翠山镇打工三月" },
{ lat:31.5, lng:117.8, ch:10, label:"救素素、遇李靖" },
{ lat:31.9, lng:118.5, ch:11, label:"丹阳近郊遇追兵" }
]
},
{
name: "宇文化及", color: "#4169E1", dashArray: "8 4",
points: [
{ lat:33.5, lng:118.0, ch:1, label:"率五牙大舰南下" },
{ lat:32.39, lng:119.43, ch:1, label:"扬州击杀石龙" },
{ lat:32.0, lng:119.0, ch:3, label:"长江追击" },
{ lat:31.5, lng:118.2, ch:8, label:"山上决战受重伤" }
]
},
{
name: "傅君婥", color: "#E0E0E0", dashArray: "4 4",
points: [
{ lat:32.5, lng:119.35, ch:1, label:"扬州北郊杀焦邪" },
{ lat:32.25, lng:119.1, ch:3, label:"长江上救起二人" },
{ lat:32.5, lng:119.3, ch:4, label:"北坡县救人" },
{ lat:32.0, lng:118.95, ch:5, label:"丹阳" },
{ lat:31.8, lng:118.5, ch:7, label:"船上传功" },
{ lat:31.3, lng:118.0, ch:8, label:"山谷:战死" }
]
},
{
name: "李靖", color: "#00BFFF", dashArray: "6 3",
points: [
{ lat:31.7, lng:118.37, ch:10, label:"随杜伏威军驻历阳" },
{ lat:31.5, lng:117.8, ch:10, label:"射杀祈老大救人" },
{ lat:31.9, lng:118.5, ch:11, label:"丹阳近郊被重伤" }
]
}
];
// ==================== MAP INIT ====================
const map = L.map('map', {
center: [32.0, 116.0],
zoom: 6,
zoomControl: true,
attributionControl: false
});
// Dark tile layer
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
maxZoom: 18,
subdomains: 'abcd'
}).addTo(map);
// Attribution
L.control.attribution({ prefix: false, position: 'bottomright' })
.addAttribution('大唐双龙传 - 黄易')
.addTo(map);
// ==================== LAYERS ====================
const layerGroups = {};
let currentChapter = 11;
// Faction territory circles
const territoryLayers = [];
factions.forEach(f => {
f.territories.forEach(tid => {
const loc = locations.find(l => l.id === tid);
if (!loc) return;
const circle = L.circle([loc.lat, loc.lng], {
radius: 50000,
color: f.color,
fillColor: f.color,
fillOpacity: 0.12,
weight: 2,
opacity: 0.5,
dashArray: '6 4'
}).addTo(map);
circle._factionId = f.id;
circle._chapterMin = loc.chapter;
territoryLayers.push(circle);
// Faction label
const label = L.marker([loc.lat + 0.35, loc.lng], {
icon: L.divIcon({
className: '',
html: `<div style="color:${f.color};font-size:11px;font-weight:bold;text-shadow:0 0 4px rgba(0,0,0,0.8);white-space:nowrap;text-align:center">${f.name}</div>`,
iconAnchor: [30, 8]
})
}).addTo(map);
label._chapterMin = loc.chapter;
territoryLayers.push(label);
});
});
// Location markers
const locationMarkers = [];
const cityIcon = (color) => L.divIcon({
className: '',
html: `<div style="width:10px;height:10px;background:${color};border:2px solid #fff;border-radius:50%;box-shadow:0 0 6px ${color}"></div>`,
iconSize: [10, 10],
iconAnchor: [5, 5]
});
const townIcon = (color) => L.divIcon({
className: '',
html: `<div style="width:8px;height:8px;background:${color};border:1.5px solid #ccc;border-radius:50%;box-shadow:0 0 4px ${color}"></div>`,
iconSize: [8, 8],
iconAnchor: [4, 4]
});
const landmarkIcon = L.divIcon({
className: '',
html: `<div style="width:8px;height:8px;background:#FF69B4;border:1.5px solid #fff;transform:rotate(45deg);box-shadow:0 0 4px #FF69B4"></div>`,
iconSize: [8, 8],
iconAnchor: [4, 4]
});
locations.forEach(loc => {
// Determine controlling faction color
let markerColor = '#aaa';
for (const f of factions) {
if (f.territories.includes(loc.id)) { markerColor = f.color; break; }
}
const icon = loc.type === 'city' ? cityIcon(markerColor) :
loc.type === 'landmark' ? landmarkIcon : townIcon(markerColor);
const marker = L.marker([loc.lat, loc.lng], { icon })
.bindPopup(`<b>${loc.name}</b><br>${loc.desc}`)
.addTo(map);
marker._chapterMin = loc.chapter;
locationMarkers.push(marker);
// City name label
const nameLabel = L.marker([loc.lat - 0.15, loc.lng], {
icon: L.divIcon({
className: '',
html: `<div style="color:#ccc;font-size:11px;text-shadow:0 0 3px #000,0 0 6px #000;white-space:nowrap;text-align:center">${loc.name}</div>`,
iconAnchor: [30, 0]
})
}).addTo(map);
nameLabel._chapterMin = loc.chapter;
locationMarkers.push(nameLabel);
});
// Character routes
const routeLayers = [];
routes.forEach(r => {
// Create polyline segments per chapter
for (let i = 0; i < r.points.length - 1; i++) {
const p1 = r.points[i], p2 = r.points[i+1];
const maxCh = p2.ch;
const line = L.polyline([[p1.lat, p1.lng], [p2.lat, p2.lng]], {
color: r.color,
weight: 3,
opacity: 0.8,
dashArray: r.dashArray || undefined
}).addTo(map);
line._chapterMax = maxCh;
line._routeName = r.name;
routeLayers.push(line);
}
// Route point markers
r.points.forEach((p, idx) => {
const isEnd = idx === r.points.length - 1;
const isStart = idx === 0;
const size = (isStart || isEnd) ? 7 : 5;
const dot = L.circleMarker([p.lat, p.lng], {
radius: size,
color: r.color,
fillColor: isEnd ? '#fff' : r.color,
fillOpacity: 0.9,
weight: 2
}).bindPopup(`<b>${r.name}</b><br>第${p.ch}章:${p.label}`)
.addTo(map);
dot._chapterMax = p.ch;
dot._routeName = r.name;
routeLayers.push(dot);
});
});
// Waterways (simplified)
const grandCanal = L.polyline([
[39.9, 116.4], [37.5, 116.8], [35.0, 117.0], [34.62, 114.0],
[33.5, 118.0], [32.78, 119.44], [32.39, 119.43]
], { color: '#2a6496', weight: 1.5, opacity: 0.4, dashArray: '4 4' }).addTo(map);
const yangtze = L.polyline([
[30.57, 104.07], [29.5, 106.5], [30.5, 111.3], [30.6, 114.3],
[29.5, 116.0], [31.3, 118.0], [31.7, 118.37], [32.0, 118.95], [32.2, 119.2], [32.39, 119.43]
], { color: '#2a6496', weight: 2, opacity: 0.4 }).addTo(map);
// ==================== LEGEND ====================
const factionLegend = document.getElementById('faction-legend');
factions.forEach(f => {
if (f.territories.length === 0 && f.id !== 'li_clan') return;
const div = document.createElement('div');
div.className = 'legend-item';
div.innerHTML = `<div class="legend-dot" style="background:${f.color}"></div><span>${f.name}${f.leader}</span>`;
div.onclick = () => showFactionInfo(f);
factionLegend.appendChild(div);
});
const routeLegend = document.getElementById('route-legend');
routes.forEach(r => {
const div = document.createElement('div');
div.className = 'legend-item';
div.innerHTML = `<div class="legend-line" style="background:${r.color}"></div><span>${r.name}</span>`;
routeLegend.appendChild(div);
});
function showFactionInfo(f) {
const panel = document.getElementById('infoPanel');
const content = document.getElementById('infoPanelContent');
content.innerHTML = `
<h3 style="color:${f.color}">${f.name}</h3>
<p><b>首领:</b>${f.leader}</p>
<p>${f.desc}</p>
${f.territories.length ? `<p><b>据点:</b>${f.territories.map(t => {
const loc = locations.find(l => l.id === t);
return loc ? loc.name : t;
}).join('、')}</p>` : ''}
`;
panel.style.display = 'block';
}
// ==================== CHAPTER SLIDER ====================
const slider = document.getElementById('chapterSlider');
const chapterNumEl = document.getElementById('chapterNum');
const chapterNameEl = document.getElementById('chapterName');
slider.addEventListener('input', (e) => {
currentChapter = parseInt(e.target.value);
chapterNumEl.textContent = currentChapter;
chapterNameEl.textContent = chapters[currentChapter - 1];
updateVisibility();
});
function updateVisibility() {
// Territory layers
territoryLayers.forEach(layer => {
const show = !layer._chapterMin || layer._chapterMin <= currentChapter;
if (show) {
if (!map.hasLayer(layer)) map.addLayer(layer);
} else {
if (map.hasLayer(layer)) map.removeLayer(layer);
}
});
// Location markers
locationMarkers.forEach(marker => {
const show = !marker._chapterMin || marker._chapterMin <= currentChapter;
if (show) {
if (!map.hasLayer(marker)) map.addLayer(marker);
} else {
if (map.hasLayer(marker)) map.removeLayer(marker);
}
});
// Route layers
routeLayers.forEach(layer => {
const show = !layer._chapterMax || layer._chapterMax <= currentChapter;
if (show) {
if (!map.hasLayer(layer)) map.addLayer(layer);
} else {
if (map.hasLayer(layer)) map.removeLayer(layer);
}
});
}
// ==================== WATERWAY LABELS ====================
L.marker([33.0, 117.5], {
icon: L.divIcon({
className: '',
html: '<div style="color:#4a90b8;font-size:10px;opacity:0.6;transform:rotate(-30deg);white-space:nowrap">大运河</div>',
iconAnchor: [15, 5]
})
}).addTo(map);
L.marker([30.8, 113.0], {
icon: L.divIcon({
className: '',
html: '<div style="color:#4a90b8;font-size:10px;opacity:0.6;white-space:nowrap">长江</div>',
iconAnchor: [10, 5]
})
}).addTo(map);
// Initial state
updateVisibility();
</script>
</body>
</html>