'commit'
This commit is contained in:
@@ -40,15 +40,11 @@
|
||||
height: 30px;
|
||||
background: url("hongqi.jpg") no-repeat center/contain;
|
||||
position: absolute;
|
||||
offset-path: path('M100,350 C150,340 200,320 250,300 300,280 350,260 400,240 450,220 500,200 550,180 600,160 650,140 700,100');
|
||||
offset-distance: 0%;
|
||||
animation: move 20s linear paused;
|
||||
}
|
||||
|
||||
@keyframes move {
|
||||
to {
|
||||
offset-distance: 100%;
|
||||
}
|
||||
transform: translate(-50%, -50%); /* 使红旗中心对准路径 */
|
||||
z-index: 10;
|
||||
/* 添加备用背景样式,以防图片加载失败 */
|
||||
background-color: red;
|
||||
border-radius: 50% 0;
|
||||
}
|
||||
|
||||
#subtitle {
|
||||
@@ -98,6 +94,8 @@
|
||||
<script>
|
||||
const flag = document.getElementById("redFlag");
|
||||
const subtitle = document.getElementById("subtitle");
|
||||
const route = document.getElementById("route");
|
||||
const map = document.getElementById("map");
|
||||
|
||||
const timeline = [
|
||||
{ p: 0, text: "1934年10月 从江西瑞金出发" },
|
||||
@@ -110,30 +108,92 @@
|
||||
{ p: 95, text: "1935年10月 到达吴起镇" }
|
||||
];
|
||||
|
||||
let interval;
|
||||
let animationId;
|
||||
let startTime;
|
||||
let pausedTime = 0;
|
||||
let isPlaying = false;
|
||||
const duration = 20000; // 20秒
|
||||
|
||||
// 获取SVG路径的总长度
|
||||
const pathLength = route.getTotalLength();
|
||||
|
||||
// 计算SVG坐标系到页面坐标系的转换比例
|
||||
function getScaleFactor() {
|
||||
const viewBox = route.viewBox.baseVal;
|
||||
const svgRect = route.closest('svg').getBoundingClientRect();
|
||||
return {
|
||||
x: svgRect.width / viewBox.width,
|
||||
y: svgRect.height / viewBox.height
|
||||
};
|
||||
}
|
||||
|
||||
// 根据进度百分比获取路径上的点
|
||||
function getPointOnPath(percent) {
|
||||
const distance = percent * pathLength / 100;
|
||||
const point = route.getPointAtLength(distance);
|
||||
const scale = getScaleFactor();
|
||||
|
||||
// 获取SVG元素相对于页面的位置
|
||||
const svgRect = route.closest('svg').getBoundingClientRect();
|
||||
const mapRect = map.getBoundingClientRect();
|
||||
|
||||
// 计算红旗在页面上的位置
|
||||
return {
|
||||
x: svgRect.left - mapRect.left + point.x * scale.x,
|
||||
y: svgRect.top - mapRect.top + point.y * scale.y
|
||||
};
|
||||
}
|
||||
|
||||
// 更新红旗位置
|
||||
function updateFlagPosition(percent) {
|
||||
const point = getPointOnPath(percent);
|
||||
flag.style.left = `${point.x}px`;
|
||||
flag.style.top = `${point.y}px`;
|
||||
}
|
||||
|
||||
// 动画循环
|
||||
function animate(timestamp) {
|
||||
if (!startTime) startTime = timestamp;
|
||||
|
||||
const elapsed = timestamp - startTime + pausedTime;
|
||||
const progress = Math.min(elapsed / duration, 1) * 100;
|
||||
|
||||
updateFlagPosition(progress);
|
||||
updateSubtitle(progress);
|
||||
|
||||
if (progress < 100) {
|
||||
animationId = requestAnimationFrame(animate);
|
||||
} else {
|
||||
isPlaying = false;
|
||||
}
|
||||
}
|
||||
|
||||
function play() {
|
||||
flag.style.animationPlayState = "running";
|
||||
interval = setInterval(updateSubtitle, 200);
|
||||
if (!isPlaying) {
|
||||
isPlaying = true;
|
||||
startTime = null;
|
||||
animationId = requestAnimationFrame(animate);
|
||||
}
|
||||
}
|
||||
|
||||
function pause() {
|
||||
flag.style.animationPlayState = "paused";
|
||||
clearInterval(interval);
|
||||
if (isPlaying) {
|
||||
isPlaying = false;
|
||||
cancelAnimationFrame(animationId);
|
||||
if (startTime) {
|
||||
pausedTime += performance.now() - startTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function reset() {
|
||||
flag.style.animation = "none";
|
||||
flag.offsetHeight; // 触发重排
|
||||
flag.style.animation = "move 20s linear paused";
|
||||
pause();
|
||||
pausedTime = 0;
|
||||
updateFlagPosition(0);
|
||||
subtitle.textContent = timeline[0].text;
|
||||
clearInterval(interval);
|
||||
}
|
||||
|
||||
function updateSubtitle() {
|
||||
const computed = window.getComputedStyle(flag);
|
||||
const distance = computed.offsetDistance;
|
||||
const percent = parseFloat(distance);
|
||||
function updateSubtitle(percent) {
|
||||
for (let i = timeline.length - 1; i >= 0; i--) {
|
||||
if (percent >= timeline[i].p) {
|
||||
subtitle.textContent = timeline[i].text;
|
||||
@@ -141,7 +201,27 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
// 页面加载完成后初始化红旗位置
|
||||
window.addEventListener('load', function() {
|
||||
// 确保红旗在初始位置可见
|
||||
updateFlagPosition(0);
|
||||
|
||||
// 检查红旗图片是否加载成功
|
||||
const img = new Image();
|
||||
img.onload = function() {
|
||||
// 图片加载成功,使用图片作为背景
|
||||
flag.style.backgroundImage = 'url("hongqi.jpg")';
|
||||
flag.style.backgroundColor = 'transparent';
|
||||
};
|
||||
img.onerror = function() {
|
||||
// 图片加载失败,使用备用样式
|
||||
console.warn('红旗图片加载失败,使用备用样式');
|
||||
flag.style.backgroundImage = 'none';
|
||||
flag.style.backgroundColor = 'red';
|
||||
};
|
||||
img.src = 'hongqi.jpg';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user