Refactor and enhance various HTML pages with updated links, improved styles, and optimized JavaScript functionality
- Updated badge styles in culture.html for better visual consistency and added backdrop-filter support. - Introduced a fallback panel for the map in index.html with enhanced styles and responsive design. - Changed links in product_ecommerce_freight_booking.html, product_full_logistics_chain_cargo_agent.html, product_full_logistics_chain_platform.html, product_full_logistics_chain_ship_agent.html, product_port_cdi_container.html, product_shipping_boat.html, product_shipping_company.html to point to new URLs with query parameters. - Improved scroll reveal functionality in solution_inland_river_shipping.html, solution_logistics_chain.html, solution_port_supply_chain.html, and solution_supply_chain.html by replacing forEach with a traditional for loop for better performance.
This commit is contained in:
@@ -456,6 +456,7 @@
|
||||
|
||||
.arch-grid-item {
|
||||
background: rgba(30, 41, 59, 0.8);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
backdrop-filter: blur(8px);
|
||||
border: 1px solid rgba(71, 85, 105, 0.5);
|
||||
border-radius: 16px;
|
||||
@@ -519,6 +520,7 @@
|
||||
border-radius: 16px;
|
||||
padding: 10px ;
|
||||
border: 1px solid rgba(71, 85, 105, 0.5);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
backdrop-filter: blur(8px);
|
||||
box-shadow: 0 20px 60px -20px rgba(0, 0, 0, 0.3);
|
||||
display: flex;
|
||||
|
||||
@@ -4679,6 +4679,7 @@ color:#ffffff;
|
||||
box-shadow: -1px 3px 6px rgb(5 99 241 / 67%);
|
||||
border-radius: 30px;
|
||||
background: rgba(16, 119, 255, 0.918);
|
||||
-webkit-backdrop-filter: blur(6px);
|
||||
backdrop-filter: blur(6px);
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
@@ -7730,16 +7731,18 @@ color:#ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
}
|
||||
.product-card .card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
align-items:top;
|
||||
height: 2em;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.product-card .card-header h4 {
|
||||
margin: 0;
|
||||
font-size: 17px;
|
||||
font-size: 16px;
|
||||
color: #102541;
|
||||
font-weight: 600;
|
||||
white-space: normal;
|
||||
@@ -7761,7 +7764,7 @@ color:#ffffff;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -7986,3 +7989,76 @@ color:#ffffff;
|
||||
color: #23527c;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 客户案例详情页项目 Tab */
|
||||
.case-project-switcher {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 14px;
|
||||
margin: 40px 0 30px;
|
||||
padding-bottom: 18px;
|
||||
border-bottom: 1px solid #dbe6f3;
|
||||
}
|
||||
|
||||
.case-project-tab {
|
||||
border: 0;
|
||||
border-radius: 16px;
|
||||
padding: 14px 22px;
|
||||
background: #f2f7ff;
|
||||
color: #39526d;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
transition: background-color 0.25s ease, color 0.25s ease, box-shadow 0.25s ease, transform 0.25s ease;
|
||||
}
|
||||
|
||||
.case-project-tab:hover,
|
||||
.case-project-tab:focus {
|
||||
background: #e3efff;
|
||||
color: #173f73;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.case-project-tab.is-active {
|
||||
background: linear-gradient(135deg, #0b63ce 0%, #1ba0ff 100%);
|
||||
color: #ffffff;
|
||||
box-shadow: 0 12px 24px rgba(11, 99, 206, 0.2);
|
||||
}
|
||||
|
||||
.case-project-pane {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.case-project-pane.is-active {
|
||||
display: block;
|
||||
animation: caseProjectFadeIn 0.25s ease;
|
||||
}
|
||||
|
||||
.case-project-pane .project-single-content {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
@keyframes caseProjectFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
.case-project-switcher {
|
||||
margin-top: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.case-project-tab {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@
|
||||
background: linear-gradient(90deg, rgba(20, 129, 255, 0.08) 0%, transparent 100%);
|
||||
}
|
||||
|
||||
.timeline-container:has(.auto-expanded) .timeline-item:not(.auto-expanded) {
|
||||
.timeline-container.has-auto-expanded .timeline-item:not(.auto-expanded) {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
|
||||
52
assets/js/classiccase-project-tabs.js
Normal file
52
assets/js/classiccase-project-tabs.js
Normal file
@@ -0,0 +1,52 @@
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var tabGroups = document.querySelectorAll("[data-case-tabs]");
|
||||
|
||||
Array.prototype.forEach.call(tabGroups, function(group) {
|
||||
var buttons = group.querySelectorAll("[data-case-tab]");
|
||||
var panes = group.querySelectorAll("[data-case-pane]");
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var requestedTab = params.get("tab");
|
||||
var defaultTab = group.getAttribute("data-default-tab");
|
||||
var initialTab = requestedTab || defaultTab;
|
||||
|
||||
function activateTab(tabName, updateUrl) {
|
||||
var hasMatch = false;
|
||||
|
||||
Array.prototype.forEach.call(buttons, function(button) {
|
||||
var isActive = button.getAttribute("data-case-tab") === tabName;
|
||||
button.classList.toggle("is-active", isActive);
|
||||
button.setAttribute("aria-selected", isActive ? "true" : "false");
|
||||
button.setAttribute("tabindex", isActive ? "0" : "-1");
|
||||
if (isActive) {
|
||||
hasMatch = true;
|
||||
}
|
||||
});
|
||||
|
||||
Array.prototype.forEach.call(panes, function(pane) {
|
||||
var isActive = pane.getAttribute("data-case-pane") === tabName;
|
||||
pane.classList.toggle("is-active", isActive);
|
||||
pane.hidden = !isActive;
|
||||
});
|
||||
|
||||
if (!hasMatch) {
|
||||
if (defaultTab && defaultTab !== tabName) {
|
||||
activateTab(defaultTab, updateUrl);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (updateUrl) {
|
||||
params.set("tab", tabName);
|
||||
window.history.replaceState({}, "", window.location.pathname + "?" + params.toString() + window.location.hash);
|
||||
}
|
||||
}
|
||||
|
||||
Array.prototype.forEach.call(buttons, function(button) {
|
||||
button.addEventListener("click", function() {
|
||||
activateTab(button.getAttribute("data-case-tab"), true);
|
||||
});
|
||||
});
|
||||
|
||||
activateTab(initialTab, Boolean(requestedTab));
|
||||
});
|
||||
});
|
||||
47
assets/js/map3d-loader.js
Normal file
47
assets/js/map3d-loader.js
Normal file
@@ -0,0 +1,47 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function supportsModuleScripts() {
|
||||
var script = document.createElement("script");
|
||||
return "noModule" in script;
|
||||
}
|
||||
|
||||
function supportsWebGL() {
|
||||
try {
|
||||
var canvas = document.createElement("canvas");
|
||||
return !!(window.WebGLRenderingContext && (canvas.getContext("webgl") || canvas.getContext("experimental-webgl")));
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function bootstrapMapModule() {
|
||||
var map = document.getElementById("map");
|
||||
var script;
|
||||
|
||||
if (!map || map.getAttribute("data-map-module-loaded") === "true") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!supportsModuleScripts() || !supportsWebGL() || typeof Promise === "undefined" || typeof fetch === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
map.setAttribute("data-map-module-loaded", "true");
|
||||
|
||||
script = document.createElement("script");
|
||||
script.type = "module";
|
||||
script.src = "assets/js/map3d.js";
|
||||
script.onerror = function () {
|
||||
map.removeAttribute("data-map-module-loaded");
|
||||
};
|
||||
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", bootstrapMapModule);
|
||||
} else {
|
||||
bootstrapMapModule();
|
||||
}
|
||||
}());
|
||||
@@ -74,6 +74,8 @@ async function initMap3D(geoDataPromise = null, threeJSPromise = null) {
|
||||
const labelRenderer = new CSS2DRenderer();
|
||||
labelRenderer.domElement.style.position = "absolute";
|
||||
labelRenderer.domElement.style.top = "0px";
|
||||
labelRenderer.domElement.style.left = "0px";
|
||||
labelRenderer.domElement.style.zIndex = "3";
|
||||
labelRenderer.domElement.style.pointerEvents = "none";
|
||||
labelRenderer.setSize(container.clientWidth, container.clientHeight);
|
||||
container.appendChild(labelRenderer.domElement);
|
||||
@@ -81,6 +83,8 @@ async function initMap3D(geoDataPromise = null, threeJSPromise = null) {
|
||||
const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
|
||||
renderer.setSize(container.clientWidth, container.clientHeight);
|
||||
renderer.setPixelRatio(window.devicePixelRatio || 1);
|
||||
renderer.domElement.style.position = "relative";
|
||||
renderer.domElement.style.zIndex = "2";
|
||||
container.appendChild(renderer.domElement);
|
||||
|
||||
const controls = new OrbitControls(camera, renderer.domElement);
|
||||
@@ -95,6 +99,7 @@ async function initMap3D(geoDataPromise = null, threeJSPromise = null) {
|
||||
|
||||
const tooltip = document.createElement("div");
|
||||
tooltip.style.cssText = "position:absolute;padding:6px 10px;background:rgba(24,118,242,0.92);color:#fff;font-size:13px;border-radius:6px;pointer-events:none;box-shadow:0 2px 6px rgba(0,0,0,0.25);display:none;";
|
||||
tooltip.style.zIndex = "4";
|
||||
container.appendChild(tooltip);
|
||||
|
||||
const animate = () => {
|
||||
@@ -372,6 +377,7 @@ async function initMap3D(geoDataPromise = null, threeJSPromise = null) {
|
||||
const map = createMap(data, 0.05);
|
||||
map.add(createPulseRings(data, 0.05));
|
||||
scene.add(map);
|
||||
container.classList.add("map-enhanced-ready");
|
||||
} catch (err) {
|
||||
console.error("Failed to load map data:", err);
|
||||
}
|
||||
|
||||
@@ -6,72 +6,104 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// 等待DOM加载完成
|
||||
document.addEventListener('DOMContentLoaded', initTimeline);
|
||||
|
||||
function forEachNode(list, callback) {
|
||||
Array.prototype.forEach.call(list, callback);
|
||||
}
|
||||
|
||||
function supportsSmoothScroll() {
|
||||
return 'scrollBehavior' in document.documentElement.style;
|
||||
}
|
||||
|
||||
function initTimeline() {
|
||||
const container = document.querySelector('.timeline-container');
|
||||
var container = document.querySelector('.timeline-container');
|
||||
if (!container) return;
|
||||
|
||||
const items = container.querySelectorAll('.timeline-item');
|
||||
var items = container.querySelectorAll('.timeline-item');
|
||||
if (!items.length) return;
|
||||
|
||||
// 入场动画 - 使用 Intersection Observer
|
||||
const observerOptions = {
|
||||
var hasIntersectionObserver = 'IntersectionObserver' in window;
|
||||
var touchStartX = null;
|
||||
var scrollLeft = null;
|
||||
var isDragging = false;
|
||||
var startX;
|
||||
var dragScrollLeft;
|
||||
var currentIndex = 0;
|
||||
var autoPlayIndex = 0;
|
||||
var autoPlayTimer = null;
|
||||
var isUserInteracting = false;
|
||||
var interactionTimer = null;
|
||||
var autoPlayInterval = 3000;
|
||||
var pauseAfterInteraction = 5000;
|
||||
var observerOptions = {
|
||||
threshold: 0.1,
|
||||
rootMargin: '0px 0px -50px 0px'
|
||||
};
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
animateItems();
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
function updateExpandedState(active) {
|
||||
if (active) {
|
||||
container.classList.add('has-auto-expanded');
|
||||
} else {
|
||||
container.classList.remove('has-auto-expanded');
|
||||
}
|
||||
}
|
||||
|
||||
function clearExpandedItems() {
|
||||
forEachNode(items, function(item) {
|
||||
item.classList.remove('auto-expanded');
|
||||
});
|
||||
}, observerOptions);
|
||||
updateExpandedState(false);
|
||||
}
|
||||
|
||||
observer.observe(container);
|
||||
|
||||
// 节点逐个入场动画
|
||||
function animateItems() {
|
||||
items.forEach((item, index) => {
|
||||
setTimeout(() => {
|
||||
function animateItems(useDelay) {
|
||||
forEachNode(items, function(item, index) {
|
||||
var delay = useDelay ? index * 80 : 0;
|
||||
setTimeout(function() {
|
||||
item.style.opacity = '1';
|
||||
item.style.transform = 'translateY(0)';
|
||||
}, index * 80);
|
||||
}, delay);
|
||||
});
|
||||
}
|
||||
|
||||
// 初始化节点样式(用于动画)
|
||||
items.forEach(item => {
|
||||
forEachNode(items, function(item) {
|
||||
item.style.opacity = '0';
|
||||
item.style.transform = 'translateY(20px)';
|
||||
item.style.transition = 'opacity 0.5s ease, transform 0.5s ease, flex 0.5s cubic-bezier(0.25, 0.1, 0.25, 1), background 0.5s ease';
|
||||
});
|
||||
|
||||
// 触摸设备支持
|
||||
let touchStartX = null;
|
||||
let scrollLeft = null;
|
||||
if (hasIntersectionObserver) {
|
||||
var observer = new IntersectionObserver(function(entries) {
|
||||
for (var entryIndex = 0; entryIndex < entries.length; entryIndex += 1) {
|
||||
if (entries[entryIndex].isIntersecting) {
|
||||
animateItems(true);
|
||||
observer.unobserve(entries[entryIndex].target);
|
||||
}
|
||||
}
|
||||
}, observerOptions);
|
||||
|
||||
container.addEventListener('touchstart', (e) => {
|
||||
observer.observe(container);
|
||||
} else {
|
||||
animateItems(false);
|
||||
}
|
||||
|
||||
container.addEventListener('touchstart', function(e) {
|
||||
touchStartX = e.touches[0].pageX;
|
||||
scrollLeft = container.scrollLeft;
|
||||
}, { passive: true });
|
||||
|
||||
container.addEventListener('touchmove', (e) => {
|
||||
container.addEventListener('touchmove', function(e) {
|
||||
if (!touchStartX) return;
|
||||
const x = e.touches[0].pageX;
|
||||
const walk = (touchStartX - x) * 1.5;
|
||||
var x = e.touches[0].pageX;
|
||||
var walk = (touchStartX - x) * 1.5;
|
||||
container.scrollLeft = scrollLeft + walk;
|
||||
}, { passive: true });
|
||||
|
||||
container.addEventListener('touchend', () => {
|
||||
container.addEventListener('touchend', function() {
|
||||
touchStartX = null;
|
||||
});
|
||||
|
||||
// 鼠标滚轮横向滚动(移动端视图时)
|
||||
container.addEventListener('wheel', (e) => {
|
||||
container.addEventListener('wheel', function(e) {
|
||||
if (container.scrollWidth > container.clientWidth) {
|
||||
if (Math.abs(e.deltaX) < Math.abs(e.deltaY)) {
|
||||
e.preventDefault();
|
||||
@@ -80,56 +112,46 @@
|
||||
}
|
||||
}, { passive: false });
|
||||
|
||||
// 拖拽滚动(移动端视图时)
|
||||
let isDragging = false;
|
||||
let startX;
|
||||
let dragScrollLeft;
|
||||
|
||||
container.addEventListener('mousedown', (e) => {
|
||||
container.addEventListener('mousedown', function(e) {
|
||||
if (container.scrollWidth <= container.clientWidth) return;
|
||||
if (e.target.closest('.timeline-item')) return;
|
||||
if (e.target.closest && e.target.closest('.timeline-item')) return;
|
||||
isDragging = true;
|
||||
container.style.cursor = 'grabbing';
|
||||
startX = e.pageX - container.offsetLeft;
|
||||
dragScrollLeft = container.scrollLeft;
|
||||
});
|
||||
|
||||
container.addEventListener('mouseleave', () => {
|
||||
container.addEventListener('mouseleave', function() {
|
||||
isDragging = false;
|
||||
container.style.cursor = '';
|
||||
});
|
||||
|
||||
container.addEventListener('mouseup', () => {
|
||||
container.addEventListener('mouseup', function() {
|
||||
isDragging = false;
|
||||
container.style.cursor = '';
|
||||
});
|
||||
|
||||
container.addEventListener('mousemove', (e) => {
|
||||
container.addEventListener('mousemove', function(e) {
|
||||
if (!isDragging) return;
|
||||
e.preventDefault();
|
||||
const x = e.pageX - container.offsetLeft;
|
||||
const walk = (x - startX) * 2;
|
||||
var x = e.pageX - container.offsetLeft;
|
||||
var walk = (x - startX) * 2;
|
||||
container.scrollLeft = dragScrollLeft - walk;
|
||||
});
|
||||
|
||||
// 节点点击事件(可扩展)
|
||||
items.forEach((item) => {
|
||||
item.addEventListener('click', () => {
|
||||
// 添加点击反馈动画
|
||||
const dot = item.querySelector('.dot');
|
||||
forEachNode(items, function(item) {
|
||||
item.addEventListener('click', function() {
|
||||
var dot = item.querySelector('.dot');
|
||||
if (dot) {
|
||||
dot.style.transform = 'translate(-50%, -50%) scale(2)';
|
||||
setTimeout(() => {
|
||||
setTimeout(function() {
|
||||
dot.style.transform = '';
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 键盘导航支持
|
||||
let currentIndex = 0;
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (!isElementInViewport(container)) return;
|
||||
|
||||
if (e.key === 'ArrowLeft') {
|
||||
@@ -144,42 +166,32 @@
|
||||
function scrollToItem(index) {
|
||||
if (container.scrollWidth <= container.clientWidth) return;
|
||||
|
||||
const item = items[index];
|
||||
var item = items[index];
|
||||
if (!item) return;
|
||||
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
const itemRect = item.getBoundingClientRect();
|
||||
var containerRect = container.getBoundingClientRect();
|
||||
var itemRect = item.getBoundingClientRect();
|
||||
var targetScrollLeft = container.scrollLeft + (itemRect.left - containerRect.left) - (containerRect.width / 2) + (itemRect.width / 2);
|
||||
|
||||
const targetScrollLeft = container.scrollLeft + (itemRect.left - containerRect.left) - (containerRect.width / 2) + (itemRect.width / 2);
|
||||
if (typeof container.scrollTo === 'function' && supportsSmoothScroll()) {
|
||||
container.scrollTo({
|
||||
left: targetScrollLeft,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
container.scrollTo({
|
||||
left: targetScrollLeft,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
container.scrollLeft = targetScrollLeft;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 自动轮播功能 - 从左到右循环展开
|
||||
// ============================================
|
||||
let autoPlayIndex = 0;
|
||||
let autoPlayTimer = null;
|
||||
let isUserInteracting = false;
|
||||
const autoPlayInterval = 3000; // 每个节点展开持续时间(毫秒)
|
||||
const pauseAfterInteraction = 5000; // 用户交互后暂停时间(毫秒)
|
||||
|
||||
// 添加自动展开的CSS类
|
||||
function expandItem(index) {
|
||||
// 移除所有节点的展开状态
|
||||
items.forEach(item => {
|
||||
item.classList.remove('auto-expanded');
|
||||
});
|
||||
// 给当前节点添加展开状态
|
||||
clearExpandedItems();
|
||||
if (items[index]) {
|
||||
items[index].classList.add('auto-expanded');
|
||||
updateExpandedState(true);
|
||||
}
|
||||
}
|
||||
|
||||
// 自动轮播
|
||||
function autoPlay() {
|
||||
if (isUserInteracting) return;
|
||||
|
||||
@@ -187,63 +199,56 @@
|
||||
autoPlayIndex = (autoPlayIndex + 1) % items.length;
|
||||
}
|
||||
|
||||
// 启动自动轮播
|
||||
function startAutoPlay() {
|
||||
if (autoPlayTimer) return;
|
||||
autoPlayTimer = setInterval(autoPlay, autoPlayInterval);
|
||||
// 立即展开第一个
|
||||
autoPlay();
|
||||
}
|
||||
|
||||
// 停止自动轮播
|
||||
function stopAutoPlay() {
|
||||
if (autoPlayTimer) {
|
||||
clearInterval(autoPlayTimer);
|
||||
autoPlayTimer = null;
|
||||
}
|
||||
// 移除所有展开状态
|
||||
items.forEach(item => {
|
||||
item.classList.remove('auto-expanded');
|
||||
});
|
||||
clearExpandedItems();
|
||||
}
|
||||
|
||||
// 用户交互时暂停自动轮播
|
||||
function pauseAutoPlay() {
|
||||
isUserInteracting = true;
|
||||
stopAutoPlay();
|
||||
|
||||
// 一段时间后恢复自动轮播
|
||||
setTimeout(() => {
|
||||
if (interactionTimer) {
|
||||
clearTimeout(interactionTimer);
|
||||
}
|
||||
|
||||
interactionTimer = setTimeout(function() {
|
||||
isUserInteracting = false;
|
||||
if (isElementInViewport(container)) {
|
||||
if (hasIntersectionObserver && isElementInViewport(container)) {
|
||||
startAutoPlay();
|
||||
}
|
||||
}, pauseAfterInteraction);
|
||||
}
|
||||
|
||||
// 监听用户交互
|
||||
container.addEventListener('mouseenter', pauseAutoPlay);
|
||||
container.addEventListener('touchstart', pauseAutoPlay, { passive: true });
|
||||
|
||||
// 使用 Intersection Observer 控制自动轮播
|
||||
const autoPlayObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting && !isUserInteracting) {
|
||||
startAutoPlay();
|
||||
} else {
|
||||
stopAutoPlay();
|
||||
if (hasIntersectionObserver) {
|
||||
var autoPlayObserver = new IntersectionObserver(function(entries) {
|
||||
for (var entryIndex = 0; entryIndex < entries.length; entryIndex += 1) {
|
||||
if (entries[entryIndex].isIntersecting && !isUserInteracting) {
|
||||
startAutoPlay();
|
||||
} else {
|
||||
stopAutoPlay();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.3 });
|
||||
}, { threshold: 0.3 });
|
||||
|
||||
autoPlayObserver.observe(container);
|
||||
|
||||
console.log("Timeline Loaded with Enhanced Labels and Positioning");
|
||||
autoPlayObserver.observe(container);
|
||||
}
|
||||
}
|
||||
|
||||
// 工具函数:检查元素是否在视口中
|
||||
function isElementInViewport(el) {
|
||||
const rect = el.getBoundingClientRect();
|
||||
var rect = el.getBoundingClientRect();
|
||||
return (
|
||||
rect.top < window.innerHeight &&
|
||||
rect.bottom > 0
|
||||
|
||||
Reference in New Issue
Block a user