杜甫的足迹人生
<!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://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
<style>
/* 全局样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Microsoft YaHei", "SimSun", sans-serif;
background-color: #f9f5e9;
color: #333;
line-height: 1.6;
}
/* 地图容器样式 */
#mapContainer {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
}
#map {
width: 100%;
height: 100%;
z-index: 1;
}
/* 信息卡片样式 */
#infoCard {
position: absolute;
top: 20px;
left: 20px;
width: 320px;
max-height: calc(100vh - 100px);
background-color: rgba(255, 255, 255, 0.95);
border-radius: 12px;
padding: 20px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
backdrop-filter: blur(10px);
z-index: 100;
transition: transform 0.3s ease, opacity 0.3s ease;
transform: translateX(-100%);
opacity: 0;
overflow-y: auto;
}
#infoCard.active {
transform: translateX(0);
opacity: 1;
}
#infoCard h2 {
font-size: 24px;
margin-bottom: 10px;
color: #8B4513;
border-bottom: 2px solid #DAA520;
padding-bottom: 8px;
}
#infoYear {
font-size: 14px;
color: #666;
margin-bottom: 15px;
font-style: italic;
}
#infoImage {
width: 100%;
height: 200px;
object-fit: cover;
border-radius: 8px;
margin: 15px 0;
transition: filter 0.3s ease;
}
#infoImage.image-loading {
filter: blur(10px);
}
#infoDescription {
font-size: 16px;
margin-bottom: 15px;
line-height: 1.8;
}
#infoPoem {
font-size: 18px;
color: #8B4513;
font-style: italic;
margin-bottom: 15px;
text-align: center;
}
#infoAnecdote {
font-size: 14px;
color: #555;
line-height: 1.8;
}
/* 控制按钮样式 */
#controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background-color: rgba(255, 255, 255, 0.9);
border-radius: 50px;
padding: 10px 20px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
z-index: 100;
display: flex;
align-items: center;
gap: 15px;
}
.control-btn {
background: none;
border: none;
font-size: 24px;
cursor: pointer;
padding: 8px 12px;
border-radius: 50%;
transition: background-color 0.3s ease;
}
.control-btn:hover {
background-color: rgba(139, 69, 19, 0.1);
}
#playBtn {
font-size: 20px;
}
/* 视频控制样式 */
#videoControl {
display: none;
align-items: center;
gap: 10px;
margin-top: 15px;
padding-top: 15px;
border-top: 1px solid #eee;
}
#videoBtn {
background-color: #8B4513;
color: white;
border: none;
padding: 8px 16px;
border-radius: 20px;
cursor: pointer;
font-size: 14px;
display: flex;
align-items: center;
gap: 5px;
transition: background-color 0.3s ease;
}
#videoBtn:hover {
background-color: #6d3815;
}
/* 视频模态框样式 */
#videoModal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s ease;
}
#videoModal.active {
opacity: 1;
visibility: visible;
}
#videoPlayerContainer {
position: relative;
max-width: 90%;
max-height: 90%;
}
#videoPlayer {
max-width: 100%;
max-height: 80vh;
}
#closeVideoBtn {
position: absolute;
top: -40px;
right: 0;
background-color: rgba(0, 0, 0, 0.5);
color: white;
border: none;
font-size: 24px;
width: 40px;
height: 40px;
border-radius: 50%;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
/* 阶段颜色指示器样式 */
#stageColors {
position: absolute;
top: 20px;
right: 20px;
background-color: rgba(255, 255, 255, 0.9);
border-radius: 12px;
padding: 15px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
z-index: 100;
max-height: calc(100vh - 100px);
overflow-y: auto;
}
.stage-color-item {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
font-size: 14px;
}
.stage-color {
width: 16px;
height: 16px;
border-radius: 50%;
border: 2px solid #fff;
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.1);
}
.stage-name {
white-space: nowrap;
}
/* 语言切换样式 */
#langSwitch {
position: absolute;
top: 20px;
right: 20px;
margin-top: 140px;
background-color: rgba(255, 255, 255, 0.9);
border-radius: 20px;
padding: 5px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
z-index: 100;
display: flex;
gap: 5px;
}
.lang-btn {
background: none;
border: none;
padding: 8px 16px;
border-radius: 15px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s ease;
}
.lang-btn.active {
background-color: #8B4513;
color: white;
}
/* 地图加载指示器 */
#mapLoader {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(255, 255, 255, 0.9);
padding: 20px 40px;
border-radius: 12px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
z-index: 200;
font-size: 16px;
color: #8B4513;
}
/* 响应式设计 */
@media (max-width: 768px) {
#infoCard {
width: calc(100vw - 40px);
max-height: 60vh;
top: auto;
bottom: 80px;
left: 20px;
}
#stageColors {
right: 10px;
top: 10px;
padding: 10px;
}
.stage-color-item {
font-size: 12px;
}
#langSwitch {
margin-top: 120px;
right: 10px;
}
}
/* 图片查看器样式 */
#imageViewer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.9);
display: flex;
justify-content: center;
align-items: center;
z-index: 2000;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s ease;
}
#imageViewer.active {
opacity: 1;
visibility: visible;
}
#fullImage {
max-width: 90%;
max-height: 90vh;
object-fit: contain;
}
#closeImageBtn {
position: absolute;
top: 20px;
right: 20px;
background-color: rgba(0, 0, 0, 0.5);
color: white;
border: none;
font-size: 24px;
width: 40px;
height: 40px;
border-radius: 50%;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
/* 动画效果 */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.fade-in {
animation: fadeIn 0.6s ease forwards;
}
/* 进度条样式 */
#progressBar {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 4px;
background-color: rgba(0, 0, 0, 0.1);
z-index: 1000;
}
#progressFill {
height: 100%;
background-color: #8B4513;
width: 0%;
transition: width 0.3s ease;
}
</style>
</head>
<body>
<div id="mapContainer">
<!-- 地图加载指示器 -->
<div id="mapLoader">加载中...</div>
<!-- 地图 -->
<div id="map"></div>
<!-- 信息卡片 -->
<div id="infoCard">
<h2 id="infoTitle">杜甫</h2>
<div id="infoYear">公元712年 | 童年时期</div>
<div id="infoDescription">唐代现实主义诗人,被誉为"诗史"</div>
<img id="infoImage" src="" alt="杜甫" />
<div id="infoPoem">「国破山河在,城春草木深」</div>
<div id="infoAnecdote"></div>
<div id="videoControl">
<button id="videoBtn"><span>▶</span> 播放视频</button>
</div>
</div>
<!-- 控制按钮 -->
<div id="controls">
<button id="prevBtn" class="control-btn">⏮</button>
<button id="playBtn" class="control-btn">▶</button>
<button id="nextBtn" class="control-btn">⏭</button>
</div>
<!-- 阶段颜色指示器 -->
<div id="stageColors"></div>
<!-- 语言切换 -->
<div id="langSwitch">
<button id="btnZh" class="lang-btn active">中文</button>
<button id="btnEn" class="lang-btn">English</button>
</div>
<!-- 视频模态框 -->
<div id="videoModal">
<div id="videoPlayerContainer">
<video id="videoPlayer" controls>
<source src="" type="video/mp4">
您的浏览器不支持视频播放
</video>
<button id="closeVideoBtn" onclick="closeVideo()">×</button>
</div>
</div>
<!-- 进度条 -->
<div id="progressBar">
<div id="progressFill"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<script src="https://cdn.jsdelivr.net/npm/leaflet-ant-path@1.3.0/dist/leaflet-ant-path.min.js"></script>
<script>
// 杜甫一生重要地点数据
const allPoints = [
{
name: "巩县",
nameEn: "Gongxian",
year: 712,
stage: 1,
coord: [34.7, 112.9],
event: "杜甫出生于巩县瑶湾村",
eventEn: "Du Fu was born in Yaowan Village, Gongxian",
poem: "忆年十五心尚孩,健如黄犊走复来",
poemEn: "Recalling when I was fifteen, my heart was still childlike, as strong as a yellow calf running back and forth",
image: "./images/gongxian.jpg",
fallbackImage: "https://picsum.photos/id/1018/800/600",
culture: {
lines: ["忆年十五心尚孩,健如黄犊走复来","庭前八月梨枣熟,一日上树能千回"],
linesEn: ["Recalling when I was fifteen, my heart was still childlike, as strong as a yellow calf running back and forth", "In front of the courtyard, pears and jujubes ripen in August; I can climb the tree a thousand times a day"],
anecdote: "杜甫出身于京兆杜氏,是晋代名将杜预的后代。其祖父杜审言是初唐著名诗人,父亲杜闲曾任兖州司马。杜甫幼年聪慧,七岁能诗,展现出非凡的文学天赋。",
anecdoteEn: "Du Fu came from the Du clan of Jingzhao, a descendant of the famous Jin Dynasty general Du Yu. His grandfather Du Shenyan was a renowned poet of the early Tang Dynasty, and his father Du Xian served as Sima of Yanzhou. Du Fu was intelligent from childhood, able to compose poems at the age of seven, showing extraordinary literary talent."
},
hasVideo: false
},
{
name: "洛阳",
nameEn: "Luoyang",
year: 735,
stage: 2,
coord: [34.6, 112.4],
event: "首次赴洛阳应进士考试,落第",
eventEn: "First trip to Luoyang to take the imperial examination, failed",
poem: "白也诗无敌,飘然思不群",
poemEn: "Li Bai's poetry is unparalleled, his thoughts float beyond the ordinary",
image: "./images/luoyang.jpg",
fallbackImage: "https://picsum.photos/id/1019/800/600",
culture: {
lines: ["白也诗无敌,飘然思不群","清新庾开府,俊逸鲍参军"],
linesEn: ["Li Bai's poetry is unparalleled, his thoughts float beyond the ordinary", "Fresh and elegant like Yu Xin, handsome and free like Bao Zhao"],
anecdote: "杜甫在洛阳结识了许多文坛好友,其中包括李白。两人一见如故,同游梁宋,共访隐士,结下深厚友谊。杜甫曾在《饮中八仙歌》中描绘李白'李白斗酒诗百篇'的豪放形象。",
anecdoteEn: "In Luoyang, Du Fu made many literary friends, including Li Bai. The two hit it off immediately, traveling together to Liang and Song, visiting hermits, and forming a deep friendship. Du Fu described Li Bai's bold image in 'Song of the Eight Immortals of the Wine Cup': 'Li Bai with a dou of wine composes a hundred poems.'"
},
hasVideo: false
},
{
name: "长安",
nameEn: "Chang'an",
year: 744,
stage: 3,
coord: [34.3, 108.9],
event: "赴长安求仕,困居十年",
eventEn: "Traveled to Chang'an to seek official position, lived in hardship for ten years",
poem: "纨绔不饿死,儒冠多误身",
poemEn: "The wealthy and idle don't starve to death, while scholar's hats often bring ruin",
image: "./images/changan.jpg",
fallbackImage: "https://picsum.photos/id/1020/800/600",
culture: {
lines: ["纨绔不饿死,儒冠多误身","丈人试静听,贱子请具陈"],
linesEn: ["The wealthy and idle don't starve to death, while scholar's hats often bring ruin", "Sir, please listen quietly, let your humble servant explain in detail"],
anecdote: "杜甫在长安期间,生活贫困,甚至'朝扣富儿门,暮随肥马尘'。尽管如此,他仍然坚持诗歌创作,写下了许多反映社会现实的作品,如《兵车行》《丽人行》等,奠定了'诗史'的地位。",
anecdoteEn: "During his stay in Chang'an, Du Fu lived in poverty, even 'knocking on rich men's doors in the morning and following the dust of fat horses in the evening.' Despite this, he persisted in poetic creation, writing many works that reflected social reality, such as 'Song of the Chariots of War' and 'Song of the Beautiful Ladies,' establishing his status as a 'poet-historian.'"
},
hasVideo: false
},
{
name: "奉先",
nameEn: "Fengxian",
year: 755,
stage: 4,
coord: [35.0, 109.3],
event: "归奉先省亲,幼子饿死",
eventEn: "Returned to Fengxian to visit family, youngest son starved to death",
poem: "朱门酒肉臭,路有冻死骨",
poemEn: "In vermilion gates, wine and meat rot; on the road, frozen corpses lie",
image: "./images/fengxian.jpg",
fallbackImage: "https://picsum.photos/id/1021/800/600",
culture: {
lines: ["朱门酒肉臭,路有冻死骨","荣枯咫尺异,惆怅难再述"],
linesEn: ["In vermilion gates, wine and meat rot; on the road, frozen corpses lie", "Prosperity and decline differ within a foot's reach; my sadness is hard to express again"],
anecdote: "杜甫从长安返回奉先途中,目睹了社会的贫富悬殊和民间疾苦。到家后,发现幼子因饥饿而死,悲痛欲绝。这段经历成为他创作《自京赴奉先县咏怀五百字》的重要背景。",
anecdoteEn: "On his way back from Chang'an to Fengxian, Du Fu witnessed the disparity between rich and poor and the sufferings of the people. When he arrived home, he found that his youngest son had starved to death, causing him extreme grief. This experience became an important background for his creation of 'A Hundred Thoughts on the Journey from the Capital to Fengxian County.'"
},
hasVideo: false
},
{
name: "灵武",
nameEn: "Lingwu",
year: 756,
stage: 4,
coord: [38.1, 106.3],
event: "听闻肃宗在灵武即位,前往投奔",
eventEn: "Heard that Emperor Suzong had ascended the throne in Lingwu, went to join him",
poem: "此生那老蜀,不死会归秦",
poemEn: "In this life, how can I grow old in Shu; if I don't die, I will return to Qin",
image: "./images/lingwu.jpg",
fallbackImage: "https://picsum.photos/id/1022/800/600",
culture: {
lines: ["此生那老蜀,不死会归秦","初谒临丹殿,恩华赐绣袍"],
linesEn: ["In this life, how can I grow old in Shu; if I don't die, I will return to Qin", "First audience at the Lidan Palace, granted embroidered robes as favor"],
anecdote: "安史之乱爆发后,杜甫带着家人逃难。当他听说唐肃宗在灵武即位,立即前往投奔,被任命为左拾遗。这是杜甫一生中担任的最高官职,但不久因上书救房琯而触怒肃宗,被贬为华州司功参军。",
anecdoteEn: "After the An Lushan Rebellion broke out, Du Fu fled with his family. When he heard that Emperor Suzong had ascended the throne in Lingwu, he immediately went to join him and was appointed as Left Remonstrator. This was the highest official position Du Fu held in his life, but soon he offended Emperor Suzong by submitting a letter to rescue Fang Guan, and was demoted to Sihu参军 of Huazhou."
},
hasVideo: false
},
{
name: "秦州",
nameEn: "Qinzhou",
year: 759,
stage: 5,
coord: [34.6, 105.7],
event: "辞官西行,流寓秦州",
eventEn: "Resigned and traveled west, sojourned in Qinzhou",
poem: "迟回度陇怯,浩荡及关愁",
poemEn: "Hesitant to cross Long, timid; vast and reaching the pass, sorrowful",
image: "./images/qinzhou.jpg",
fallbackImage: "https://picsum.photos/id/1023/800/600",
culture: {
lines: ["迟回度陇怯,浩荡及关愁","水落鱼龙夜,山空鸟鼠秋"],
linesEn: ["Hesitant to cross Long, timid; vast and reaching the pass, sorrowful", "Water recedes on a night of fish and dragon; mountains empty in autumn of birds and rats"],
anecdote: "杜甫在华州任职期间,目睹了战乱给百姓带来的深重灾难,写下了著名的'三吏'(《新安吏》《石壕吏》《潼关吏》)和'三别'(《新婚别》《垂老别》《无家别》)。因对时政失望,他辞官西行,流寓秦州。",
anecdoteEn: "During his tenure in Huazhou, Du Fu witnessed the深重 disasters brought to the people by the war, and wrote the famous 'Three Officials' (The New An Official, The Shihao Official, The Tongguan Official) and 'Three Partings' (The Newlywed Parting, The Elderly Parting, The Homeless Parting). Disappointed with current politics, he resigned and traveled west, sojourning in Qinzhou."
},
hasVideo: false
},
{
name: "同谷",
nameEn: "Tonggu",
year: 759,
stage: 5,
coord: [33.9, 105.3],
event: "移家同谷,生活困苦",
eventEn: "Moved family to Tonggu, lived in hardship",
poem: "岁拾橡栗随狙公,天寒日暮山谷里",
poemEn: "Yearly picking acorns following the monkey trainer; cold weather, sunset in the mountain valley",
image: "./images/tonggu.jpg",
fallbackImage: "https://picsum.photos/id/1024/800/600",
culture: {
lines: ["岁拾橡栗随狙公,天寒日暮山谷里","中原无书归不得,手脚冻皴皮肉死"],
linesEn: ["Yearly picking acorns following the monkey trainer; cold weather, sunset in the mountain valley", "No letters from the Central Plain, can't return; hands and feet frostbitten, skin and flesh dead"],
anecdote: "杜甫在同谷期间,生活极其艰苦,甚至需要捡拾橡栗充饥。他在《乾元中寓居同谷县作歌七首》中真实记录了这段艰难岁月。尽管如此,他仍然心系国家和人民,写下了许多感人至深的诗篇。",
anecdoteEn: "During his stay in Tonggu, Du Fu lived in extreme hardship, even having to pick acorns for food. He truly recorded this difficult period in 'Seven Songs Written While Residing in Tonggu County During the Qianyuan Era.' Despite this, he still cared about the country and the people, writing many deeply moving poems."
},
hasVideo: false
},
{
name: "成都",
nameEn: "Chengdu",
year: 760,
stage: 6,
coord: [30.6, 104.0],
event: "入蜀,在成都建草堂定居",
eventEn: "Entered Shu, built Thatched Cottage in Chengdu and settled there",
poem: "安得广厦千万间,大庇天下寒士俱欢颜",
poemEn: "How can I get ten thousand spacious mansions to shelter all the poor scholars under heaven with happy faces",
image: "./images/chengdu.jpg",
fallbackImage: "https://picsum.photos/id/1025/800/600",
culture: {
lines: ["安得广厦千万间,大庇天下寒士俱欢颜","风雨不动安如山。呜呼!何时眼前突兀见此屋"],
linesEn: ["How can I get ten thousand spacious mansions to shelter all the poor scholars under heaven with happy faces", "Safe and stable like mountains despite wind and rain. Alas! When will such houses suddenly appear before my eyes"],
anecdote: "在亲友的帮助下,杜甫在成都浣花溪畔建成了著名的'杜甫草堂'。在这里,他度过了相对安定的几年时光,创作了大量优秀诗篇,如《茅屋为秋风所破歌》《春夜喜雨》等。成都时期是杜甫诗歌创作的高峰期之一。",
anecdoteEn: "With the help of relatives and friends, Du Fu built the famous 'Du Fu Thatched Cottage' by Huanhuaxi in Chengdu. Here, he spent several relatively stable years, creating a large number of excellent poems, such as 'Song of the Thatched Cottage Broken by Autumn Wind' and 'Happy Rain on a Spring Night.' The Chengdu period was one of the peak periods of Du Fu's poetic creation."
},
hasVideo: true
},
{
name: "梓州",
nameEn: "Zizhou",
year: 762,
stage: 6,
coord: [31.4, 105.9],
event: "因战乱,暂避梓州",
eventEn: "Temporarily took refuge in Zizhou due to war",
poem: "万里悲秋常作客,百年多病独登台",
poemEn: "Ten thousand li of sorrow in autumn, always a traveler; a hundred years of many illnesses, alone ascending the terrace",
image: "./images/zizhou.jpg",
fallbackImage: "https://picsum.photos/id/1026/800/600",
culture: {
lines: ["万里悲秋常作客,百年多病独登台","艰难苦恨繁霜鬓,潦倒新停浊酒杯"],
linesEn: ["Ten thousand li of sorrow in autumn, always a traveler; a hundred years of many illnesses, alone ascending the terrace", "Hardships and bitter hatred have turned my hair frosty; down and out, newly stopping drinking turbid wine"],
anecdote: "剑南节度使严武去世后,成都发生动乱,杜甫不得不再次流离失所,暂居梓州。在梓州期间,他写下了《登高》这首被誉为'古今七律第一'的杰作。这首诗通过描绘秋江景色,抒发了诗人漂泊异乡、年老多病的感慨。",
anecdoteEn: "After the death of Yan Wu, military governor of Jiannan, unrest broke out in Chengdu, and Du Fu had to become homeless again, temporarily residing in Zizhou. During his stay in Zizhou, he wrote 'Ascending the Heights,' which is hailed as the 'number one seven-character regulated poem of all time.' Through describing autumn river scenery, this poem expresses the poet's feelings of wandering in a foreign land and being old and ill."
},
hasVideo: false
},
{
name: "夔州",
nameEn: "Kuizhou",
year: 765,
stage: 7,
coord: [31.0, 109.8],
event: "移居夔州,任柏茂琳幕府参谋",
eventEn: "Moved to Kuizhou, served as advisor to Bai Maolin's staff",
poem: "无边落木萧萧下,不尽长江滚滚来",
poemEn: "Boundless falling leaves rustle down; endless Yangtze River rolls on",
image: "./images/kuizhou.jpg",
fallbackImage: "https://picsum.photos/id/1027/800/600",
culture: {
lines: ["无边落木萧萧下,不尽长江滚滚来","万里悲秋常作客,百年多病独登台"],
linesEn: ["Boundless falling leaves rustle down; endless Yangtze River rolls on", "Ten thousand li of sorrow in autumn, always a traveler; a hundred years of many illnesses, alone ascending the terrace"],
anecdote: "杜甫在夔州期间,得到了柏茂琳的照顾,生活相对稳定。他在这里创作了大量诗篇,包括《秋兴八首》《咏怀古迹五首》等组诗。这些作品意境开阔,情感深沉,被认为是杜甫诗歌的巅峰之作。",
anecdoteEn: "During his stay in Kuizhou, Du Fu was taken care of by Bai Maolin and lived a relatively stable life. Here, he created a large number of poems, including the poem series 'Eight Songs of Autumn Thoughts' and 'Five Songs of Chanting Ancient Sites.' These works have broad artistic conception and deep emotions, and are considered the peak of Du Fu's poetry."
},
hasVideo: false
},
{
name: "江陵",
nameEn: "Jiangling",
year: 768,
stage: 8,
coord: [30.3, 112.2],
event: "出峡东下,漂泊江陵",
eventEn: "Left the gorges and went east, wandered in Jiangling",
poem: "细草微风岸,危樯独夜舟",
poemEn: "Fine grass on the微风 shore; dangerous mast, lonely night boat",
image: "./images/jiangling.jpg",
fallbackImage: "https://picsum.photos/id/1028/800/600",
culture: {
lines: ["细草微风岸,危樯独夜舟","星垂平野阔,月涌大江流"],
linesEn: ["Fine grass on the微风 shore; dangerous mast, lonely night boat", "Stars hang low over the vast plain; moon surges with the great river flow"],
anecdote: "杜甫思乡心切,决定出峡东下,返回中原。他先到达江陵,本想在此定居,但由于生活困难,不得不继续漂泊。在江陵期间,他写下了《旅夜书怀》等著名诗篇,表达了自己漂泊无依的感慨。",
anecdoteEn: "Longing for his homeland, Du Fu decided to leave the gorges and go east, returning to the Central Plain. He first arrived in Jiangling, intending to settle there, but due to financial difficulties, he had to continue wandering. During his stay in Jiangling, he wrote famous poems such as 'Writing Down Thoughts on a Night Journey,' expressing his feelings of being adrift with no one to rely on."
},
hasVideo: false
},
{
name: "公安",
nameEn: "Gong'an",
year: 768,
stage: 8,
coord: [30.0, 112.2],
event: "短暂停留公安",
eventEn: "Brief stay in Gong'an",
poem: "水流心不竞,云在意俱迟",
poemEn: "Water flows, but the heart does not compete; clouds linger, and thoughts are slow",
image: "./images/gongan.jpg",
fallbackImage: "https://picsum.photos/id/1029/800/600",
culture: {
lines: ["水流心不竞,云在意俱迟","寂寂春将晚,欣欣物自私"],
linesEn: ["Water flows, but the heart does not compete; clouds linger, and thoughts are slow", "Quietly spring is drawing to a close; joyfully all things are self-interested"],
anecdote: "杜甫在公安期间,生活依然贫困,但他的诗歌风格逐渐趋于平和。他开始更多地关注自然景物,通过描绘自然来寄托自己的情感。这种转变反映了诗人晚年心态的变化。",
anecdoteEn: "During his stay in Gong'an, Du Fu's life was still poor, but his poetic style gradually became more peaceful. He began to pay more attention to natural scenery, expressing his emotions through describing nature. This transformation reflects the changes in the poet's mentality in his later years."
},
hasVideo: false
},
{
name: "岳阳",
nameEn: "Yueyang",
year: 768,
stage: 8,
coord: [29.3, 113.1],
event: "登岳阳楼,写下千古名篇",
eventEn: "Climbed Yueyang Tower, wrote timeless masterpiece",
poem: "吴楚东南坼,乾坤日夜浮",
poemEn: "Wu and Chu split in southeast; heaven and earth float day and night",
image: "./images/yueyang.jpg",
fallbackImage: "https://picsum.photos/id/1030/800/600",
culture: {
lines: ["吴楚东南坼,乾坤日夜浮","亲朋无一字,老病有孤舟"],
linesEn: ["Wu and Chu split in southeast; heaven and earth float day and night", "No word from relatives and friends; old and ill with a lonely boat"],
anecdote: "杜甫登上岳阳楼,远眺洞庭湖,写下了《登岳阳楼》这首著名诗篇。诗中既有对壮丽自然风光的赞美,也有对自己漂泊生涯的感慨,体现了诗人忧国忧民的情怀。此诗被誉为唐代五言律诗的代表作之一。",
anecdoteEn: "Du Fu climbed Yueyang Tower, looked out at Dongting Lake from a distance, and wrote the famous poem 'Climbing Yueyang Tower.' The poem contains both praise for the magnificent natural scenery and感慨 about his wandering life, embodying the poet's concern for the country and the people. This poem is hailed as one of the representative works of seven-character regulated poems of the Tang Dynasty."
},
hasVideo: false
},
{
name: "潭州",
nameEn: "Tanzhou",
year: 769,
stage: 8,
coord: [28.2, 112.9],
event: "漂泊至潭州,贫病交加",
eventEn: "Wandered to Tanzhou, poor and seriously ill",
poem: "亲朋无一字,老病有孤舟",
poemEn: "No word from relatives and friends; old and ill with a lonely boat",
image: "./images/tanzhou.jpg",
fallbackImage: "https://picsum.photos/id/1031/800/600",
culture: {
lines: ["岁暮阴阳催短景,天涯霜雪霁寒宵","五更鼓角声悲壮,三峡星河影动摇"],
linesEn: ["Year's end, yin and yang hasten short days; sky's edge, frost and snow clear cold night", "Five watch drums and horns sound solemn; Three Gorges stars and river shadows shake"],
anecdote: "杜甫在潭州期间,身体状况日益恶化,但他仍然坚持创作。他在《岁晏行》中描绘了潭州地区百姓的疾苦,表达了对民生的深切关怀。尽管贫病交加,杜甫始终保持着对诗歌的热爱和对国家的忧虑。",
anecdoteEn: "During his stay in Tanzhou, Du Fu's health deteriorated day by day, but he still persisted in creating. In 'Song of Year's End,' he depicted the sufferings of the people in Tanzhou area, expressing deep concern for people's livelihood. Despite being poor and seriously ill, Du Fu always maintained his love for poetry and worry for the country."
},
hasVideo: false
},
{
name: "耒阳",
nameEn: "Leiyang",
year: 770,
stage: 8,
coord: [26.4, 112.8],
event: "病逝于耒阳舟中",
eventEn: "Passed away in a boat in Leiyang",
poem: "战血流依旧,军声动至今",
poemEn: "Warlords' blood still flows; army sounds still move to this day",
image: "./images/leiyang.jpg",
fallbackImage: "https://picsum.photos/id/1032/800/600",
culture: {
lines: ["战血流依旧,军声动至今","无人织锦韂,谁为铸金鞭"],
linesEn: ["Warlords' blood still flows; army sounds still move to this day", "No one weaves brocade saddle covers; who will cast golden whips"],
anecdote: "大历五年(770年),杜甫在前往郴州投奔舅父崔伟的途中,遇到江水暴涨,被困耒阳。耒阳县令聂某闻讯,派人送来酒肉。杜甫在舟中饮酒过多,加之长期贫病交加,不幸去世,享年59岁。一代诗圣就此陨落,但他的诗歌却永远流传于世。",
anecdoteEn: "In the fifth year of Dali (770), Du Fu was on his way to Chenzhou to投奔 his uncle Cui Wei when he encountered rising river waters and was trapped in Leiyang. Upon hearing the news, the magistrate of Leiyang County, Nie, sent someone to deliver wine and meat. Du Fu drank too much wine in the boat, and coupled with long-term poverty and illness, he unfortunately passed away at the age of 59. A generation of poetic sage thus fell, but his poetry will forever be passed down in the world."
},
hasVideo: false
}
];
// 人生阶段名称(中文和英文)
const stageNames = [
{stage: 1, name: "童年时期"},
{stage: 2, name: "青年漫游"},
{stage: 3, name: "困居长安"},
{stage: 4, name: "战乱流离"},
{stage: 5, name: "秦州同谷"},
{stage: 6, name: "成都草堂"},
{stage: 7, name: "夔州岁月"},
{stage: 8, name: "晚年漂泊"}
];
const stageNamesEn = [
{stage: 1, name: "Childhood"},
{stage: 2, name: "Youthful Wandering"},
{stage: 3, name: "Trapped in Chang'an"},
{stage: 4, name: "Wartime Exile"},
{stage: 5, name: "Qinzhou & Tonggu"},
{stage: 6, name: "Chengdu Thatched Cottage"},
{stage: 7, name: "Kuizhou Years"},
{stage: 8, name: "Late Years Wandering"}
];
// 古风颜色方案(对应人生各个阶段)
const stageColors = [
"#8B4513", // 赭石色 - 阶段1
"#4682B4", // 石青色 - 阶段2
"#CD5C5C", // 朱砂色 - 阶段3
"#DAA520", // 藤黄色 - 阶段4
"#2E8B57", // 石绿色 - 阶段5
"#8A2BE2", // 紫色 - 阶段6
"#B22222", // 红色 - 阶段7
"#696969" // 墨色 - 阶段8
];
// 全局变量
let map;
let horseMarker;
let currentPointIndex = 0;
let animationInterval;
let isAnimating = false;
let pathSegments = []; // 存储各段路线
let currentLang = 'zh'; // 默认语言为中文
/* 初始化地图 */
function initMap() {
// 创建地图实例
map = L.map('map', {
preferCanvas: true,
zoomControl: false,
minZoom: 3,
maxZoom: 14
}).setView([34, 110], 5);
// 添加地图图层
L.tileLayer('https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', {
subdomains: '1234',
crossOrigin: true,
reuseTiles: true,
maxZoom: 14
}).addTo(map);
// 添加缩放控件
L.control.zoom({position: 'bottomright'}).addTo(map);
// 绘制分段路线(不同阶段不同颜色,使用蚂蚁线动画)
drawPathSegments();
// 创建点位标记
createPointMarkers();
// 创建骑马标记
createHorseMarker();
// 初始化阶段颜色指示器
initStageIndicators();
// 隐藏加载指示器
document.getElementById('mapLoader').style.display = 'none';
// 显示第一个点位信息
showPointInfo(allPoints[0]);
// 绑定视频按钮事件
document.getElementById('videoBtn').addEventListener('click', openVideo);
}
/* 初始化语言切换功能 */
function initLangSwitch() {
document.getElementById('btnZh').addEventListener('click', () => switchLang('zh'));
document.getElementById('btnEn').addEventListener('click', () => switchLang('en'));
}
/* 切换语言 */
function switchLang(lang) {
if (currentLang === lang) return;
currentLang = lang;
// 更新按钮状态
document.getElementById('btnZh').classList.toggle('active', lang === 'zh');
document.getElementById('btnEn').classList.toggle('active', lang === 'en');
// 更新当前显示的点位信息
showPointInfo(allPoints[currentPointIndex]);
}
/* 绘制分段路线(使用蚂蚁线动画) */
function drawPathSegments() {
// 清除已有路线
pathSegments.forEach(segment => map.removeLayer(segment));
pathSegments = [];
// 绘制每段路线
for (let i = 0; i < allPoints.length - 1; i++) {
const startPoint = allPoints[i];
const endPoint = allPoints[i + 1];
// 使用起点的阶段颜色
const color = stageColors[startPoint.stage - 1];
// 创建蚂蚁线路线
const segment = L.polyline.antPath(
[startPoint.coord, endPoint.coord],
{
color: color,
weight: 3,
opacity: 0.7,
dashArray: [10, 20],
delay: 1000,
pulseColor: '#ffffff'
}
).addTo(map);
pathSegments.push(segment);
}
}
/* 创建点位标记 */
function createPointMarkers() {
allPoints.forEach((point, index) => {
// 使用对应阶段的颜色
const color = stageColors[point.stage - 1];
// 创建标记
const marker = L.marker(point.coord, {
icon: L.divIcon({
className: '',
html: `<div style="background:${color};width:12px;height:12px;border-radius:50%;border:2px solid #fff;box-shadow:0 0 0 2px ${color}80"></div>`,
iconSize: [16, 16]
})
})
.bindTooltip(`${point.name}(${point.year})`)
.on('click', () => {
stopAnimation();
currentPointIndex = index;
moveHorseToPoint(index);
showPointInfo(point);
})
.addTo(map);
});
}
/* 创建骑马标记 - 不旋转版本 */
function createHorseMarker() {
// 创建骑马图标,移除旋转效果
horseMarker = L.marker(allPoints[0].coord, {
icon: L.divIcon({
className: '',
html: `<div style="font-size:24px;">🐎</div>`, // 移除transform属性
iconSize: [30, 30]
}),
zIndexOffset: 1000
}).addTo(map);
}
/* 初始化阶段颜色指示器(带名称) */
function initStageIndicators() {
const container = document.getElementById('stageColors');
// 去重获取所有阶段
const stages = [...new Set(allPoints.map(p => p.stage))];
stages.forEach(stage => {
// 找到对应阶段名称(根据当前语言)
const stageInfo = currentLang === 'en'
? stageNamesEn.find(s => s.stage === stage)
: stageNames.find(s => s.stage === stage);
const stageName = stageInfo ? stageInfo.name : `阶段 ${stage}`;
const colorItem = document.createElement('div');
colorItem.className = 'stage-color-item';
const colorDiv = document.createElement('div');
colorDiv.className = 'stage-color';
colorDiv.style.backgroundColor = stageColors[stage - 1];
const nameSpan = document.createElement('span');
nameSpan.className = 'stage-name';
nameSpan.textContent = stageName;
colorItem.appendChild(colorDiv);
colorItem.appendChild(nameSpan);
container.appendChild(colorItem);
});
}
/* 移动马到指定点位 - 不旋转 */
function moveHorseToPoint(index) {
if (index < 0 || index >= allPoints.length) return;
const targetPoint = allPoints[index];
const targetCoord = targetPoint.coord;
// 平滑移动动画(移除旋转相关代码)
horseMarker.setLatLng(targetCoord);
// 调整地图视角
map.setView(targetCoord, Math.max(map.getZoom(), 6), {
animate: true,
duration: 1
});
}
/* 图片加载失败处理函数 */
function handleImageError(imgElement, fallbackSrc) {
// 仅在未加载成功时才替换
if (imgElement.src !== fallbackSrc) {
imgElement.src = fallbackSrc;
// 防止循环错误
imgElement.onerror = null;
}
}
/* 显示点位信息(支持多语言和图片容错) */
function showPointInfo(point) {
const isEn = currentLang === 'en';
const stageInfo = isEn
? stageNamesEn.find(s => s.stage === point.stage)
: stageNames.find(s => s.stage === point.stage);
const stageName = stageInfo ? stageInfo.name : `阶段 ${point.stage}`;
document.getElementById('infoTitle').textContent = isEn ? point.nameEn : point.name;
document.getElementById('infoYear').textContent = isEn
? `Year ${point.year} | ${stageName}`
: `公元${point.year}年 | ${stageName}`;
document.getElementById('infoDescription').textContent = isEn ? point.eventEn : point.event;
document.getElementById('infoPoem').textContent = isEn ? `「${point.poemEn}」` : `「${point.poem}」`;
const anecdoteHtml = isEn
? `<strong>Anecdote: </strong>${point.culture.anecdoteEn}<br><br><strong>Poetry: </strong>${point.culture.linesEn.join(' / ')}`
: `<strong>轶事:</strong>${point.culture.anecdote}<br><br><strong>诗句:</strong>${point.culture.lines.join(' / ')}`;
document.getElementById('infoAnecdote').innerHTML = anecdoteHtml;
// 处理图片加载
const infoImage = document.getElementById('infoImage');
// 添加加载状态样式
infoImage.classList.add('image-loading');
// 设置图片源和错误处理
infoImage.src = point.image;
infoImage.alt = isEn ? point.nameEn : point.name;
// 验证图片路径格式
if (!point.image.startsWith('./images/')) {
console.warn(`图片路径格式错误: ${point.image},应为./images/文件名`);
}
// 错误处理函数增强
infoImage.onerror = function() {
console.error(`本地图片加载失败: ${point.image},请检查文件是否存在于images文件夹中`);
// 切换到备用图片
handleImageError(this, point.fallbackImage);
};
// 图片加载成功后移除加载样式
infoImage.onload = function() {
infoImage.classList.remove('image-loading');
console.log(`本地图片加载成功: ${point.image}`);
};
// 仅在绵州昌隆显示视频按钮
if (point.hasVideo) {
document.getElementById('videoControl').style.display = 'flex';
} else {
document.getElementById('videoControl').style.display = 'none';
}
// 显示信息卡片
document.getElementById('infoCard').classList.add('active');
}
/* 隐藏信息卡片 */
function hideInfoCard() {
document.getElementById('infoCard').classList.remove('active');
}
/* 打开视频播放模态框 */
function openVideo() {
const videoModal = document.getElementById('videoModal');
const videoPlayer = document.getElementById('videoPlayer');
videoModal.classList.add('active');
// 尝试自动播放视频(可能受浏览器限制)
videoPlayer.play().catch(error => {
console.log('视频自动播放失败,需用户手动点击播放:', error);
});
// 阻止背景滚动
document.body.style.overflow = 'hidden';
}
/* 关闭视频播放模态框 */
function closeVideo() {
const videoModal = document.getElementById('videoModal');
const videoPlayer = document.getElementById('videoPlayer');
videoModal.classList.remove('active');
videoPlayer.pause();
// 恢复背景滚动
document.body.style.overflow = 'auto';
}
/* 切换动画播放/暂停 */
function toggleAnimation() {
if (isAnimating) {
stopAnimation();
} else {
startAnimation();
}
}
/* 开始动画 */
function startAnimation() {
isAnimating = true;
document.getElementById('playBtn').textContent = "⏸";
// 动画间隔(每3秒移动到下一个点)
animationInterval = setInterval(() => {
currentPointIndex = (currentPointIndex + 1) % allPoints.length;
moveHorseToPoint(currentPointIndex);
showPointInfo(allPoints[currentPointIndex]);
// 如果到达最后一个点,停止动画
if (currentPointIndex === allPoints.length - 1) {
clearInterval(animationInterval);
isAnimating = false;
document.getElementById('playBtn').textContent = "▶";
}
}, 5000); // 每个点位停留5秒
}
/* 停止动画 */
function stopAnimation() {
isAnimating = false;
clearInterval(animationInterval);
document.getElementById('playBtn').textContent = "▶";
}
/* 上一个点位 */
function prevPoint() {
stopAnimation();
currentPointIndex = (currentPointIndex - 1 + allPoints.length) % allPoints.length;
moveHorseToPoint(currentPointIndex);
showPointInfo(allPoints[currentPointIndex]);
}
/* 下一个点位 */
function nextPoint() {
stopAnimation();
currentPointIndex = (currentPointIndex + 1) % allPoints.length;
moveHorseToPoint(currentPointIndex);
showPointInfo(allPoints[currentPointIndex]);
}
// 页面加载完成后初始化地图和语言切换
window.onload = function() {
initMap();
initLangSwitch();
// 绑定控制按钮事件
document.getElementById('playBtn').addEventListener('click', toggleAnimation);
document.getElementById('prevBtn').addEventListener('click', prevPoint);
document.getElementById('nextBtn').addEventListener('click', nextPoint);
// 绑定视频模态框关闭事件
document.getElementById('closeVideoBtn').addEventListener('click', closeVideo);
// 点击模态框背景关闭
document.getElementById('videoModal').addEventListener('click', function(e) {
if (e.target === this) closeVideo();
});
};
</script>
</body>
</html>
请先 登录后发表评论 ~