联系我们
431
assets/css/timeline.css
Normal file
@@ -0,0 +1,431 @@
|
|||||||
|
/* ============================================
|
||||||
|
智慧时间轴组件 - 横向展开式
|
||||||
|
Smart Timeline Component - Horizontal Expansion
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&family=Oswald:wght@400;700&display=swap');
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--tl-bg-color: #f8fafc;
|
||||||
|
--tl-line-color: rgba(20, 129, 255, 0.3);
|
||||||
|
--tl-active-color: #1481ff;
|
||||||
|
--tl-text-color: #2a3e5d;
|
||||||
|
--tl-year-color: #102541;
|
||||||
|
--tl-transition-speed: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Section 容器 */
|
||||||
|
.timeline-section {
|
||||||
|
width: 100%;
|
||||||
|
background-image:
|
||||||
|
radial-gradient(circle at 10% 20%, rgba(20, 129, 255, 0.08) 0%, transparent 20%),
|
||||||
|
radial-gradient(circle at 90% 80%, rgba(20, 129, 255, 0.05) 0%, transparent 20%);
|
||||||
|
font-family: 'Noto Sans SC', sans-serif;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 60px 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 标题样式 */
|
||||||
|
.timeline-title {
|
||||||
|
color: var(--tl-year-color);
|
||||||
|
letter-spacing: 4px;
|
||||||
|
font-weight: 300;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 24px;
|
||||||
|
opacity: 0.9;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 主容器 */
|
||||||
|
.timeline-container {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 20vh;
|
||||||
|
min-height: 500px;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 主轴线 */
|
||||||
|
.timeline-line {
|
||||||
|
position: absolute;
|
||||||
|
top: 66.67%;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
background: linear-gradient(90deg,
|
||||||
|
transparent 0%,
|
||||||
|
var(--tl-line-color) 5%,
|
||||||
|
var(--tl-line-color) 95%,
|
||||||
|
transparent 100%);
|
||||||
|
z-index: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 时间节点 */
|
||||||
|
.timeline-item {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
flex: 1;
|
||||||
|
transition: flex var(--tl-transition-speed) cubic-bezier(0.25, 0.1, 0.25, 1);
|
||||||
|
border-right: 1px solid rgba(20, 129, 255, 0.1);
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item:hover {
|
||||||
|
flex: 10;
|
||||||
|
background: linear-gradient(90deg, rgba(20, 129, 255, 0.08) 0%, transparent 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-container:hover .timeline-item:not(:hover) {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 节点圆点 */
|
||||||
|
.dot {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: var(--tl-active-color);
|
||||||
|
border-radius: 50%;
|
||||||
|
position: absolute;
|
||||||
|
top: 66.67%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
box-shadow: 0 0 10px var(--tl-active-color);
|
||||||
|
transition: all var(--tl-transition-speed);
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item:hover .dot {
|
||||||
|
background-color: var(--tl-active-color);
|
||||||
|
transform: translate(-50%, -50%) scale(1.5);
|
||||||
|
box-shadow: 0 0 20px rgba(20, 129, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 竖向年份标签 */
|
||||||
|
.year-label {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(66.67% + 15px);
|
||||||
|
left: 50%;
|
||||||
|
transform-origin: 0 0;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
|
||||||
|
font-family: 'Oswald', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--tl-year-color);
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: all 0.3s;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
opacity: 0.8;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 竖向文字中的简短描述 */
|
||||||
|
.short-desc {
|
||||||
|
font-family: 'Noto Sans SC', sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
opacity: 0.6;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover 状态下:标签变大并移到底部背景 */
|
||||||
|
.timeline-item:hover .year-label {
|
||||||
|
top: auto;
|
||||||
|
bottom: -10px;
|
||||||
|
left: 20px;
|
||||||
|
transform: rotate(0deg);
|
||||||
|
font-size: 4rem;
|
||||||
|
font-weight: 700;
|
||||||
|
opacity: 0.08;
|
||||||
|
color: var(--tl-active-color);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover时隐藏简述 */
|
||||||
|
.timeline-item:hover .short-desc {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 内容区域 - 固定在时间轴线上方 */
|
||||||
|
.content {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
transition: all 0.4s ease 0.1s;
|
||||||
|
padding: 0 40px;
|
||||||
|
color: var(--tl-text-color);
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
bottom: 36%;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
text-align: left;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item:hover .content {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-date {
|
||||||
|
display: block;
|
||||||
|
color: var(--tl-active-color);
|
||||||
|
font-family: 'Oswald', sans-serif;
|
||||||
|
font-size: 2rem;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 0 0 20px rgba(20, 129, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-text {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
line-height: 1.8;
|
||||||
|
border-left: 3px solid var(--tl-active-color);
|
||||||
|
padding-left: 20px;
|
||||||
|
max-width: 650px;
|
||||||
|
background: linear-gradient(90deg, rgba(20, 129, 255, 0.08) 0%, transparent 100%);
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-radius: 0 4px 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-text p {
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-text p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 重要节点高亮 */
|
||||||
|
.timeline-item.highlight .dot {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
box-shadow: 0 0 15px var(--tl-active-color), 0 0 30px var(--tl-active-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item.highlight .year-label {
|
||||||
|
color: var(--tl-active-color);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
自动轮播展开效果(与hover效果一致)
|
||||||
|
============================================ */
|
||||||
|
.timeline-item.auto-expanded {
|
||||||
|
flex: 10;
|
||||||
|
background: linear-gradient(90deg, rgba(20, 129, 255, 0.08) 0%, transparent 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-container:has(.auto-expanded) .timeline-item:not(.auto-expanded) {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item.auto-expanded .dot {
|
||||||
|
background-color: var(--tl-active-color);
|
||||||
|
transform: translate(-50%, -50%) scale(1.5);
|
||||||
|
box-shadow: 0 0 20px rgba(20, 129, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item.auto-expanded .year-label {
|
||||||
|
top: auto;
|
||||||
|
bottom: -10px;
|
||||||
|
left: 20px;
|
||||||
|
transform: rotate(0deg);
|
||||||
|
font-size: 4rem;
|
||||||
|
font-weight: 700;
|
||||||
|
opacity: 0.08;
|
||||||
|
color: var(--tl-active-color);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item.auto-expanded .short-desc {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item.auto-expanded .content {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
响应式设计
|
||||||
|
============================================ */
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.timeline-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 20vh;
|
||||||
|
min-height: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.year-label {
|
||||||
|
font-size: 12px;
|
||||||
|
top: calc(66.67% + 15px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.short-desc {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-text {
|
||||||
|
font-size: 1rem;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-date {
|
||||||
|
font-size: 1.6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991px) {
|
||||||
|
.timeline-section {
|
||||||
|
padding: 40px 0;
|
||||||
|
min-height: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 20vh;
|
||||||
|
min-height: 500px;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: visible;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item {
|
||||||
|
min-width: 80px;
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item:hover {
|
||||||
|
flex: none;
|
||||||
|
min-width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-text {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.timeline-title {
|
||||||
|
font-size: 18px;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-container {
|
||||||
|
height: 70vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item {
|
||||||
|
min-width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item:hover {
|
||||||
|
min-width: 280px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.year-label {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.short-desc {
|
||||||
|
font-size: 9px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-date {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-text {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
padding-left: 15px;
|
||||||
|
max-width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dot {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
.timeline-section {
|
||||||
|
padding: 30px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-title {
|
||||||
|
font-size: 16px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-container {
|
||||||
|
height: 60vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item {
|
||||||
|
min-width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item:hover {
|
||||||
|
min-width: 220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.year-label {
|
||||||
|
font-size: 10px;
|
||||||
|
top: calc(66.67% + 12px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-date {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-text {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item:hover .year-label {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
bottom: -30px;
|
||||||
|
left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 299 KiB |
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 313 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 401 KiB |
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 374 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 297 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 17 KiB |
BIN
assets/images/project/port/cdi2.png
Normal file
|
After Width: | Height: | Size: 337 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 258 KiB |
|
Before Width: | Height: | Size: 913 KiB After Width: | Height: | Size: 354 KiB |
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 284 KiB |
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 271 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 284 KiB |
|
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 500 KiB |
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 434 KiB |
252
assets/js/timeline.js
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
/**
|
||||||
|
* 智慧时间轴组件 - 横向展开式
|
||||||
|
* Smart Timeline Component - Horizontal Expansion
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// 等待DOM加载完成
|
||||||
|
document.addEventListener('DOMContentLoaded', initTimeline);
|
||||||
|
|
||||||
|
function initTimeline() {
|
||||||
|
const container = document.querySelector('.timeline-container');
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
const items = container.querySelectorAll('.timeline-item');
|
||||||
|
if (!items.length) return;
|
||||||
|
|
||||||
|
// 入场动画 - 使用 Intersection Observer
|
||||||
|
const 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, observerOptions);
|
||||||
|
|
||||||
|
observer.observe(container);
|
||||||
|
|
||||||
|
// 节点逐个入场动画
|
||||||
|
function animateItems() {
|
||||||
|
items.forEach((item, index) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
item.style.opacity = '1';
|
||||||
|
item.style.transform = 'translateY(0)';
|
||||||
|
}, index * 80);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化节点样式(用于动画)
|
||||||
|
items.forEach(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;
|
||||||
|
|
||||||
|
container.addEventListener('touchstart', (e) => {
|
||||||
|
touchStartX = e.touches[0].pageX;
|
||||||
|
scrollLeft = container.scrollLeft;
|
||||||
|
}, { passive: true });
|
||||||
|
|
||||||
|
container.addEventListener('touchmove', (e) => {
|
||||||
|
if (!touchStartX) return;
|
||||||
|
const x = e.touches[0].pageX;
|
||||||
|
const walk = (touchStartX - x) * 1.5;
|
||||||
|
container.scrollLeft = scrollLeft + walk;
|
||||||
|
}, { passive: true });
|
||||||
|
|
||||||
|
container.addEventListener('touchend', () => {
|
||||||
|
touchStartX = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 鼠标滚轮横向滚动(移动端视图时)
|
||||||
|
container.addEventListener('wheel', (e) => {
|
||||||
|
if (container.scrollWidth > container.clientWidth) {
|
||||||
|
if (Math.abs(e.deltaX) < Math.abs(e.deltaY)) {
|
||||||
|
e.preventDefault();
|
||||||
|
container.scrollLeft += e.deltaY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, { passive: false });
|
||||||
|
|
||||||
|
// 拖拽滚动(移动端视图时)
|
||||||
|
let isDragging = false;
|
||||||
|
let startX;
|
||||||
|
let dragScrollLeft;
|
||||||
|
|
||||||
|
container.addEventListener('mousedown', (e) => {
|
||||||
|
if (container.scrollWidth <= container.clientWidth) return;
|
||||||
|
if (e.target.closest('.timeline-item')) return;
|
||||||
|
isDragging = true;
|
||||||
|
container.style.cursor = 'grabbing';
|
||||||
|
startX = e.pageX - container.offsetLeft;
|
||||||
|
dragScrollLeft = container.scrollLeft;
|
||||||
|
});
|
||||||
|
|
||||||
|
container.addEventListener('mouseleave', () => {
|
||||||
|
isDragging = false;
|
||||||
|
container.style.cursor = '';
|
||||||
|
});
|
||||||
|
|
||||||
|
container.addEventListener('mouseup', () => {
|
||||||
|
isDragging = false;
|
||||||
|
container.style.cursor = '';
|
||||||
|
});
|
||||||
|
|
||||||
|
container.addEventListener('mousemove', (e) => {
|
||||||
|
if (!isDragging) return;
|
||||||
|
e.preventDefault();
|
||||||
|
const x = e.pageX - container.offsetLeft;
|
||||||
|
const walk = (x - startX) * 2;
|
||||||
|
container.scrollLeft = dragScrollLeft - walk;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 节点点击事件(可扩展)
|
||||||
|
items.forEach((item) => {
|
||||||
|
item.addEventListener('click', () => {
|
||||||
|
// 添加点击反馈动画
|
||||||
|
const dot = item.querySelector('.dot');
|
||||||
|
if (dot) {
|
||||||
|
dot.style.transform = 'translate(-50%, -50%) scale(2)';
|
||||||
|
setTimeout(() => {
|
||||||
|
dot.style.transform = '';
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 键盘导航支持
|
||||||
|
let currentIndex = 0;
|
||||||
|
|
||||||
|
document.addEventListener('keydown', (e) => {
|
||||||
|
if (!isElementInViewport(container)) return;
|
||||||
|
|
||||||
|
if (e.key === 'ArrowLeft') {
|
||||||
|
currentIndex = Math.max(0, currentIndex - 1);
|
||||||
|
scrollToItem(currentIndex);
|
||||||
|
} else if (e.key === 'ArrowRight') {
|
||||||
|
currentIndex = Math.min(items.length - 1, currentIndex + 1);
|
||||||
|
scrollToItem(currentIndex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function scrollToItem(index) {
|
||||||
|
if (container.scrollWidth <= container.clientWidth) return;
|
||||||
|
|
||||||
|
const item = items[index];
|
||||||
|
if (!item) return;
|
||||||
|
|
||||||
|
const containerRect = container.getBoundingClientRect();
|
||||||
|
const itemRect = item.getBoundingClientRect();
|
||||||
|
|
||||||
|
const targetScrollLeft = container.scrollLeft + (itemRect.left - containerRect.left) - (containerRect.width / 2) + (itemRect.width / 2);
|
||||||
|
|
||||||
|
container.scrollTo({
|
||||||
|
left: targetScrollLeft,
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================
|
||||||
|
// 自动轮播功能 - 从左到右循环展开
|
||||||
|
// ============================================
|
||||||
|
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');
|
||||||
|
});
|
||||||
|
// 给当前节点添加展开状态
|
||||||
|
if (items[index]) {
|
||||||
|
items[index].classList.add('auto-expanded');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动轮播
|
||||||
|
function autoPlay() {
|
||||||
|
if (isUserInteracting) return;
|
||||||
|
|
||||||
|
expandItem(autoPlayIndex);
|
||||||
|
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');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户交互时暂停自动轮播
|
||||||
|
function pauseAutoPlay() {
|
||||||
|
isUserInteracting = true;
|
||||||
|
stopAutoPlay();
|
||||||
|
|
||||||
|
// 一段时间后恢复自动轮播
|
||||||
|
setTimeout(() => {
|
||||||
|
isUserInteracting = false;
|
||||||
|
if (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();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, { threshold: 0.3 });
|
||||||
|
|
||||||
|
autoPlayObserver.observe(container);
|
||||||
|
|
||||||
|
console.log("Timeline Loaded with Enhanced Labels and Positioning");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 工具函数:检查元素是否在视口中
|
||||||
|
function isElementInViewport(el) {
|
||||||
|
const rect = el.getBoundingClientRect();
|
||||||
|
return (
|
||||||
|
rect.top < window.innerHeight &&
|
||||||
|
rect.bottom > 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})();
|
||||||
213
contact.html
@@ -25,6 +25,7 @@
|
|||||||
<link href="assets/css/jquery.fancybox.css" rel="stylesheet">
|
<link href="assets/css/jquery.fancybox.css" rel="stylesheet">
|
||||||
<link href="assets/css/style.css" rel="stylesheet">
|
<link href="assets/css/style.css" rel="stylesheet">
|
||||||
<link href="assets/css/style 2.css" rel="stylesheet">
|
<link href="assets/css/style 2.css" rel="stylesheet">
|
||||||
|
<link href="assets/css/timeline.css" rel="stylesheet">
|
||||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||||
<!--[if lt IE 9]>
|
<!--[if lt IE 9]>
|
||||||
<script src="assets/js/html5shiv.min.js"></script>
|
<script src="assets/js/html5shiv.min.js"></script>
|
||||||
@@ -105,6 +106,217 @@
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 发展里程 -->
|
||||||
|
<section class="timeline-section">
|
||||||
|
<h3 class="timeline-title">发展里程</h3>
|
||||||
|
<div class="timeline-container">
|
||||||
|
<div class="timeline-line"></div>
|
||||||
|
|
||||||
|
<!-- 2016年8月 -->
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2016.08 <span class="short-desc">软件企业</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2016年8月</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>荣获"山东省软件企业"资质</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2017年5月 -->
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2017.05 <span class="short-desc">科技创新</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2017年5月</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>荣获"国家科技型创新企业"资质</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2017年10月 -->
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2017.10 <span class="short-desc">ISO认证</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2017年10月</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>ISO9001质量管理体系认证</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2017年12月 -->
|
||||||
|
<div class="timeline-item highlight">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2017.12 <span class="short-desc">锦江电商</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2017年12月</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>建设完成中日韩航线最大的电子商务平台-锦江航运电商平台</p>
|
||||||
|
<p>年线上交易额达到10亿元</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2018年5月 -->
|
||||||
|
<div class="timeline-item highlight">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2018.05 <span class="short-desc">云码头</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2018年5月</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>国内第一个自主研发的云码头平台在中山港航集团上线</p>
|
||||||
|
<p>建设运营成本仅为原有模式的10%,预计为全国码头节省建设成本近百亿</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2018年6月 -->
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2018.06 <span class="short-desc">技术研发</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2018年6月</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>荣获市级"基于新旧动能转换的港口物流信息管理智慧云平台的关键技术研发"三等奖</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2018年7月 -->
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2018.07 <span class="short-desc">多式联运</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2018年7月</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>实现侨益集团粮食物流公、铁、水多式联运信息化管理</p>
|
||||||
|
<p>打通其国际粮食进口、国内北粮南运信息化通道</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2018年8月 -->
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2018.08 <span class="short-desc">高新技术</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2018年8月</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>荣获"高新技术企业"资质</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2019年11月 -->
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2019.11 <span class="short-desc">省级项目</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2019年11月</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>承建两个山东省技术创新项目</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2019年 -->
|
||||||
|
<div class="timeline-item highlight">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2019 <span class="short-desc">国产替代</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2019年</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>打破港航软件长期依赖国外ORACLE数据库的现状</p>
|
||||||
|
<p>成功研发出基于国产数据库的"码头智能操作系统",解决国外"卡脖子"问题</p>
|
||||||
|
<p>大大提升了国家航运数据安全性</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2020年 -->
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2020 <span class="short-desc">创新创业</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2020年</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>荣获"第九届中国创新创业大赛(山东赛区)暨2020年山东省中小微企业创新竞技行动计划优胜企业"</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2020年6月 -->
|
||||||
|
<div class="timeline-item highlight">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2020.06 <span class="short-desc">一键通</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2020年6月</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>交付完成交通部十三五重点项目之一</p>
|
||||||
|
<p>京津冀协同下的"一键通"大宗干散货智慧物流示范工程</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2021年7月 -->
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2021.07 <span class="short-desc">研发中心</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2021年7月</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>荣获山东省"一企一技术"研发中心资源认证</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2022年6月 -->
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2022.06 <span class="short-desc">专精特新</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2022年6月</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>荣获山东省"专精特新"荣誉认证</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2023年7月 -->
|
||||||
|
<div class="timeline-item">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2023.07 <span class="short-desc">瞪羚企业</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2023年7月</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>荣获山东省"瞪羚企业"荣誉认证</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 2025年 -->
|
||||||
|
<div class="timeline-item highlight">
|
||||||
|
<div class="dot"></div>
|
||||||
|
<span class="year-label">2025 <span class="short-desc">AI智能</span></span>
|
||||||
|
<div class="content">
|
||||||
|
<span class="content-date">2025年</span>
|
||||||
|
<div class="content-text">
|
||||||
|
<p>省级工业互联网平台入库名单</p>
|
||||||
|
<p>"数字化智能供应链平台"成功跻身省级工业互联网平台行列</p>
|
||||||
|
<p>"基于大语言模型和机器人流程自动化技术的港口AI智能平台"强势入选山东省创新能力提升工程</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col col-xs-12">
|
<div class="col col-xs-12">
|
||||||
<div class="contact-form">
|
<div class="contact-form">
|
||||||
@@ -185,5 +397,6 @@
|
|||||||
|
|
||||||
<!-- Custom script for this template -->
|
<!-- Custom script for this template -->
|
||||||
<script src="assets/js/script.js"></script>
|
<script src="assets/js/script.js"></script>
|
||||||
|
<script src="assets/js/timeline.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||