|
|
<!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 href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
|
|
<link href="https://fonts.googleapis.com" rel="preconnect"/>
|
|
|
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
|
|
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;700;900&family=Liu Jian Mao Cao:wght@400;700&family=Montserrat:wght@400;500;700;800;900&family=Inter:wght@400;500;700;800;900&family=JetBrains+Mono:wght@500&display=swap" rel="stylesheet"/>
|
|
|
|
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/11.0.5/swiper-bundle.min.css" />
|
|
|
<!-- AOS Animation Library -->
|
|
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.css" rel="stylesheet">
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/vanilla-tilt/1.7.2/vanilla-tilt.min.js"></script>
|
|
|
<!-- Tailwind & Config -->
|
|
|
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
|
|
<script id="tailwind-config">
|
|
|
tailwind.config = {
|
|
|
darkMode: "class",
|
|
|
theme: {
|
|
|
extend: {
|
|
|
colors: {
|
|
|
"primary": "#13eca4",
|
|
|
"background-light": "#f8fcfa",
|
|
|
"background-dark": "#10221c",
|
|
|
"pearlescent": "#f0f7f5",
|
|
|
"silver-accent": "#e2e8f0",
|
|
|
"about-us": "#ff6b00",
|
|
|
"primary-dark": "#0da670", // Added for contrast on light mode
|
|
|
"accent": "#ff6b00"
|
|
|
},
|
|
|
fontFamily: {
|
|
|
"display": ["Montserrat", "sans-serif"],
|
|
|
"sans": ["Montserrat", "sans-serif"],
|
|
|
"mono": ["JetBrains Mono", "Montserrat"],
|
|
|
"inter": ["Inter", "Montserrat"],
|
|
|
},
|
|
|
borderRadius: {
|
|
|
"DEFAULT": "0.5rem",
|
|
|
"lg": "1rem",
|
|
|
"xl": "1.5rem",
|
|
|
"2xl": "2rem",
|
|
|
"3xl": "3rem",
|
|
|
"full": "9999px"
|
|
|
},
|
|
|
backgroundImage: {
|
|
|
'liquid-gradient': 'linear-gradient(135deg, #f8fcfa 0%, #e8f5f1 50%, #dcfce7 100%)',
|
|
|
'glass-gradient': 'linear-gradient(180deg, rgba(255, 255, 255, 0.6) 0%, rgba(255, 255, 255, 0.3) 100%)',
|
|
|
'aurora': 'linear-gradient(135deg, rgba(19,236,164,0.1) 0%, rgba(13,166,112,0.05) 50%, rgba(248,252,250,0) 100%)',
|
|
|
'mesh': 'radial-gradient(at 40% 20%, rgba(19,236,164,0.08) 0px, transparent 50%), radial-gradient(at 80% 0%, rgba(16,34,28,0.05) 0px, transparent 50%), radial-gradient(at 0% 50%, rgba(19,236,164,0.05) 0px, transparent 50%)',
|
|
|
|
|
|
},
|
|
|
boxShadow: {
|
|
|
// 将光效统一映射为 primary 颜色 (13eca4 的 RGBA)
|
|
|
'glow': '0 0 20px rgba(19, 236, 164, 0.4)',
|
|
|
'glow-lg': '0 10px 30px rgba(19, 236, 164, 0.4)',
|
|
|
'bento': '0 20px 40px -15px rgba(0,0,0,0.05), 0 0 0 1px rgba(0,0,0,0.02)',
|
|
|
'bento-hover': '0 30px 60px -20px rgba(19,236,164,0.15), 0 0 0 1px rgba(19,236,164,0.3)',
|
|
|
'bento-dark': '0 30px 60px -15px rgba(0,0,0,0.3), 0 0 0 1px rgba(255,255,255,0.1)',
|
|
|
},
|
|
|
keyframes: {
|
|
|
fadeIn: {
|
|
|
'0%': { opacity: '0', transform: 'translateY(10px)' },
|
|
|
'100%': { opacity: '1', transform: 'translateY(0)' },
|
|
|
},
|
|
|
scan: {
|
|
|
'0%': { top: '-10%', opacity: '0' },
|
|
|
'10%': { opacity: '1' },
|
|
|
'90%': { opacity: '1' },
|
|
|
'100%': { top: '110%', opacity: '0' },
|
|
|
},
|
|
|
rotateGlobe: {
|
|
|
'0%': { transform: 'rotate(0deg)' },
|
|
|
'100%': { transform: 'rotate(360deg)' },
|
|
|
},
|
|
|
dash: {
|
|
|
'0%': { strokeDashoffset: '1000' },
|
|
|
'100%': { strokeDashoffset: '0' },
|
|
|
},
|
|
|
globePulse: {
|
|
|
'0%': { boxShadow: '0 0 0px rgba(19,236,164,0)' },
|
|
|
'50%': { boxShadow: '0 0 50px rgba(19,236,164,0.4)', transform: 'scale(1.02)' },
|
|
|
'100%': { boxShadow: '0 0 0px rgba(19,236,164,0)' },
|
|
|
},
|
|
|
// 高级交互动画
|
|
|
pulseGlow: {
|
|
|
'0%': { textShadow: '0 0 10px rgba(19, 236, 164, 0.4)' },
|
|
|
'100%': { textShadow: '0 0 30px #ff6b00' }
|
|
|
},
|
|
|
sweep: { '100%': { left: '200%' } },
|
|
|
cardFlip: {
|
|
|
'0%': { opacity: '0', transform: 'rotateY(-90deg) translateZ(50px)' },
|
|
|
'100%': { opacity: '1', transform: 'rotateY(0deg) translateZ(0)' }
|
|
|
},
|
|
|
floatY: {
|
|
|
'0%, 100%': { transform: 'translateY(0)' },
|
|
|
'50%': { transform: 'translateY(-15px)' }
|
|
|
},
|
|
|
textShimmer: {
|
|
|
'0%': { backgroundPosition: '0% 50%' },
|
|
|
'100%': { backgroundPosition: '100% 50%' },
|
|
|
},
|
|
|
blobSpin: {
|
|
|
'0%': { transform: 'rotate(0deg) scale(1)' },
|
|
|
'50%': { transform: 'rotate(180deg) translate(-80%, 50%) scale(1.1)' },
|
|
|
'100%': { transform: 'rotate(360deg) translate(0) scale(1)' },
|
|
|
}
|
|
|
},
|
|
|
animation: {
|
|
|
'fade-in': 'fadeIn 0.5s ease-out forwards',
|
|
|
'scan-slow': 'scan 6s linear infinite',
|
|
|
'spin-slow': 'rotateGlobe 60s linear infinite',
|
|
|
'dash-flow': 'dash 3s linear infinite',
|
|
|
'globe-select': 'globePulse 0.8s ease-out',
|
|
|
'pulse-glow': 'pulseGlow 2s infinite alternate',
|
|
|
'sweep': 'sweep 3s infinite',
|
|
|
'flip-in': 'cardFlip 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards',
|
|
|
'float-1': 'floatY 3s ease-in-out infinite',
|
|
|
'float-2': 'floatY 3s ease-in-out infinite 1s',
|
|
|
'float-3': 'floatY 3s ease-in-out infinite 2s',
|
|
|
'text-shimmer': 'textShimmer 3s ease-out infinite alternate',
|
|
|
'blob-spin': 'blobSpin 20s infinite cubic-bezier(0.4, 0, 0.2, 1)',
|
|
|
}
|
|
|
},
|
|
|
},
|
|
|
}
|
|
|
</script>
|
|
|
<!-- Tailwind 基础样式注入 -->
|
|
|
<style type="text/tailwindcss">
|
|
|
|
|
|
@layer utilities {
|
|
|
/* contact us */
|
|
|
#contact-us .focus-group:hover > div:not(:hover) {
|
|
|
opacity: 0.6;
|
|
|
transform: scale(0.98);
|
|
|
filter: blur(2px);
|
|
|
}
|
|
|
#contact-us .focus-group > div {
|
|
|
transition: opacity 0.5s ease, transform 0.5s ease, filter 0.5s ease;
|
|
|
}
|
|
|
|
|
|
/* about-us */
|
|
|
/* 新增:专门为副标题定制的 3D 荧光挤压动画 */
|
|
|
.text-3d-subtitle {
|
|
|
color: #ff6b00; /* 保持主题色 */
|
|
|
animation: pulse3d 2s infinite alternate;
|
|
|
}
|
|
|
|
|
|
@keyframes pulse3d {
|
|
|
0% {
|
|
|
text-shadow:
|
|
|
/* 左上高光 */
|
|
|
-1px -1px 0px rgba(255, 255, 255, 0.5),
|
|
|
/* 右下厚度 (深翠绿色系) */
|
|
|
1px 1px 0px #ce6c33,
|
|
|
2px 2px 0px #b44914,
|
|
|
3px 3px 0px #75600a,
|
|
|
/* 基础投影 */
|
|
|
4px 4px 10px rgba(0, 0, 0, 0.6),
|
|
|
/* 较弱的呼吸背光 */
|
|
|
0px 0px 10px rgba(224, 114, 12, 0.3);
|
|
|
}
|
|
|
100% {
|
|
|
text-shadow:
|
|
|
-1px -1px 0px rgba(255, 255, 255, 0.7),
|
|
|
1px 1px 0px #cc7e19,
|
|
|
2px 2px 0px #e2d921,
|
|
|
3px 3px 0px #692a05,
|
|
|
5px 5px 15px rgba(0, 0, 0, 0.8),
|
|
|
/* 较强的呼吸背光,模拟能量溢出 */
|
|
|
0px 0px 30px #f2e930,
|
|
|
0px 0px 50px rgba(195, 159, 16, 0.6);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.text-3d {
|
|
|
text-shadow:
|
|
|
0 1px 0 #e2e8f0, /* 亮银色顶边 */
|
|
|
0 2px 0 #cbd5e1,
|
|
|
0 3px 0 #94a3b8,
|
|
|
0 4px 0 #64748b, /* 逐渐变暗模拟背光面 */
|
|
|
0 5px 0 #475569,
|
|
|
0 6px 0 #334155,
|
|
|
0 8px 10px rgba(0, 0, 0, 0.4), /* 近处接触阴影 */
|
|
|
0 15px 20px rgba(0, 0, 0, 0.3), /* 中距离扩散阴影 */
|
|
|
0 25px 40px rgba(0, 0, 0, 0.8); /* 远距离环境阴影 */
|
|
|
}
|
|
|
.-ultra {
|
|
|
color: #ffffff;
|
|
|
/* 1. 顶部左侧的亮色高光切割边 */
|
|
|
text-shadow:
|
|
|
-1px -1px 1px rgba(255, 255, 255, 0.3),
|
|
|
/* 2. 右下角 45度 斜向挤压厚度 (融入您的深墨绿环境色) */
|
|
|
1px 1px 0px #0d1e18,
|
|
|
2px 2px 0px #0a1813,
|
|
|
3px 3px 0px #08130e,
|
|
|
4px 4px 0px #060e0a,
|
|
|
5px 5px 0px #040906,
|
|
|
6px 6px 0px #020403,
|
|
|
7px 7px 0px #000000,
|
|
|
/* 3. 接触面的死黑投影 */
|
|
|
8px 8px 15px rgba(0, 0, 0, 0.8),
|
|
|
/* 4. 远距离大范围柔和投影 */
|
|
|
15px 15px 30px rgba(0, 0, 0, 0.6),
|
|
|
/* 5. 核心点睛之笔:在阴影反方向及底部映射出 #13eca4 (Primary) 的环境光晕 */
|
|
|
-5px -5px 30px rgba(19, 236, 164, 0.1),
|
|
|
10px 10px 40px rgba(19, 236, 164, 0.25);
|
|
|
}
|
|
|
/* Tab 状态管控:选中时变为 primary 背景与深色字体 */
|
|
|
|
|
|
#tech-landing-wrapper .tab-content { @apply hidden; }
|
|
|
#tech-landing-wrapper .tab-content.active { @apply grid; }
|
|
|
}
|
|
|
</style>
|
|
|
</head>
|
|
|
<style>
|
|
|
html {
|
|
|
scroll-behavior: auto !important;
|
|
|
}
|
|
|
a:hover {
|
|
|
color: transparent;
|
|
|
font-weight: normal;
|
|
|
}
|
|
|
::-webkit-scrollbar { width: 6px; height: 6px; }
|
|
|
::-webkit-scrollbar-track { background: transparent; }
|
|
|
::-webkit-scrollbar-thumb { background: rgba(19, 236, 164, 0.2); border-radius: 10px; }
|
|
|
::-webkit-scrollbar-thumb:hover { background: rgba(19, 236, 164, 0.4); }
|
|
|
|
|
|
/* [优化] 提升重绘性能的强制复合层 */
|
|
|
.liquid-blob { position: absolute; filter: blur(80px); z-index: 0; opacity: 0.6; will-change: transform; transform: translateZ(0); }
|
|
|
|
|
|
.globe-grid { background-image: radial-gradient(circle, rgba(19,236,164,0.1) 1px, transparent 1px); background-size: 20px 20px; }
|
|
|
.animate-select { animation: globePulse 0.6s ease-out; }
|
|
|
.hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
|
|
|
.hide-scrollbar::-webkit-scrollbar { display: none; }
|
|
|
|
|
|
.project-card.active { border-color: #13eca4; background: rgba(19, 236, 164, 0.1); }
|
|
|
|
|
|
.globe-dot.active .active-radar {
|
|
|
opacity: 1;
|
|
|
transform: scale(1);
|
|
|
animation: radarPulse 2s infinite ease-out;
|
|
|
}
|
|
|
.globe-dot.active .active-radar-2 {
|
|
|
opacity: 1;
|
|
|
transform: scale(1);
|
|
|
animation: radarPulse 2s infinite ease-out 0.4s;
|
|
|
}
|
|
|
.globe-dot.active .dot-core {
|
|
|
background-color: #13eca4;
|
|
|
box-shadow: 0 0 20px rgba(19, 236, 164, 0.9);
|
|
|
border: 2px solid white;
|
|
|
}
|
|
|
|
|
|
#dot-p2.active .dot-core { background-color: #60a5fa; box-shadow: 0 0 20px rgba(96, 165, 250, 0.9); }
|
|
|
#dot-p2.active .active-radar { border-color: rgba(96, 165, 250, 0.4); }
|
|
|
|
|
|
#dot-p4.active .dot-core { background-color: #fb923c; box-shadow: 0 0 20px rgba(251, 146, 60, 0.9); }
|
|
|
#dot-p4.active .active-radar { border-color: rgba(251, 146, 60, 0.4); }
|
|
|
|
|
|
@keyframes float-y {
|
|
|
0%, 100% { transform: translateY(0px); }
|
|
|
50% { transform: translateY(-20px); }
|
|
|
}
|
|
|
|
|
|
.animate-float-slow { animation: float-y 6s ease-in-out infinite; }
|
|
|
.animate-float-medium { animation: float-y 5s ease-in-out infinite 0.5s; }
|
|
|
.animate-float-fast { animation: float-y 7s ease-in-out infinite 1s; }
|
|
|
|
|
|
.group:hover .animate-float-slow,
|
|
|
.group:hover .animate-float-medium,
|
|
|
.group:hover .animate-float-fast {
|
|
|
animation-play-state: paused;
|
|
|
}
|
|
|
|
|
|
@keyframes radarPulse {
|
|
|
0% { transform: scale(0.5); opacity: 0; }
|
|
|
50% { opacity: 1; }
|
|
|
100% { transform: scale(1.8); opacity: 0; }
|
|
|
}
|
|
|
@keyframes scrollDown {
|
|
|
0% { transform: translateY(0); opacity: 1; }
|
|
|
100% { transform: translateY(12px); opacity: 0; }
|
|
|
}
|
|
|
|
|
|
#particle-canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 0; }
|
|
|
.cursor::after { content: '_'; animation: blink 1s infinite; color: #13eca4; }
|
|
|
@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
|
|
|
.hud-border { border: 1px solid rgba(19, 236, 164, 0.3); background: rgba(19, 236, 164, 0.05); }
|
|
|
|
|
|
.stack-card {
|
|
|
transform-origin: top;
|
|
|
will-change: transform;
|
|
|
}
|
|
|
.bg-parallax { translate: 0 -10%; will-change: transform; }
|
|
|
.card-overlay { will-change: opacity; }
|
|
|
</style>
|
|
|
|
|
|
<style>
|
|
|
|
|
|
.globe-module-wrapper {
|
|
|
position: relative; width: 100%; height: 85vh; min-height: 550px;
|
|
|
overflow: hidden; touch-action: pan-y;
|
|
|
}
|
|
|
|
|
|
#globe-container {
|
|
|
width: 100%; height: 100%; cursor: grab;
|
|
|
animation: canvasFadeIn 1.5s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
|
}
|
|
|
#globe-container:active { cursor: grabbing; }
|
|
|
|
|
|
/* [优化] 移除了致使滚动卡顿的 filter: blur(10px) 属性 */
|
|
|
@keyframes canvasFadeIn {
|
|
|
0% { opacity: 0; transform: scale(0.95) translateY(20px); }
|
|
|
100% { opacity: 1; transform: scale(1) translateY(0); }
|
|
|
}
|
|
|
|
|
|
.anchor-point { width: 0; height: 0; position: relative; }
|
|
|
|
|
|
.visibility-wrapper {
|
|
|
transition: opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1), transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
|
|
transform-origin: left center;
|
|
|
}
|
|
|
.visibility-wrapper.hud-hidden {
|
|
|
opacity: 0 !important; transform: scale(0.8) !important; pointer-events: none !important;
|
|
|
}
|
|
|
|
|
|
.hud-container {
|
|
|
position: absolute; left: 8px; top: 0; transform: translateY(-50%);
|
|
|
display: flex; align-items: center; z-index: 10; pointer-events: auto;
|
|
|
opacity: 0; animation: slideInFade 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
|
}
|
|
|
.hud-container:hover { z-index: 9999; }
|
|
|
|
|
|
@keyframes slideInFade {
|
|
|
0% { opacity: 0; margin-left: -8px; }
|
|
|
100% { opacity: 1; margin-left: 0; }
|
|
|
}
|
|
|
|
|
|
.hud-line { width: 16px; height: 1.5px; opacity: 0.7; }
|
|
|
|
|
|
.hud-card {
|
|
|
background: rgba(255, 255, 255, 0.6); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
|
|
|
padding: 4px 10px 4px 8px; border-radius: 6px;
|
|
|
border: 1px solid rgba(255, 255, 255, 0.8);
|
|
|
font-family: 'Inter', sans-serif; font-size: 11px; font-weight: 700;
|
|
|
display: flex; align-items: center; gap: 8px;
|
|
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.04), inset 0 0 0 1px rgba(255,255,255,0.4);
|
|
|
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1); cursor: pointer; white-space: nowrap;
|
|
|
}
|
|
|
.hud-container:hover .hud-card {
|
|
|
transform: translateX(4px); box-shadow: 0 12px 32px rgba(19, 236, 164, 0.15), inset 0 0 0 1px rgba(255,255,255,0.8);
|
|
|
background: rgba(255, 255, 255, 0.9);
|
|
|
}
|
|
|
|
|
|
.hint-fade-out {
|
|
|
opacity: 0 !important; transform: translateY(10px) scale(0.95) !important; pointer-events: none;
|
|
|
}
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
.globe-module-wrapper { height: 70vh; }
|
|
|
.hud-container { left: 4px; }
|
|
|
.hud-line { width: 8px; }
|
|
|
.hud-card { padding: 3px 8px 3px 6px; font-size: 9px; gap: 6px; }
|
|
|
.hud-card .tag { font-size: 7px !important; padding: 1px 4px !important; }
|
|
|
}
|
|
|
</style>
|
|
|
<body>
|
|
|
<div class="fixed inset-0 pointer-events-none overflow-hidden z-0">
|
|
|
<div class="liquid-blob bg-primary/20 w-[600px] h-[600px] rounded-full -top-40 -left-40"></div>
|
|
|
<div class="liquid-blob bg-blue-200/30 w-[500px] h-[500px] rounded-full top-1/3 -right-20"></div>
|
|
|
<div class="liquid-blob bg-teal-100/40 w-[800px] h-[800px] rounded-full -bottom-40 left-1/4"></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="relative z-[1] flex flex-col min-h-screen">
|
|
|
|
|
|
<!-- Hero Section -->
|
|
|
<section class="relative w-full h-[calc(100vh-60px)] md:h-[calc(100vh-80px)] min-h-[600px] overflow-hidden bg-[#f8fcfa] group/hero" id="hero-section">
|
|
|
|
|
|
<div class="swiper heroSwiper w-full h-full relative z-10">
|
|
|
<div class="swiper-wrapper">
|
|
|
<div class="swiper-slide bg-liquid-gradient relative overflow-hidden">
|
|
|
<div class="absolute inset-0 bg-mesh opacity-60 z-0"></div>
|
|
|
<div id="particle-canvas" class="relative z-10"></div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-t from-background-light via-transparent to-transparent z-20 pointer-events-none"></div>
|
|
|
|
|
|
<div class="absolute inset-0 z-30 flex flex-col justify-between p-10 md:p-20 pointer-events-none">
|
|
|
<header class="flex justify-between items-start">
|
|
|
<h1 class="text-4xl md:text-[2.66rem] tracking-tighter text-background-dark font-display">NENGHUI</h1>
|
|
|
<div class="hud-border border-primary/30 bg-primary/10 px-4 py-2 rounded font-mono text-xs text-background-dark hidden md:block backdrop-blur-sm">
|
|
|
CORE: <span class="text-primary font-bold">STABLE</span>
|
|
|
</div>
|
|
|
</header>
|
|
|
|
|
|
<div class="max-w-2xl">
|
|
|
<div class="bg-white/60 border border-primary/20 backdrop-blur-md px-6 py-2 rounded-full mb-6 inline-block shadow-[0_5px_15px_rgba(19,236,164,0.15)]">
|
|
|
<span class="font-mono text-sm tracking-widest text-background-dark uppercase cursor" id="hud-text">INIT_SYSTEM</span>
|
|
|
</div>
|
|
|
<h2 class="text-4xl md:text-[2.66rem] leading-[0.9] tracking-tighter mb-6 uppercase text-background-dark">
|
|
|
Energy<br><span class="text-transparent bg-clip-text bg-gradient-to-r from-primary to-teal-500 drop-shadow-sm">EMPOWERING.</span>
|
|
|
</h2>
|
|
|
<p class="text-[1rem] text-background-dark/70 max-w-md italic font-medium">Smart energy solutions for a sustainable and low-carbon future.</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="swiper-slide relative w-full h-full flex items-center justify-center overflow-hidden">
|
|
|
<div class="absolute inset-0 z-0 skeleton-wrapper skeleton-pulse ">
|
|
|
<div class="lazy-target w-full h-full bg-cover bg-center opacity-90 transition-transform duration-[10s] ease-linear scale-100 hover:scale-105"
|
|
|
data-bg="https://nenghui.com/wp-content/uploads/2026/03/home-banner-20260318.jpg" >
|
|
|
</div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-b from-white/60 via-transparent to-background-light"></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="relative z-10 max-w-[1000px] px-6 text-center flex flex-col items-center gap-3 md:gap-8" data-swiper-parallax="-300">
|
|
|
<h1 class="text-[#0d1b17] text-4xl md:text-[2.66rem] tracking-tighter">
|
|
|
ธุรกิจโรงไฟฟ้า PPA <br/>
|
|
|
<span class="italic font-light text-transparent bg-clip-text bg-gradient-to-r from-primary to-[#0d6efd]">ในประเทศไทย.</span>
|
|
|
</h1>
|
|
|
<p class="text-[#0d1b17]/80 text-[1rem] max-w-2xl backdrop-blur-sm">
|
|
|
ขอเชิญพันธมิตรผู้พัฒนาช่องทางธุรกิจร่วมเติบโตไปกับเรา.
|
|
|
</p>
|
|
|
<div class="flex flex-col sm:flex-row gap-4 mt-4">
|
|
|
<a href="/contact-us" class="flex h-12 px-8 items-center justify-center rounded-full bg-white/50 backdrop-blur-md text-[#0d1b17] border border-white/60 text-base font-medium hover:bg-white hover:scale-105 transition-all">
|
|
|
Contact Us
|
|
|
</a>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="swiper-slide relative w-full h-full flex items-center justify-center overflow-hidden">
|
|
|
<div class="absolute inset-0 z-0 skeleton-wrapper skeleton-pulse ">
|
|
|
<div class="lazy-target w-full h-full bg-cover bg-center opacity-90 transition-transform duration-[10s] ease-linear scale-100 hover:scale-105"
|
|
|
data-bg="https://nenghui.com/wp-content/uploads/2026/01/test-banner5.jpg" >
|
|
|
</div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-b from-white/60 via-transparent to-background-light"></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="relative z-10 max-w-[1000px] px-6 text-center flex flex-col items-center gap-3 md:gap-8" data-swiper-parallax="-300">
|
|
|
<h1 class="text-[#0d1b17] text-4xl md:text-[2.66rem] tracking-tighter">
|
|
|
Global Vision <br/>
|
|
|
<span class="italic font-light text-transparent bg-clip-text bg-gradient-to-r from-primary to-[#0d6efd]">Localized Performance.</span>
|
|
|
</h1>
|
|
|
<p class="text-[#0d1b17]/80 text-[1rem] max-w-2xl backdrop-blur-sm">
|
|
|
Engineering excellence meets on-site precision, Delivering integrated EPC solutions with global expertise.
|
|
|
</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="swiper-slide relative w-full h-full flex items-center justify-center overflow-hidden">
|
|
|
<div class="absolute inset-0 z-0 skeleton-wrapper skeleton-pulse ">
|
|
|
<div class="lazy-target w-full h-full bg-cover bg-center opacity-90 transition-transform duration-[10s] ease-linear scale-100 hover:scale-105"
|
|
|
data-bg="https://nenghui.com/wp-content/uploads/2026/01/test-banner3.jpg">
|
|
|
</div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-b from-white/60 via-transparent to-background-light"></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="relative z-10 max-w-[1000px] px-6 text-center flex flex-col items-center gap-3 md:gap-8" data-swiper-parallax="-300">
|
|
|
<h1 class="text-[#0d1b17] text-4xl md:text-[2.66rem] tracking-tighter">
|
|
|
Powering the AI-Driven <br/>
|
|
|
<span class="italic font-light text-transparent bg-clip-text bg-gradient-to-r from-primary to-[#0d6efd]">Energy Revolution.</span>
|
|
|
</h1>
|
|
|
<p class="text-[#0d1b17]/80 text-[1rem] max-w-2xl backdrop-blur-sm">
|
|
|
Next-Gen Energy Storage Solutions | EPC & EMC/PPA for a Sustainable Future.
|
|
|
</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="swiper-button-next !text-[#0d1b17]/10 hover:!text-primary !hidden md:!flex transition-opacity duration-300" id="hero-next"></div>
|
|
|
<div class="swiper-button-prev !text-[#0d1b17]/10 hover:!text-primary !hidden md:!flex transition-opacity duration-300" id="hero-prev"></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="absolute md:bottom-[5px] bottom-[14%] left-0 w-full flex justify-center z-30 pointer-events-none">
|
|
|
<div class="cursor-pointer pointer-events-auto animate-fade-in" onclick="document.getElementById('trust').scrollIntoView({behavior: 'smooth'})">
|
|
|
<div class="hidden md:flex flex-col items-center gap-3 group">
|
|
|
<span class="text-[10px] uppercase tracking-[0.2em] text-[#0d1b17]/60 group-hover:text-primary transition-colors duration-300">Scroll</span>
|
|
|
<div class="w-[26px] h-[42px] rounded-full border-2 border-[#0d1b17]/20 bg-white/10 backdrop-blur-sm flex justify-center p-1 shadow-sm group-hover:border-primary/50 transition-colors duration-300">
|
|
|
<div class="w-1 h-1.5 bg-primary rounded-full animate-[scrollDown_1.5s_infinite]"></div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="flex md:hidden flex-col items-center gap-1 opacity-70">
|
|
|
<span class="text-[9px] uppercase tracking-[0.15em] text-[#0d1b17]/60 mb-1">Swipe</span>
|
|
|
<div class="animate-bounce p-2 rounded-full bg-white/20 backdrop-blur-sm border border-white/10 shadow-sm">
|
|
|
<span class="material-symbols-outlined text-2xl text-[#0d1b17]"></span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</section>
|
|
|
|
|
|
<!-- Trust Stats Section -->
|
|
|
<section class="py-24 pb-40 relative" id="trust">
|
|
|
<div class="absolute top-1/2 left-0 w-full h-px bg-gradient-to-r from-transparent via-primary/20 to-transparent -translate-y-1/2 z-0 pointer-events-none"></div>
|
|
|
|
|
|
<div class="layout-container max-w-[1280px] mx-auto px-6 relative z-10">
|
|
|
<div class="mb-16 text-center" data-aos="fade-up">
|
|
|
<h3 class="text-4xl md:text-[2.66rem] text-[#0d1b17] mb-2">Powering the Planet</h3>
|
|
|
<p class="text-[#0d1b17]/60 text-[1rem]">Driving the transition with measurable impact.</p>
|
|
|
</div>
|
|
|
|
|
|
<div class="flex flex-wrap justify-center items-center gap-8 md:gap-16">
|
|
|
<div class="animate-float-slow group relative w-48 h-48 md:w-64 md:h-64 cursor-default" data-aos="fade-right" data-aos-delay="0">
|
|
|
<div class="absolute inset-0 bg-primary/20 rounded-full blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
|
|
|
<div class="relative w-full h-full rounded-full bg-white/60 backdrop-blur-xl border border-white/80 shadow-[0_8px_32px_rgba(0,0,0,0.05)] flex flex-col items-center justify-center transition-all duration-500 group-hover:scale-105 group-hover:border-primary/30 group-hover:shadow-[0_15px_40px_rgba(19,236,164,0.15)]">
|
|
|
<div class="absolute inset-2 rounded-full border border-dashed border-[#0d1b17]/10 w-[calc(100%-16px)] h-[calc(100%-16px)] animate-[spin_20s_linear_infinite] opacity-30 group-hover:opacity-60 transition-opacity"></div>
|
|
|
<p class="text-[#0d1b17]/60 text-[10px] md:text-xs uppercase tracking-widest mb-2 z-10">Technology Pioneer</p>
|
|
|
<h4 class="text-[#0d1b17] text-4xl md:text-5xl tracking-tight z-10 flex items-baseline">
|
|
|
<span class="counter" data-target="200">0</span>
|
|
|
<span class="text-2xl text-primary ml-1">+</span>
|
|
|
</h4>
|
|
|
<p class="text-[#0d1b17]/40 text-[10px] mt-1">Patents Granted</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="animate-float-medium group relative w-56 h-56 md:w-80 md:h-80 -my-4 md:-my-8 z-20 cursor-default" data-aos="zoom-in" data-aos-delay="100">
|
|
|
<div class="absolute inset-[-20px] rounded-full border border-primary/20 opacity-0 scale-90 group-hover:opacity-100 group-hover:scale-100 transition-all duration-700 ease-out"></div>
|
|
|
<div class="absolute inset-[-20px] rounded-full border-t border-primary/60 opacity-0 rotate-45 group-hover:opacity-100 group-hover:rotate-180 transition-all duration-1000 ease-out"></div>
|
|
|
<div class="relative w-full h-full rounded-full bg-gradient-to-b from-white to-[#f0f7f5] backdrop-blur-xl border-2 border-primary/10 shadow-[0_20px_50px_rgba(19,236,164,0.15)] flex flex-col items-center justify-center transition-all duration-500 group-hover:scale-105 group-hover:shadow-[0_30px_60px_rgba(19,236,164,0.25)]">
|
|
|
<div class="absolute w-32 h-32 bg-primary/10 rounded-full blur-2xl filter group-hover:bg-primary/20 transition-colors"></div>
|
|
|
<div class="relative z-10 text-center">
|
|
|
<span class="inline-block p-2 rounded-full bg-primary/10 text-primary mb-3">
|
|
|
<span class="material-symbols-outlined text-xl"></span>
|
|
|
</span>
|
|
|
<p class="text-[#0d1b17]/60 text-xs uppercase tracking-widest mb-1">Carbon Offset</p>
|
|
|
<h4 class="text-[#0d1b17] text-5xl md:text-7xl tracking-tight leading-none mb-1">
|
|
|
<span class="counter" data-target="10">0</span>
|
|
|
<span class="text-3xl md:text-4xl text-primary">GW</span>
|
|
|
</h4>
|
|
|
<p class="text-[#0d1b17]/50 text-xs">Clean Energy Delivered</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="animate-float-fast group relative w-48 h-48 md:w-64 md:h-64 cursor-default" data-aos="fade-left" data-aos-delay="200">
|
|
|
<div class="absolute inset-0 bg-blue-400/20 rounded-full blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
|
|
|
<div class="relative w-full h-full rounded-full bg-white/60 backdrop-blur-xl border border-white/80 shadow-[0_8px_32px_rgba(0,0,0,0.05)] flex flex-col items-center justify-center transition-all duration-500 group-hover:scale-105 group-hover:border-blue-400/30 group-hover:shadow-[0_15px_40px_rgba(96,165,250,0.15)]">
|
|
|
<div class="absolute inset-2 rounded-full border border-dashed border-[#0d1b17]/10 w-[calc(100%-16px)] h-[calc(100%-16px)] animate-[spin_25s_linear_infinite_reverse] opacity-30 group-hover:opacity-60 transition-opacity"></div>
|
|
|
<p class="text-[#0d1b17]/60 text-[10px] md:text-xs uppercase tracking-widest mb-2 z-10">EPC Portfolio</p>
|
|
|
<h4 class="text-[#0d1b17] text-4xl md:text-5xl tracking-tight z-10 flex items-baseline">
|
|
|
<span class="counter" data-target="1000">0</span>
|
|
|
<span class="text-2xl text-blue-500 ml-1">+</span>
|
|
|
</h4>
|
|
|
<p class="text-[#0d1b17]/40 text-[10px] mt-1">Projects Completed</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</section>
|
|
|
|
|
|
<!-- 堆叠滚动模块外层容器 -->
|
|
|
<section id="stacking-features" class="relative w-full text-white pb-[20vh]">
|
|
|
<div class="relative w-full mx-auto cursor-pointer">
|
|
|
|
|
|
<a href="/products/nh-ts-edb180-261/" class="stack-card sticky top-[0] flex items-center h-[100vh] w-full overflow-hidden border-t border-white/10 origin-top">
|
|
|
<div class="absolute inset-0 overflow-hidden z-0">
|
|
|
<div class="bg-parallax absolute w-full h-[120%] -top-[10%] bg-cover bg-center"
|
|
|
style="background-image: url('https://nenghui.com/wp-content/uploads/2026/03/NH-ICS180-261-3.jpg');">
|
|
|
</div>
|
|
|
<!-- 新增:移动端专属图片图层 -->
|
|
|
<div class="bg-parallax absolute w-full h-[100%] -top-[10%] bg-cover bg-center block md:hidden"
|
|
|
style="background-image: url('您的移动端图片链接1.jpg');">
|
|
|
</div>
|
|
|
<div class="absolute inset-0 bg-black/20"></div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-blue-500/10 opacity-50"></div>
|
|
|
<div class="card-overlay absolute inset-0 bg-black/80 opacity-0 pointer-events-none"></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="relative z-10 p-10 md:p-20 w-full md:w-2/3" data-tilt data-tilt-max="5" data-tilt-speed="400">
|
|
|
<div class="inline-block px-5 py-2 rounded-full bg-white/10 text-white font-mono text-sm mb-6 border border-white/20 backdrop-blur-md">
|
|
|
Smart Energy Storage Systems
|
|
|
</div>
|
|
|
<h3 class="text-4xl md:text-[2.66rem] mb-6 text-white drop-shadow-lg tracking-tight leading-none">
|
|
|
NH-TS-EDB180-261
|
|
|
</h3>
|
|
|
<p class="text-lg md:text-[1rem] text-gray-300 font-light leading-relaxed max-w-xl">
|
|
|
The NH-TS-EDB180-261 ESS Charger integrates high-capacity energy storage with ultra-fast EV charging in one compact system. Featuring 180kW max output, compatibility with diverse power environments.
|
|
|
</p>
|
|
|
</div>
|
|
|
</a>
|
|
|
|
|
|
<a href="/products/n20hc5000/" class="stack-card sticky top-[0] flex items-center h-[100vh] w-full overflow-hidden border-t border-white/10 origin-top">
|
|
|
<div class="absolute inset-0 overflow-hidden z-0">
|
|
|
<div class="bg-parallax absolute w-full h-[120%] -top-[10%] bg-cover bg-center"
|
|
|
style="background-image: url('https://nenghui.com/wp-content/uploads/2026/01/upload_1768961014.jpg');">
|
|
|
</div>
|
|
|
<div class="bg-parallax absolute w-full h-[100%] -top-[10%] bg-cover bg-center block md:hidden"
|
|
|
style="background-image: url('您的移动端图片链接1.jpg');">
|
|
|
</div>
|
|
|
<div class="absolute inset-0 bg-black/20"></div>
|
|
|
<div class="card-overlay absolute inset-0 bg-black/80 opacity-0 pointer-events-none"></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="relative z-10 p-10 md:p-20 w-full md:w-2/3 ml-auto text-right" data-tilt data-tilt-max="5" data-tilt-speed="400">
|
|
|
<div class="inline-block px-5 py-2 rounded-full bg-blue-500/20 text-blue-300 font-mono text-sm mb-6 border border-blue-500/30 backdrop-blur-md">
|
|
|
Smart Energy Storage Systems
|
|
|
</div>
|
|
|
<h3 class="text-4xl md:text-[2.66rem] mb-6 text-white drop-shadow-lg tracking-tight leading-none">
|
|
|
Liquid-cooled ESS Container 5MWh
|
|
|
</h3>
|
|
|
<p class="text-lg md:text-[1rem] text-gray-300 font-light leading-relaxed ml-auto max-w-xl">
|
|
|
Liquid-cooled thermal control ensures ±4°C cell uniformity, extending lifespan by 30% and achieving >95% efficiency for grid, solar, and industrial applications.
|
|
|
</p>
|
|
|
</div>
|
|
|
</a>
|
|
|
|
|
|
<a href="/epc-emc/" class="stack-card sticky top-[0] flex items-center h-[100vh] w-full overflow-hidden border-t border-white/10 origin-top">
|
|
|
<div class="absolute inset-0 overflow-hidden z-0">
|
|
|
<div class="bg-parallax absolute w-full h-[120%] -top-[10%] bg-cover bg-center"
|
|
|
style="background-image: url('https://nenghui.com/wp-content/uploads/2026/02/home-page-1');">
|
|
|
</div>
|
|
|
<div class="bg-parallax absolute w-full h-[100%] -top-[10%] bg-cover bg-center block md:hidden"
|
|
|
style="background-image: url('您的移动端图片链接1.jpg');">
|
|
|
</div>
|
|
|
<div class="absolute inset-0 bg-black/20"></div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-t from-black/80 to-transparent"></div>
|
|
|
<div class="card-overlay absolute inset-0 bg-black/80 opacity-0 pointer-events-none"></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="relative z-10 p-10 md:p-20 w-full md:w-2/3" data-tilt data-tilt-max="5" data-tilt-speed="400">
|
|
|
<div class="inline-block px-5 py-2 rounded-full bg-white/10 text-white font-mono text-sm mb-6 border border-white/20 backdrop-blur-md">
|
|
|
Turnkey Energy Services
|
|
|
</div>
|
|
|
<h3 class="text-4xl md:text-[2.66rem] mb-6 text-white tracking-tight leading-tight">
|
|
|
Turnkey Energy Services<br>(EPC & EMC/PPA)
|
|
|
</h3>
|
|
|
<p class="text-lg md:text-[1rem] text-gray-300 font-light leading-relaxed max-w-xl">
|
|
|
Comprehensive energy solutions from design to operation, ensuring sustainable growth and optimized energy investment.
|
|
|
</p>
|
|
|
</div>
|
|
|
</a>
|
|
|
|
|
|
<a href="/microgrid" class="stack-card sticky top-[0] flex items-center h-[100vh] w-full overflow-hidden border-t border-white/10 origin-top">
|
|
|
<div class="absolute inset-0 overflow-hidden z-0">
|
|
|
<div class="bg-parallax absolute w-full h-[120%] -top-[10%] bg-cover bg-center"
|
|
|
style="background-image: url('https://nenghui.com/wp-content/uploads/2026/03/home-microgrid.jpg');">
|
|
|
</div>
|
|
|
<div class="bg-parallax absolute w-full h-[100%] -top-[10%] bg-cover bg-center block md:hidden"
|
|
|
style="background-image: url('您的移动端图片链接1.jpg');">
|
|
|
</div>
|
|
|
<div class="absolute inset-0 bg-black/20"></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="relative z-10 p-10 md:p-20 w-full md:w-2/3 ml-auto text-right" data-tilt data-tilt-max="5" data-tilt-speed="400">
|
|
|
<div class="inline-block px-5 py-2 rounded-full bg-teal-500/20 text-teal-300 font-mono text-sm mb-6 border border-teal-500/30 backdrop-blur-md">
|
|
|
Microgrids
|
|
|
</div>
|
|
|
<h3 class="text-4xl md:text-[2.66rem] mb-6 text-white tracking-tight leading-tight">
|
|
|
Reliable Microgrid Solutions Engineering a Greener Grid
|
|
|
</h3>
|
|
|
<p class="text-lg md:text-[1rem] text-gray-300 font-light leading-relaxed ml-auto max-w-xl">
|
|
|
From industrial parks to remote islands, Nenghui delivers end-to-end Microgrid EPC services. Our systems optimize the synergy between PV and ESS, providing seamless power switching.
|
|
|
</p>
|
|
|
</div>
|
|
|
</a>
|
|
|
|
|
|
</div>
|
|
|
</section>
|
|
|
|
|
|
<!-- 全球站点 -->
|
|
|
<section class="globe-module-wrapper relative">
|
|
|
<div class="pointer-events-none absolute inset-0 z-20">
|
|
|
<div class="absolute top-5 left-5 md:top-10 md:left-10 bg-white/40 backdrop-blur-2xl p-4 md:p-6 rounded-2xl border border-white/60 shadow-[0_8px_32px_rgba(0,0,0,0.04)] border-l-4 border-l-primary pointer-events-auto" style="animation: canvasFadeIn 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards;">
|
|
|
<h1 class="text-2xl md:text-[2.66rem] text-background-dark tracking-tighter uppercase font-display">
|
|
|
Global <span class="text-primary">Network</span>
|
|
|
</h1>
|
|
|
<p class="text-[8px] md:text-[10px] text-background-dark/50 font-bold tracking-[0.2em] md:tracking-[0.35em] mt-1.5 uppercase font-sans">
|
|
|
Sustainable Energy Monitoring
|
|
|
</p>
|
|
|
</div>
|
|
|
|
|
|
<div class="absolute bottom-16 right-5 md:top-10 md:right-10 md:bottom-auto bg-white/50 backdrop-blur-2xl px-5 py-3 md:px-8 md:py-5 rounded-xl md:rounded-2xl border border-white/80 shadow-[0_8px_32px_rgba(0,0,0,0.04)] hover:shadow-[0_12px_40px_rgba(19,236,164,0.15)] transition-all duration-500 pointer-events-auto cursor-default" style="animation: canvasFadeIn 1.2s cubic-bezier(0.16, 1, 0.3, 1) forwards;">
|
|
|
<div class="flex items-center justify-between mb-1">
|
|
|
<p class="text-[8px] md:text-[10px] text-background-dark/50 font-bold uppercase tracking-widest font-sans">Active Stations</p>
|
|
|
<span class="relative flex h-2 w-2 ml-3">
|
|
|
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75"></span>
|
|
|
<span class="relative inline-flex rounded-full h-2 w-2 bg-primary"></span>
|
|
|
</span>
|
|
|
</div>
|
|
|
<div class="flex items-baseline gap-2">
|
|
|
<span id="active-regions-count" class="text-3xl md:text-5xl font-black text-background-dark font-display tracking-tighter">8</span>
|
|
|
<span class="text-[9px] md:text-xs font-bold text-primary uppercase tracking-wider font-sans">Regions Live</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="absolute bottom-3 inset-x-0 flex justify-center pointer-events-none" style="animation: canvasFadeIn 2s cubic-bezier(0.16, 1, 0.3, 1) forwards;">
|
|
|
<div id="drag-hint" class="bg-background-dark/80 backdrop-blur-md text-white px-5 py-2.5 rounded-full flex items-center justify-center gap-2 shadow-xl border border-white/10 transition-all duration-700 ease-out">
|
|
|
<span class="material-symbols-outlined text-[16px] animate-spin-slow" style="animation: spin 6s linear infinite;">360</span>
|
|
|
<span class="text-[10px] md:text-[11px] font-bold tracking-widest uppercase font-sans">Drag to Explore</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div id="globe-container"></div>
|
|
|
</section>
|
|
|
|
|
|
<!-- Why Us Section -->
|
|
|
<section class="py-24 relative overflow-hidden bg-gradient-to-b from-transparent to-[#f0f7f5]/50" id="tech">
|
|
|
<div class="absolute left-0 top-1/4 w-[500px] h-[500px] bg-primary/5 rounded-full blur-3xl -z-10"></div>
|
|
|
<div class="absolute right-0 bottom-0 w-[600px] h-[600px] bg-blue-100/20 rounded-full blur-3xl -z-10"></div>
|
|
|
|
|
|
<div class="layout-container max-w-[1280px] mx-auto px-6">
|
|
|
<div class="text-center max-w-4xl mx-auto mb-16" data-aos="fade-up">
|
|
|
<h2 class="text-4xl md:text-[2.66rem] text-[#0d1b17] leading-tight mb-6">
|
|
|
Why Partner with NENGHUI?
|
|
|
</h2>
|
|
|
<p class="text-[1rem] text-[#0d1b17]/70 leading-relaxed font-light">
|
|
|
Engineering trust through decades of expertise, design innovation, and global compliance.
|
|
|
</p>
|
|
|
</div>
|
|
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-6 gap-6">
|
|
|
<div class="lg:col-span-2 group relative rounded-[2.5rem] bg-[#0d1b17] text-white overflow-hidden p-8 flex flex-col hover:shadow-2xl transition-all duration-500" data-aos="fade-up" data-aos-delay="0">
|
|
|
<div class="absolute top-0 right-0 w-32 h-32 bg-white/5 rounded-full blur-2xl -mr-10 -mt-10"></div>
|
|
|
<div class="size-12 rounded-xl bg-white/10 flex items-center justify-center border border-white/10 mb-6 group-hover:scale-110 group-hover:bg-primary group-hover:text-[#0d1b17] transition-all duration-300">
|
|
|
<span class="material-symbols-outlined text-2xl"></span>
|
|
|
</div>
|
|
|
<h3 class="text-xl mb-3">Proven Delivery Excellence</h3>
|
|
|
<p class="text-white/70 text-sm leading-relaxed mb-4 flex-grow">
|
|
|
With years of consistent contract fulfillment and project execution, we ensure reliability in every commitment. Our robust operational capacity guarantees your energy transition is in safe hands.
|
|
|
</p>
|
|
|
<div class="mt-auto pt-4 border-t border-white/10">
|
|
|
<span class="text-[10px] tracking-widest text-primary uppercase">Reliable Execution</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="lg:col-span-2 group relative rounded-[2.5rem] bg-white border border-white/60 shadow-sm overflow-hidden p-8 flex flex-col hover:-translate-y-2 hover:shadow-xl transition-all duration-500" data-aos="fade-up" data-aos-delay="100">
|
|
|
<div class="absolute -right-10 -top-10 w-32 h-32 bg-blue-50 rounded-full blur-2xl group-hover:scale-150 transition-transform"></div>
|
|
|
<div class="size-12 rounded-xl bg-blue-50 text-blue-600 flex items-center justify-center mb-6 group-hover:scale-150 transition-transform duration-300">
|
|
|
<span class="material-symbols-outlined text-2xl"></span>
|
|
|
</div>
|
|
|
<h3 class="text-xl text-[#0d1b17] mb-3">
|
|
|
<span id="dynamic-years-title">16</span> Years of Technical Leadership
|
|
|
</h3>
|
|
|
<p class="text-[#0d1b17]/60 text-sm leading-relaxed mb-4 flex-grow">
|
|
|
Founded by a technical expert team, we have remained dedicated to the energy sector for <span id="dynamic-years-text" class=" text-[#0d1b17]">16</span> years. Our deep-rooted engineering DNA drives continuous innovation and professional rigor in everything we build.
|
|
|
</p>
|
|
|
<div class="mt-auto pt-4 border-t border-gray-100">
|
|
|
<span class="text-[10px] tracking-widest text-blue-600 uppercase">Since <span id="dynamic-years-value">2009</span></span>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="lg:col-span-2 group relative rounded-[2.5rem] bg-gradient-to-br from-primary/10 to-white border border-primary/20 shadow-sm overflow-hidden p-8 flex flex-col hover:-translate-y-2 hover:shadow-xl transition-all duration-500" data-aos="fade-up" data-aos-delay="200">
|
|
|
<div class="size-12 rounded-xl bg-white text-primary shadow-sm flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-300">
|
|
|
<span class="material-symbols-outlined text-2xl"></span>
|
|
|
</div>
|
|
|
<h3 class="text-xl text-[#0d1b17] mb-3">Design-Driven Evolution</h3>
|
|
|
<p class="text-[#0d1b17]/60 text-sm leading-relaxed mb-4 flex-grow">
|
|
|
Originating from the power industry, NENGHUI has evolved into a specialist in clean energy design and engineering. We provide high-value services, working heart-to-heart with global partners to create sustainable impact.
|
|
|
</p>
|
|
|
<div class="mt-auto pt-4 border-t border-primary/10">
|
|
|
<span class="text-[10px] tracking-widest text-primary uppercase">High-Value Services</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="lg:col-span-3 group relative rounded-[2.5rem] bg-white border border-gray-100 shadow-sm overflow-hidden p-8 flex flex-col md:flex-row items-center gap-8 hover:shadow-xl transition-all duration-500" data-aos="fade-up" data-aos-delay="400">
|
|
|
<div class="absolute -left-10 -bottom-10 w-40 h-40 bg-gray-50 rounded-full blur-2xl -z-10"></div>
|
|
|
<div class="flex-1 relative z-10">
|
|
|
<div class="size-12 rounded-xl bg-gray-100 text-gray-700 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform duration-300">
|
|
|
<span class="material-symbols-outlined text-2xl"></span>
|
|
|
</div>
|
|
|
<h3 class="text-xl text-[#0d1b17] mb-3">Certified Global Quality</h3>
|
|
|
<p class="text-[#0d1b17]/60 text-sm leading-relaxed">
|
|
|
Our products and processes meet stringent domestic and international standards. With comprehensive global certifications, we ensure seamless market entry and long-term operational safety across the world.
|
|
|
</p>
|
|
|
</div>
|
|
|
<div class="flex gap-3 flex-wrap justify-center md:justify-end w-full md:w-auto md:flex-col">
|
|
|
<div class="flex flex-col items-center gap-1 group/badge">
|
|
|
<div class="h-12 w-12 rounded-full border border-gray-100 bg-white shadow-sm flex items-center justify-center text-[10px] text-[#004084] group-hover/badge:-translate-y-1 transition-transform">TÜV</div>
|
|
|
<span class="text-[8px] text-gray-400 uppercase tracking-wider">Safety</span>
|
|
|
</div>
|
|
|
<div class="flex flex-col items-center gap-1 group/badge">
|
|
|
<div class="h-12 w-12 rounded-full border border-gray-100 bg-white shadow-sm flex items-center justify-center text-[10px] text-black group-hover/badge:-translate-y-1 transition-transform delay-75">CE</div>
|
|
|
<span class="text-[8px] text-gray-400 uppercase tracking-wider">EU Std</span>
|
|
|
</div>
|
|
|
<div class="flex flex-col items-center gap-1 group/badge">
|
|
|
<div class="h-12 w-12 rounded-full border border-gray-100 bg-white shadow-sm flex items-center justify-center text-[10px] text-[#D32026] group-hover/badge:-translate-y-1 transition-transform delay-150">UL</div>
|
|
|
<span class="text-[8px] text-gray-400 uppercase tracking-wider">US Std</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="lg:col-span-3 group relative rounded-[2.5rem] bg-[#f0f7f5] border border-white/60 shadow-sm overflow-hidden p-8 flex flex-col md:flex-row items-center gap-8 hover:shadow-xl transition-all duration-500" data-aos="fade-up" data-aos-delay="300">
|
|
|
<div class="flex-1 relative z-10 order-2 md:order-1">
|
|
|
<div class="size-12 rounded-xl bg-teal-100/50 text-teal-700 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform duration-300">
|
|
|
<span class="material-symbols-outlined text-2xl"></span>
|
|
|
</div>
|
|
|
<h3 class="text-xl text-[#0d1b17] mb-3">Tailored Multi-Scenario Solutions</h3>
|
|
|
<p class="text-[#0d1b17]/60 text-sm leading-relaxed">
|
|
|
We offer a full spectrum of energy assets, including Solar, ESS, and EV Charging infrastructure. From microgrids to grid-scale projects, our integrated "Solar + Storage + Charging" solutions meet diverse global demands
|
|
|
</p>
|
|
|
</div>
|
|
|
<div class="skeleton-wrapper skeleton-pulse w-full md:w-5/12 h-40 md:h-full min-h-[160px] relative rounded-2xl overflow-hidden shadow-sm group-hover:shadow-md transition-all duration-500 order-1 md:order-2">
|
|
|
<div class="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-110 lazy-target"
|
|
|
data-bg="https://nenghui.com/wp-content/uploads/2026/02/home-page-sun.avif"></div>
|
|
|
<div class="absolute inset-0 bg-teal-900/10 mix-blend-overlay"></div>
|
|
|
<div class="absolute bottom-2 left-2 bg-black/40 backdrop-blur-md px-2 py-1 rounded text-[9px] text-white uppercase">
|
|
|
Solar + Storage + Charging
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</section>
|
|
|
|
|
|
<!-- CASES -->
|
|
|
<section class="py-24 bg-[#f0f7f5]" id="impact-stories">
|
|
|
<div class="layout-container max-w-[96vw] mx-auto px-6">
|
|
|
|
|
|
<div class="flex justify-between items-center mb-12" data-aos="fade-right">
|
|
|
<h2 class="text-4xl md:text-[2.66rem] text-[#0d1b17]">Cases</h2>
|
|
|
|
|
|
<div class="flex gap-2">
|
|
|
|
|
|
<button class="swiper-custom-prev size-10 rounded-full border border-[#0d1b17]/10 flex items-center justify-center hover:bg-white transition-colors cursor-pointer group z-10">
|
|
|
<span class="material-symbols-outlined group-hover:-translate-x-0.5 transition-transform"></span>
|
|
|
</button>
|
|
|
|
|
|
<button class="swiper-custom-next size-10 rounded-full bg-[#0d1b17] text-white flex items-center justify-center hover:bg-primary hover:text-[#0d1b17] transition-colors cursor-pointer group z-10">
|
|
|
<span class="material-symbols-outlined group-hover:translate-x-0.5 transition-transform"></span>
|
|
|
</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="swiper impactSwiper w-full !pb-10" data-aos="zoom-in">
|
|
|
<div class="swiper-wrapper">
|
|
|
<div class="swiper-slide relative w-full h-[550px] rounded-3xl overflow-hidden shadow-xl group cursor-grab active:cursor-grabbing">
|
|
|
<div class="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-105"
|
|
|
style="background-image: url("https://nenghui.com/wp-content/uploads/2026/02/home-case-iraq.jpg")"
|
|
|
data-bg="https://nenghui.com/wp-content/uploads/2026/02/home-case-iraq.jpg"></div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent"></div>
|
|
|
<div class="absolute bottom-0 left-0 w-full p-8 md:p-10">
|
|
|
<div class="max-w-2xl">
|
|
|
<span class="text-primary text-sm uppercase tracking-widest mb-2 block">IRAQ BESS - 2025</span>
|
|
|
<h3 class="text-3xl text-white mb-4 line-clamp-2">Empowering Iraq’s Grid with Smart BESS Technology </h3>
|
|
|
<p class="text-gray-200 text-base mb-2 line-clamp-2">330kW/763kWh Turnkey EPC Project for Sustainable Industrial Power Management.</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="swiper-slide relative w-full h-[550px] rounded-3xl overflow-hidden shadow-xl group cursor-grab active:cursor-grabbing">
|
|
|
<div class="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-105"
|
|
|
style="background-image: url("https://nenghui.com/wp-content/uploads/2026/02/home-case-soar.jpg")"
|
|
|
data-bg="https://nenghui.com/wp-content/uploads/2026/02/home-case-soar.jpg"></div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent"></div>
|
|
|
<div class="absolute bottom-0 left-0 w-full p-8 md:p-10">
|
|
|
<div class="max-w-2xl">
|
|
|
<span class="text-primary text-sm uppercase tracking-widest mb-2 block">Excellence in Mountainous Solar Integration - 2024</span>
|
|
|
<h3 class="text-3xl text-white mb-4 line-clamp-2">Excellence in Mountainous Solar Integration </h3>
|
|
|
<p class="text-gray-200 text-base mb-2 line-clamp-2">This signature project by Shanghai Nenghui Technology showcases our end-to-end capability in mountainous solar. From sophisticated grid connection to resilient structural engineering, we ensure long-term reliability in every peak we power.</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="swiper-slide relative w-full h-[550px] rounded-3xl overflow-hidden shadow-xl group cursor-grab active:cursor-grabbing">
|
|
|
<div class="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-105"
|
|
|
style="background-image: url("https://nenghui.com/wp-content/uploads/2026/02/home-case-arid.jpg")"
|
|
|
data-bg="https://nenghui.com/wp-content/uploads/2026/02/home-case-arid.jpg"></div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent"></div>
|
|
|
<div class="absolute bottom-0 left-0 w-full p-8 md:p-10">
|
|
|
<div class="max-w-2xl">
|
|
|
<span class="text-primary text-sm uppercase tracking-widest mb-2 block">We Power the Arid Frontier - 2023</span>
|
|
|
<h3 class="text-3xl text-white mb-4 line-clamp-2">Innovative solar solutions tailored for the most demanding climates.</h3>
|
|
|
<p class="text-gray-200 text-base mb-2 line-clamp-2">This landmark project showcases our ability to design and maintain high-efficiency PV plants in sandy and rocky deserts, setting a new benchmark for utility-scale solar.</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="swiper-slide relative w-full h-[550px] rounded-3xl overflow-hidden shadow-xl group cursor-grab active:cursor-grabbing">
|
|
|
<div class="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-105"
|
|
|
style="background-image: url("https://nenghui.com/wp-content/uploads/2026/02/home-case-zhuhai.jpg")"
|
|
|
data-bg="https://nenghui.com/wp-content/uploads/2026/02/home-case-zhuhai.jpg"></div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent"></div>
|
|
|
<div class="absolute bottom-0 left-0 w-full p-8 md:p-10">
|
|
|
<div class="max-w-2xl">
|
|
|
<span class="text-primary text-sm uppercase tracking-widest mb-2 block">Commercial ESS Project - 2019</span>
|
|
|
<h3 class="text-3xl text-white mb-4 line-clamp-2">Smart Energy, Zero Investment </h3>
|
|
|
<p class="text-gray-200 text-base mb-2 line-clamp-2">NENGHUI-funded energy storage featuring smart C&I integration and lifetime performance guarantee.</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="swiper-slide relative w-full h-[550px] rounded-3xl overflow-hidden shadow-xl group cursor-grab active:cursor-grabbing">
|
|
|
<div class="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-105"
|
|
|
style="background-image: url("https://nenghui.com/wp-content/uploads/2026/02/home-case-zongcheng.jpg")"
|
|
|
data-bg="https://nenghui.com/wp-content/uploads/2026/02/home-case-zongcheng.jpg"></div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent"></div>
|
|
|
<div class="absolute bottom-0 left-0 w-full p-8 md:p-10">
|
|
|
<div class="max-w-2xl">
|
|
|
<span class="text-primary text-sm uppercase tracking-widest mb-2 block">Next-Gen EV Heavy Truck Powertrain - 2025</span>
|
|
|
<h3 class="text-3xl text-white mb-4 line-clamp-2">Pioneering Core Technology Breakthroughs</h3>
|
|
|
<p class="text-gray-200 text-base mb-2 line-clamp-2">Delivering high-performance powertrain systems through intelligent manufacturing and advanced engineering.</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="swiper-slide relative w-full h-[550px] rounded-3xl overflow-hidden shadow-xl group cursor-grab active:cursor-grabbing">
|
|
|
<div class="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-105"
|
|
|
style="background-image: url("https://nenghui.com/wp-content/uploads/2026/02/home-case-qinzhou.jpg")"
|
|
|
data-bg="https://nenghui.com/wp-content/uploads/2026/02/home-case-qinzhou.jpg"></div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent"></div>
|
|
|
<div class="absolute bottom-0 left-0 w-full p-8 md:p-10">
|
|
|
<div class="max-w-2xl">
|
|
|
<span class="text-primary text-sm uppercase tracking-widest mb-2 block">Qinzhou 20MWp Fishing-Solar Hybrid Project - 2023</span>
|
|
|
<h3 class="text-3xl text-white mb-4 line-clamp-2">Sustainable Synergy of Energy & Aquaculture</h3>
|
|
|
<p class="text-gray-200 text-base mb-2 line-clamp-2">A premier EPC turnkey solution integrating high-efficiency PV arrays with modern fishery ecosystems.</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="swiper-slide relative w-full h-[550px] rounded-3xl overflow-hidden shadow-xl group cursor-grab active:cursor-grabbing">
|
|
|
<div class="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-105"
|
|
|
style="background-image: url("https://nenghui.com/wp-content/uploads/2026/02/home-case-hybird.jpg")"
|
|
|
data-bg="https://nenghui.com/wp-content/uploads/2026/02/home-case-hybird.jpg"></div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent"></div>
|
|
|
<div class="absolute bottom-0 left-0 w-full p-8 md:p-10">
|
|
|
<div class="max-w-2xl">
|
|
|
<span class="text-primary text-sm uppercase tracking-widest mb-2 block">Innovative Agri-Solar Hybrid Project - 2024</span>
|
|
|
<h3 class="text-3xl text-white mb-4 line-clamp-2">Harmony of Energy & Agriculture</h3>
|
|
|
<p class="text-gray-200 text-base mb-2 line-clamp-2">A high-efficiency EPC solution maximizing land value through integrated solar power and sustainable forestry.</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="swiper-slide relative w-full h-[550px] rounded-3xl overflow-hidden shadow-xl group cursor-grab active:cursor-grabbing">
|
|
|
<div class="absolute inset-0 bg-cover bg-center transition-transform duration-700 group-hover:scale-105"
|
|
|
style="background-image: url("https://nenghui.com/wp-content/uploads/2026/02/home-case-120mw.png")"
|
|
|
data-bg="https://nenghui.com/wp-content/uploads/2026/02/home-case-120mw.png"></div>
|
|
|
<div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent"></div>
|
|
|
<div class="absolute bottom-0 left-0 w-full p-8 md:p-10">
|
|
|
<div class="max-w-2xl">
|
|
|
<span class="text-primary text-sm uppercase tracking-widest mb-2 block">120MWp Integrated Agrivoltaic Project - 2025</span>
|
|
|
<h3 class="text-3xl text-white mb-4 line-clamp-2">Excellence in EPC Delivery</h3>
|
|
|
<p class="text-gray-200 text-base mb-2 line-clamp-2">A premier subsidized PV development featuring high-standard equipment and rigorous execution within Guizhou's premier million-kilowatt solar cluster.</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</section>
|
|
|
<section class="py-24 bg-gradient-to-b from-white to-[#f0f7f5] border-t border-gray-100" id="compliance">
|
|
|
<div class="layout-container max-w-[1280px] mx-auto px-6 text-center">
|
|
|
<div class="max-w-3xl mx-auto mb-20" data-aos="fade-up">
|
|
|
<h2 class="text-4xl md:text-[2.66rem] text-[#0d1b17] mb-4 tracking-tight">
|
|
|
Certified Reliability, Global Compliance
|
|
|
</h2>
|
|
|
<p class="text-[#0d1b17]/60 text-[1rem] font-light ">
|
|
|
Upholding the world’s most stringent standards for safety, quality, and environmental stewardship.
|
|
|
</p>
|
|
|
</div>
|
|
|
|
|
|
<div class="grid grid-cols-2 md:grid-cols-5 gap-12 md:gap-8 items-end justify-items-center">
|
|
|
|
|
|
<div class="group flex flex-col items-center justify-end h-32 w-full cursor-default" data-aos="fade-up" data-aos-delay="0">
|
|
|
<div class="transition-all duration-300 ease-out group-hover:scale-110 group-hover:-translate-y-2 group-hover:drop-shadow-[0_10px_20px_rgba(0,64,132,0.25)]">
|
|
|
<span class="font-display text-5xl text-[#004084] tracking-tighter">TÜV</span>
|
|
|
</div>
|
|
|
<div class="h-6 mt-4 overflow-hidden">
|
|
|
<span class="block text-[10px] uppercase tracking-widest text-[#004084]/80 opacity-0 translate-y-4 transition-all duration-500 group-hover:opacity-100 group-hover:translate-y-0">
|
|
|
Safety Tested
|
|
|
</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="group flex flex-col items-center justify-end h-32 w-full cursor-default" data-aos="fade-up" data-aos-delay="100">
|
|
|
<div class="w-full flex justify-center transition-all duration-300 ease-out group-hover:scale-110 group-hover:-translate-y-2 group-hover:drop-shadow-[0_10px_20px_rgba(0,0,0,0.15)]">
|
|
|
<svg height="50" viewBox="0 0 52 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
|
<path d="M 16 8 A 12 12 0 1 0 16 32" stroke="#0d1b17" stroke-width="5" stroke-linecap="butt" />
|
|
|
<path d="M 42 8 A 12 12 0 1 0 42 32" stroke="#0d1b17" stroke-width="5" stroke-linecap="butt" />
|
|
|
<path d="M 30 20 L 41 20" stroke="#0d1b17" stroke-width="5" stroke-linecap="butt" />
|
|
|
</svg>
|
|
|
</div>
|
|
|
<div class="h-6 mt-4 w-full overflow-hidden text-center">
|
|
|
<span class="inline-block text-[10px] uppercase tracking-widest text-black/80 opacity-0 translate-y-4 transition-all duration-500 group-hover:opacity-100 group-hover:translate-y-0">
|
|
|
European Std.
|
|
|
</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="group flex flex-col items-center justify-end h-32 w-full cursor-default" data-aos="fade-up" data-aos-delay="200">
|
|
|
<div class="transition-all duration-300 ease-out group-hover:scale-110 group-hover:-translate-y-2 group-hover:drop-shadow-[0_10px_20px_rgba(211,32,38,0.25)]">
|
|
|
<div class="size-14 rounded-full border-[4px] border-[#D32026] flex items-center justify-center relative bg-white">
|
|
|
<span class="font-display text-3xl text-[#D32026] relative top-[2px] right-[1px] leading-none">UL</span>
|
|
|
<span class="absolute -bottom-1 -right-2 text-[8px] text-[#D32026]">®</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="h-6 mt-4 overflow-hidden">
|
|
|
<span class="block text-[10px] uppercase tracking-widest text-[#D32026]/80 opacity-0 translate-y-4 transition-all duration-500 group-hover:opacity-100 group-hover:translate-y-0">
|
|
|
US Safety
|
|
|
</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="group flex flex-col items-center justify-end h-32 w-full cursor-default" data-aos="fade-up" data-aos-delay="300">
|
|
|
<div class="transition-all duration-300 ease-out group-hover:scale-110 group-hover:-translate-y-2 group-hover:drop-shadow-[0_10px_20px_rgba(0,85,140,0.25)]">
|
|
|
<span class="font-display text-5xl text-[#00558C] tracking-wide">IEC</span>
|
|
|
</div>
|
|
|
<div class="h-6 mt-4 overflow-hidden">
|
|
|
<span class="block text-[10px] uppercase tracking-widest text-[#00558C]/80 opacity-0 translate-y-4 transition-all duration-500 group-hover:opacity-100 group-hover:translate-y-0">
|
|
|
Electrotechnical
|
|
|
</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="group flex flex-col items-center justify-end h-32 w-full cursor-default" data-aos="fade-up" data-aos-delay="400">
|
|
|
<div class="transition-all duration-300 ease-out group-hover:scale-110 group-hover:-translate-y-2 group-hover:drop-shadow-[0_10px_20px_rgba(30,30,30,0.2)]">
|
|
|
<span class="font-display text-5xl text-[#333] tracking-tight">ISO</span>
|
|
|
</div>
|
|
|
<div class="h-6 mt-4 overflow-hidden">
|
|
|
<span class="block text-[10px] uppercase tracking-widest text-[#333]/80 opacity-0 translate-y-4 transition-all duration-500 group-hover:opacity-100 group-hover:translate-y-0">
|
|
|
9001 / 14001 / 45001
|
|
|
</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
</section>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.js"></script>
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/11.0.5/swiper-bundle.min.js"></script>
|
|
|
|
|
|
<script>
|
|
|
|
|
|
function calcYear () {
|
|
|
const valEl = document.getElementById('dynamic-years-value');
|
|
|
if(!valEl) return;
|
|
|
const startYear = Number(valEl.innerText);
|
|
|
const currentYear = new Date().getFullYear();
|
|
|
const yearsOperation = currentYear - startYear;
|
|
|
|
|
|
const titleEl = document.getElementById('dynamic-years-title');
|
|
|
if (titleEl) titleEl.innerText = yearsOperation;
|
|
|
|
|
|
const textEl = document.getElementById('dynamic-years-text');
|
|
|
if (textEl) textEl.innerText = yearsOperation;
|
|
|
}
|
|
|
|
|
|
const counters = document.querySelectorAll('.counter');
|
|
|
|
|
|
// [优化] 将低效的 setTimeout 替换成了使用 requestAnimationFrame 实现的平滑过渡动画
|
|
|
const animateCounters = () => {
|
|
|
counters.forEach(counter => {
|
|
|
const target = +counter.getAttribute('data-target');
|
|
|
const duration = 2000;
|
|
|
const start = performance.now();
|
|
|
|
|
|
const updateCount = (currentTime) => {
|
|
|
const elapsed = currentTime - start;
|
|
|
const progress = Math.min(1, elapsed / duration);
|
|
|
const easeProgress = 1 - Math.pow(1 - progress, 4);
|
|
|
|
|
|
counter.innerText = Math.ceil(easeProgress * target);
|
|
|
|
|
|
if (progress < 1) {
|
|
|
requestAnimationFrame(updateCount);
|
|
|
} else {
|
|
|
counter.innerText = target;
|
|
|
}
|
|
|
};
|
|
|
requestAnimationFrame(updateCount);
|
|
|
});
|
|
|
};
|
|
|
|
|
|
let hasAnimated = false;
|
|
|
const section = document.querySelector('#trust');
|
|
|
const observer = new IntersectionObserver((entries) => {
|
|
|
if(entries[0].isIntersecting && !hasAnimated) {
|
|
|
animateCounters();
|
|
|
hasAnimated = true;
|
|
|
}
|
|
|
}, { threshold: 0.5 });
|
|
|
|
|
|
if(section) observer.observe(section);
|
|
|
|
|
|
var heroSwiper = new Swiper(".heroSwiper", {
|
|
|
loop: true,
|
|
|
speed: 1000,
|
|
|
parallax: true,
|
|
|
effect: 'fade',
|
|
|
fadeEffect: { crossFade: true },
|
|
|
autoplay: {
|
|
|
delay: 6000,
|
|
|
disableOnInteraction: false,
|
|
|
},
|
|
|
pagination: {
|
|
|
el: ".swiper-pagination",
|
|
|
clickable: true,
|
|
|
renderBullet: function (index, className) {
|
|
|
return '<span class="' + className + ' !bg-primary"></span>';
|
|
|
},
|
|
|
},
|
|
|
navigation: {
|
|
|
nextEl: ".swiper-button-next",
|
|
|
prevEl: ".swiper-button-prev",
|
|
|
},
|
|
|
});
|
|
|
|
|
|
class AdvancedImageLoader1 {
|
|
|
constructor(options = {}) {
|
|
|
this.options = Object.assign({
|
|
|
rootMargin: '200px 0px',
|
|
|
threshold: 0.01,
|
|
|
selector: '.lazy-target',
|
|
|
skeletonClass: 'skeleton-pulse',
|
|
|
loadedClass: 'loaded',
|
|
|
}, options);
|
|
|
|
|
|
this.observer = null;
|
|
|
this.init();
|
|
|
}
|
|
|
|
|
|
init() {
|
|
|
if ('IntersectionObserver' in window) {
|
|
|
this.observer = new IntersectionObserver((entries, observer) => {
|
|
|
entries.forEach(entry => {
|
|
|
if (entry.isIntersecting) {
|
|
|
this.loadImage(entry.target);
|
|
|
observer.unobserve(entry.target);
|
|
|
}
|
|
|
});
|
|
|
}, { rootMargin: this.options.rootMargin, threshold: this.options.threshold });
|
|
|
}
|
|
|
this.scan();
|
|
|
}
|
|
|
|
|
|
scan() {
|
|
|
const elements = document.querySelectorAll(`${this.options.selector}:not(.${this.options.loadedClass})`);
|
|
|
elements.forEach(el => {
|
|
|
if (!this.observer) this.loadImage(el);
|
|
|
else this.observer.observe(el);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
loadImage(el) {
|
|
|
const bgSrc = el.getAttribute('data-bg');
|
|
|
const imgSrc = el.getAttribute('data-src');
|
|
|
const skeleton = el.closest('.skeleton-wrapper');
|
|
|
|
|
|
if (!bgSrc && !imgSrc) return;
|
|
|
|
|
|
const loader = new Image();
|
|
|
loader.onload = () => {
|
|
|
if (bgSrc) el.style.backgroundImage = `url("${bgSrc}")`;
|
|
|
if (imgSrc) el.setAttribute('src', imgSrc);
|
|
|
requestAnimationFrame(() => el.classList.add(this.options.loadedClass));
|
|
|
if (skeleton) skeleton.classList.remove(this.options.skeletonClass);
|
|
|
};
|
|
|
loader.onerror = () => {
|
|
|
if (skeleton) skeleton.classList.remove(this.options.skeletonClass);
|
|
|
};
|
|
|
loader.src = bgSrc || imgSrc;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
window.addEventListener('load', () => {
|
|
|
|
|
|
calcYear();
|
|
|
window.ImageLoader = new AdvancedImageLoader1();
|
|
|
|
|
|
var swiper = new Swiper(".impactSwiper", {
|
|
|
loop: true,
|
|
|
slidesPerView: 1,
|
|
|
spaceBetween: 10,
|
|
|
speed: 800,
|
|
|
effect: 'slide',
|
|
|
autoplay: {
|
|
|
delay: 5000,
|
|
|
disableOnInteraction: false,
|
|
|
pauseOnMouseEnter: true,
|
|
|
},
|
|
|
navigation: {
|
|
|
nextEl: ".swiper-custom-next",
|
|
|
prevEl: ".swiper-custom-prev",
|
|
|
},
|
|
|
breakpoints: {
|
|
|
768: {
|
|
|
slidesPerView: 2,
|
|
|
spaceBetween: 24,
|
|
|
},
|
|
|
1024: {
|
|
|
slidesPerView: 3,
|
|
|
spaceBetween: 30,
|
|
|
}
|
|
|
},
|
|
|
keyboard: { enabled: true },
|
|
|
observer: true,
|
|
|
observeParents: true,
|
|
|
on: {
|
|
|
init: function () {
|
|
|
this.update();
|
|
|
this.autoplay.start();
|
|
|
},
|
|
|
}
|
|
|
});
|
|
|
|
|
|
AOS.init({ duration: 900, easing: 'ease-out-cubic', once: true, offset: 50 });
|
|
|
});
|
|
|
</script>
|
|
|
<script src="https://nenghui.com/wp-content/themes/nenghui-energy-theme-4/assets/js/globe.2.32.2.min.js"></script>
|
|
|
<script src="https://nenghui.com/wp-content/themes/nenghui-energy-theme-4/assets/js/lenis.1.0.39.min.js"></script>
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.160.0/three.min.js">
|
|
|
|
|
|
</script>
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
|
|
|
|
|
|
<script id="vertexShader" type="x-shader/x-vertex">
|
|
|
attribute vec3 targetPosition;
|
|
|
attribute vec3 targetColor;
|
|
|
varying vec3 vColor;
|
|
|
uniform float uProgress;
|
|
|
uniform float uTime;
|
|
|
|
|
|
vec3 rotatePoint(vec3 p, float angle, float cy) {
|
|
|
float s = sin(angle);
|
|
|
float c = cos(angle);
|
|
|
float tx = p.x;
|
|
|
float ty = p.y - cy;
|
|
|
return vec3(tx * c - ty * s, tx * s + ty * c + cy, (fract(p.x * 123.456) - 0.5) * 5.0);
|
|
|
}
|
|
|
|
|
|
void main() {
|
|
|
vColor = mix(vec3(0.07, 0.92, 0.64), targetColor, uProgress);
|
|
|
|
|
|
float rotorY = 120.0;
|
|
|
float angle = uTime * 4.0;
|
|
|
|
|
|
vec3 pOrigin = position;
|
|
|
if (abs(position.z - 999.9) < 0.1) {
|
|
|
pOrigin = rotatePoint(position, angle, rotorY);
|
|
|
}
|
|
|
|
|
|
vec3 pTarget = targetPosition;
|
|
|
if (abs(targetPosition.z - 999.9) < 0.1) {
|
|
|
pTarget = rotatePoint(targetPosition, angle, rotorY);
|
|
|
}
|
|
|
|
|
|
vec3 pos = mix(pOrigin, pTarget, uProgress);
|
|
|
pos.y += sin(uTime * 1.5 + position.x * 0.02) * 2.0;
|
|
|
|
|
|
vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
|
|
|
gl_PointSize = 4.5 * (400.0 / -mvPosition.z);
|
|
|
gl_Position = projectionMatrix * mvPosition;
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<script id="fragmentShader" type="x-shader/x-fragment">
|
|
|
varying vec3 vColor;
|
|
|
void main() {
|
|
|
float d = distance(gl_PointCoord, vec2(0.5));
|
|
|
if (d > 0.5) discard;
|
|
|
float alpha = smoothstep(0.5, 0.1, d) * 0.85;
|
|
|
gl_FragColor = vec4(vColor, alpha);
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<script>
|
|
|
const scene = new THREE.Scene();
|
|
|
const camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.innerHeight, 1, 2000);
|
|
|
camera.position.set(0, -20, 450);
|
|
|
|
|
|
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
|
|
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
|
|
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
|
|
document.getElementById('particle-canvas').appendChild(renderer.domElement);
|
|
|
|
|
|
const particleCount = 20000;
|
|
|
const colorMain = new THREE.Color(0x13eca4);
|
|
|
const colorText = new THREE.Color('#10d292');
|
|
|
|
|
|
const ShapeLib = {
|
|
|
fill: (pts) => {
|
|
|
const posArr = new Float32Array(particleCount * 3);
|
|
|
const colArr = new Float32Array(particleCount * 3);
|
|
|
for(let i=0; i<particleCount; i++) {
|
|
|
const p = pts[i % pts.length];
|
|
|
posArr[i*3] = p.x; posArr[i*3+1] = p.y; posArr[i*3+2] = p.z;
|
|
|
const c = p.c || colorMain;
|
|
|
colArr[i*3] = c.r; colArr[i*3+1] = c.g; colArr[i*3+2] = c.b;
|
|
|
}
|
|
|
return { pos: posArr, col: colArr };
|
|
|
},
|
|
|
generateLogoPts: (offsetX, offsetY, scale) => {
|
|
|
const pts = [];
|
|
|
const canvas = document.createElement('canvas');
|
|
|
const ctx = canvas.getContext('2d');
|
|
|
canvas.width = 200; canvas.height = 40;
|
|
|
ctx.font = 'bold 30px Arial';
|
|
|
ctx.fillStyle = 'white';
|
|
|
ctx.fillText('NENGHUI', 10, 30);
|
|
|
const data = ctx.getImageData(0,0,200,40).data;
|
|
|
for(let y=0; y<40; y+=2) {
|
|
|
for(let x=0; x<200; x+=2) {
|
|
|
if(data[(y*200+x)*4] > 128) {
|
|
|
pts.push({ x: (x - 100) * scale + offsetX, y: -(y - 20) * scale + offsetY, z: 41, c: colorText });
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return pts;
|
|
|
},
|
|
|
text: () => {
|
|
|
const canvas = document.createElement('canvas'); canvas.width = 1000; canvas.height = 200;
|
|
|
const ctx = canvas.getContext('2d');
|
|
|
ctx.font = 'bold 160px "Space Grotesk"'; ctx.fillStyle = 'white'; ctx.textAlign = 'center';
|
|
|
ctx.fillText('NENGHUI', 500, 140);
|
|
|
const data = ctx.getImageData(0,0,1000,200).data;
|
|
|
const pts = [];
|
|
|
for(let y=0; y<200; y+=3) for(let x=0; x<1000; x+=3) {
|
|
|
if(data[(y*1000+x)*4] > 128) pts.push({ x: (x-500)*0.8, y: -(y-100)*0.8, z: (Math.random()-0.5)*15, c: colorMain });
|
|
|
}
|
|
|
return ShapeLib.fill(pts);
|
|
|
},
|
|
|
bess: () => {
|
|
|
const pts = [];
|
|
|
for(let i=0; i<4000; i++) {
|
|
|
pts.push({ x: (Math.random()-0.5)*180 - 100, y: (Math.random()-0.5)*80 + 20, z: (Math.random()-0.5)*80, c: colorMain });
|
|
|
}
|
|
|
pts.push(...ShapeLib.generateLogoPts(-100, 20, 0.6));
|
|
|
for(let i=0; i<4000; i++) {
|
|
|
pts.push({ x: (Math.random()-0.5)*70 + 120, y: (Math.random()-0.5)*160 + 20, z: (Math.random()-0.5)*70, c: colorMain });
|
|
|
}
|
|
|
pts.push(...ShapeLib.generateLogoPts(120, 40, 0.3));
|
|
|
return ShapeLib.fill(pts);
|
|
|
},
|
|
|
wind: () => {
|
|
|
const pts = [];
|
|
|
const rotorY = 120;
|
|
|
for(let i=0; i<5000; i++) {
|
|
|
pts.push({ x: (Math.random()-0.5)*10, y: Math.random()*240-120, z: (Math.random()-0.5)*10 });
|
|
|
}
|
|
|
for(let b=0; b<3; b++) {
|
|
|
let angle = b * (Math.PI * 2 / 3);
|
|
|
for(let i=0; i<3000; i++) {
|
|
|
let len = Math.random() * 140;
|
|
|
pts.push({ x: Math.cos(angle) * len, y: Math.sin(angle) * len + rotorY, z: 999.9 });
|
|
|
}
|
|
|
}
|
|
|
return ShapeLib.fill(pts);
|
|
|
},
|
|
|
solar: () => {
|
|
|
const pts = [];
|
|
|
const panelWidth = 400, panelDepth = 250, stepX = 80, stepZ = 60, groundY = -80;
|
|
|
|
|
|
for(let i = 0; i < 6000; i++) {
|
|
|
let r = Math.random();
|
|
|
if (r < 0.7) {
|
|
|
let x = (Math.random() - 0.5) * panelWidth;
|
|
|
let z = (Math.random() - 0.5) * panelDepth;
|
|
|
let y = -z * 0.5 - 20;
|
|
|
pts.push({ x, y, z, c: colorMain });
|
|
|
} else if (r < 0.9) {
|
|
|
let gridX = (Math.floor(Math.random() * (panelWidth / stepX)) - (panelWidth / stepX / 2)) * stepX;
|
|
|
let gridZ = (Math.floor(Math.random() * (panelDepth / stepZ)) - (panelDepth / stepZ / 2)) * stepZ;
|
|
|
let topY = -gridZ * 0.5 - 20;
|
|
|
let y = groundY + Math.random() * (topY - groundY);
|
|
|
pts.push({ x: gridX, y, z: gridZ, c: new THREE.Color('#14b8a6') });
|
|
|
} else {
|
|
|
let z = (Math.floor(Math.random() * (panelDepth / stepZ)) - (panelDepth / stepZ / 2)) * stepZ;
|
|
|
let x = (Math.random() - 0.5) * panelWidth;
|
|
|
let y = -z * 0.5 - 22;
|
|
|
pts.push({ x, y, z, c: colorMain });
|
|
|
}
|
|
|
}
|
|
|
return ShapeLib.fill(pts);
|
|
|
},
|
|
|
truck: () => {
|
|
|
const pts = [];
|
|
|
const tractorW = 60, tractorH = 55, tractorD = 50;
|
|
|
const trailerW = 150, trailerH = 60, trailerD = 50;
|
|
|
|
|
|
for(let i=0; i<particleCount; i++) {
|
|
|
let r = Math.random();
|
|
|
if(r < 0.15) {
|
|
|
let x = Math.random() * tractorW + 75;
|
|
|
let y = Math.random() * tractorH - 30;
|
|
|
let z = (Math.random() - 0.5) * tractorD;
|
|
|
if (x > 110 && y > 0) x -= (y / tractorH) * 20;
|
|
|
pts.push({ x, y, z });
|
|
|
} else if(r < 0.45) {
|
|
|
let x = Math.random() * trailerW - 80;
|
|
|
let y = Math.random() * trailerH - 30;
|
|
|
let z = (Math.random() - 0.5) * trailerD;
|
|
|
pts.push({ x, y, z });
|
|
|
} else if(r < 0.55) {
|
|
|
let wheelPositions = [-60, -20, 20, 90, 115];
|
|
|
let wIdx = Math.floor(Math.random() * wheelPositions.length);
|
|
|
let angle = Math.random() * Math.PI * 2;
|
|
|
let rad = 12;
|
|
|
let side = Math.random() > 0.5 ? 26 : -26;
|
|
|
pts.push({ x: wheelPositions[wIdx] + Math.cos(angle) * rad, y: -35 + Math.sin(angle) * rad, z: side });
|
|
|
} else if(r < 0.85) {
|
|
|
let x = (Math.random() - 0.5) * 120 + 20;
|
|
|
let y = Math.random() * 140 - 50;
|
|
|
let z = (Math.random() - 0.5) * 110;
|
|
|
if (Math.abs(z) < 40 ) {
|
|
|
if (y < 50) {
|
|
|
z = Math.sign(z) * 45 + (Math.random()-0.5)*5;
|
|
|
}
|
|
|
}
|
|
|
pts.push({ x, y, z });
|
|
|
} else {
|
|
|
let x = 60 + (Math.random() - 0.5) * 25;
|
|
|
let y = 60 + (Math.random() - 0.5) * 20;
|
|
|
let z = (Math.random() - 0.5) * 40;
|
|
|
pts.push({ x, y, z });
|
|
|
}
|
|
|
}
|
|
|
return ShapeLib.fill(pts);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const allData = [
|
|
|
{ data: ShapeLib.text(), text: "SYSTEM // NENGHUI" },
|
|
|
{ data: ShapeLib.bess(), text: "HARDWARE // STORAGE_UNITS" },
|
|
|
{ data: ShapeLib.wind(), text: "GEN // WIND_TURBINE" },
|
|
|
{ data: ShapeLib.solar(), text: "GEN // SOLAR_ARRAY" },
|
|
|
{ data: ShapeLib.truck(), text: "LOGISTICS // TRUCK_SWAP" }
|
|
|
];
|
|
|
|
|
|
const geo = new THREE.BufferGeometry();
|
|
|
const initialPos = new Float32Array(allData[0].data.pos);
|
|
|
const initialTargetPos = new Float32Array(allData[1].data.pos);
|
|
|
const initialTargetCol = new Float32Array(allData[1].data.col);
|
|
|
|
|
|
geo.setAttribute('position', new THREE.BufferAttribute(initialPos, 3));
|
|
|
geo.setAttribute('targetPosition', new THREE.BufferAttribute(initialTargetPos, 3));
|
|
|
geo.setAttribute('targetColor', new THREE.BufferAttribute(initialTargetCol, 3));
|
|
|
|
|
|
const mat = new THREE.ShaderMaterial({
|
|
|
uniforms: { uProgress: { value: 0 }, uTime: { value: 0 } },
|
|
|
vertexShader: document.getElementById('vertexShader').textContent,
|
|
|
fragmentShader: document.getElementById('fragmentShader').textContent,
|
|
|
transparent: true,
|
|
|
blending: THREE.NormalBlending,
|
|
|
depthWrite: false
|
|
|
});
|
|
|
|
|
|
const points = new THREE.Points(geo, mat);
|
|
|
scene.add(points);
|
|
|
|
|
|
function typeText(str) {
|
|
|
const el = document.getElementById('hud-text');
|
|
|
if(!el) return;
|
|
|
el.innerText = ''; let i = 0;
|
|
|
const t = setInterval(() => {
|
|
|
el.innerText += str[i++];
|
|
|
if(i === str.length) clearInterval(t);
|
|
|
}, 40);
|
|
|
}
|
|
|
|
|
|
let curr = 0;
|
|
|
function morph() {
|
|
|
let next = (curr + 1) % allData.length;
|
|
|
|
|
|
geo.attributes.position.array.set(allData[curr].data.pos);
|
|
|
geo.attributes.targetPosition.array.set(allData[next].data.pos);
|
|
|
geo.attributes.targetColor.array.set(allData[next].data.col);
|
|
|
|
|
|
geo.attributes.position.needsUpdate = true;
|
|
|
geo.attributes.targetPosition.needsUpdate = true;
|
|
|
geo.attributes.targetColor.needsUpdate = true;
|
|
|
|
|
|
mat.uniforms.uProgress.value = 0;
|
|
|
typeText(allData[next].text);
|
|
|
|
|
|
gsap.to(mat.uniforms.uProgress, {
|
|
|
value: 1, duration: 2.0, ease: "power2.inOut",
|
|
|
onComplete: () => { curr = next; }
|
|
|
});
|
|
|
}
|
|
|
|
|
|
setInterval(morph, 5000);
|
|
|
typeText(allData[0].text);
|
|
|
|
|
|
let isParticleVisible = true;
|
|
|
const heroSectionEl = document.getElementById('hero-section');
|
|
|
if(heroSectionEl) {
|
|
|
const particleObserver = new IntersectionObserver((entries) => {
|
|
|
isParticleVisible = entries[0].isIntersecting;
|
|
|
}, { threshold: 0 });
|
|
|
particleObserver.observe(heroSectionEl);
|
|
|
}
|
|
|
|
|
|
function animate(t) {
|
|
|
requestAnimationFrame(animate);
|
|
|
if (!isParticleVisible) return;
|
|
|
|
|
|
mat.uniforms.uTime.value = t * 0.001;
|
|
|
points.rotation.y += 0.0015;
|
|
|
renderer.render(scene, camera);
|
|
|
}
|
|
|
animate(0);
|
|
|
|
|
|
window.addEventListener('resize', () => {
|
|
|
camera.aspect = window.innerWidth/window.innerHeight; camera.updateProjectionMatrix();
|
|
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
<script>
|
|
|
const lenis = new Lenis({
|
|
|
duration: 1.2,
|
|
|
easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t))
|
|
|
});
|
|
|
lenis.on('scroll', ScrollTrigger.update);
|
|
|
gsap.ticker.add((time) => { lenis.raf(time * 1000); });
|
|
|
gsap.ticker.lagSmoothing(0);
|
|
|
|
|
|
gsap.registerPlugin(ScrollTrigger);
|
|
|
const cards = gsap.utils.toArray('.stack-card');
|
|
|
|
|
|
cards.forEach((card, i) => {
|
|
|
if (i !== cards.length - 1) {
|
|
|
const nextCard = cards[i + 1];
|
|
|
const overlay = card.querySelector('.card-overlay');
|
|
|
|
|
|
gsap.to(card, {
|
|
|
scale: 0.94,
|
|
|
ease: 'none',
|
|
|
scrollTrigger: {
|
|
|
trigger: nextCard,
|
|
|
start: "top bottom",
|
|
|
end: "top top",
|
|
|
scrub: true
|
|
|
}
|
|
|
});
|
|
|
|
|
|
if (overlay) {
|
|
|
gsap.to(overlay, {
|
|
|
opacity: 1,
|
|
|
ease: 'none',
|
|
|
scrollTrigger: {
|
|
|
trigger: nextCard,
|
|
|
start: "top bottom",
|
|
|
end: "top top",
|
|
|
scrub: true
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const bg = card.querySelector('.bg-parallax');
|
|
|
if (bg) {
|
|
|
gsap.fromTo(bg,
|
|
|
{ yPercent: -10 },
|
|
|
{
|
|
|
yPercent: 10,
|
|
|
ease: "none",
|
|
|
scrollTrigger: {
|
|
|
trigger: card,
|
|
|
start: "top bottom",
|
|
|
end: "bottom top",
|
|
|
scrub: true
|
|
|
}
|
|
|
}
|
|
|
);
|
|
|
}
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
<script>
|
|
|
const globeWrapper = document.querySelector('.globe-module-wrapper');
|
|
|
const dragHint = document.getElementById('drag-hint');
|
|
|
const hideHint = () => {
|
|
|
if(dragHint && !dragHint.classList.contains('hint-fade-out')) {
|
|
|
dragHint.classList.add('hint-fade-out');
|
|
|
}
|
|
|
};
|
|
|
globeWrapper.addEventListener('mousedown', hideHint);
|
|
|
globeWrapper.addEventListener('touchstart', hideHint, {passive: true});
|
|
|
|
|
|
const energyNodes = [
|
|
|
{ lat: 31.23, lng: 121.47, name: 'SHANGHAI HQ', type: 'CORE' },
|
|
|
{ lat: 13.75, lng: 100.99, name: 'THAILAND', type: 'Solar & BESS EPC' },
|
|
|
{ lat: 21.02, lng: 105.85, name: 'VIETNAM', type: 'Solar & BESS EPC' },
|
|
|
{ lat: 11.55, lng: 104.92, name: 'CAMBODIA', type: 'Solar & BESS EPC' },
|
|
|
{ lat: 50.11, lng: 8.68, name: 'EUROPE', type: 'ESS' },
|
|
|
{ lat: 33.31, lng: 44.36, name: 'IRAQ', type: 'EPC Solutions' },
|
|
|
];
|
|
|
const countElement = document.getElementById('active-regions-count');
|
|
|
if (countElement) {
|
|
|
countElement.innerText = energyNodes.length;
|
|
|
}
|
|
|
|
|
|
const arcsData = energyNodes.slice(1).map(d => ({
|
|
|
startLat: 31.23, startLng: 121.47, endLat: d.lat, endLng: d.lng,
|
|
|
color: ['#13eca4', 'rgba(19, 236, 164, 0.05)']
|
|
|
}));
|
|
|
|
|
|
const centerOrigin = new THREE.Vector3(0, 0, 0);
|
|
|
const container = document.getElementById('globe-container');
|
|
|
|
|
|
const starGeo = new THREE.CircleGeometry(0.35, 10);
|
|
|
const matStarBlue = new THREE.MeshBasicMaterial({ color: 0x0055ff, transparent: true, opacity: 0.9, depthWrite: false, side: THREE.DoubleSide });
|
|
|
const matStarCyan = new THREE.MeshBasicMaterial({ color: 0x00ccff, transparent: true, opacity: 0.9, depthWrite: false, side: THREE.DoubleSide });
|
|
|
|
|
|
const world = Globe()
|
|
|
(container)
|
|
|
.backgroundColor('rgba(248, 252, 250, 0)')
|
|
|
.showAtmosphere(true)
|
|
|
.atmosphereColor('#13eca4')
|
|
|
.atmosphereAltitude(0.15)
|
|
|
|
|
|
.polygonAltitude(0.01)
|
|
|
.polygonCapColor(() => '#f0f7f5')
|
|
|
.polygonSideColor(() => '#e2e8f0')
|
|
|
.polygonStrokeColor(() => 'rgba(19, 236, 164, 0.25)')
|
|
|
|
|
|
.arcsData(arcsData)
|
|
|
.arcColor('color')
|
|
|
.arcDashLength(0.4).arcDashGap(0.2).arcDashAnimateTime(2500)
|
|
|
.arcStroke(window.innerWidth < 768 ? 0.8 : 0.5)
|
|
|
.arcAltitude(0.25)
|
|
|
|
|
|
.ringsData(energyNodes)
|
|
|
.ringColor(d => d.type === 'CORE' ? 'rgba(255, 107, 0, 0.9)' : 'rgba(19, 236, 164, 0.9)')
|
|
|
.ringMaxRadius(d => d.type === 'CORE' ? 5.5 : 3.0)
|
|
|
.ringPropagationSpeed(1.5)
|
|
|
.ringRepeatPeriod(d => d.type === 'CORE' ? 1000 : 1500)
|
|
|
.ringAltitude(0.012)
|
|
|
|
|
|
.customLayerData(energyNodes)
|
|
|
.customThreeObject(d => {
|
|
|
const isCore = d.type === 'CORE';
|
|
|
const dotColorHex = isCore ? 0xff6b00 : 0x13eca4;
|
|
|
const size = isCore ? 1.5 : 0.8;
|
|
|
|
|
|
const group = new THREE.Group();
|
|
|
|
|
|
const dotGeo = new THREE.CircleGeometry(size * 0.4, 32);
|
|
|
const dotMat = new THREE.MeshBasicMaterial({ color: dotColorHex, side: THREE.DoubleSide, transparent: true, opacity: 1.0 });
|
|
|
const dotMesh = new THREE.Mesh(dotGeo, dotMat);
|
|
|
group.add(dotMesh);
|
|
|
group.userData.dot = dotMesh;
|
|
|
|
|
|
if (!isCore) {
|
|
|
const nebulaGroup = new THREE.Group();
|
|
|
|
|
|
const starCount = 25;
|
|
|
const maxSpread = size * 4.5;
|
|
|
const minSpread = size * 1.8;
|
|
|
const stars = [];
|
|
|
|
|
|
for (let i = 0; i < starCount; i++) {
|
|
|
const angle = Math.random() * Math.PI * 2;
|
|
|
const r = minSpread + Math.random() * (maxSpread - minSpread);
|
|
|
|
|
|
const mesh = new THREE.Mesh(starGeo, Math.random() > 0.5 ? matStarCyan : matStarBlue);
|
|
|
mesh.position.set(Math.cos(angle) * r, Math.sin(angle) * r, 0);
|
|
|
|
|
|
const baseScale = Math.random() * 0.6 + 0.4;
|
|
|
mesh.scale.set(baseScale, baseScale, 1);
|
|
|
|
|
|
nebulaGroup.add(mesh);
|
|
|
stars.push({
|
|
|
mesh: mesh,
|
|
|
speed: Math.random() * 2.5 + 1.5,
|
|
|
offset: Math.random() * Math.PI * 2,
|
|
|
baseScale: baseScale
|
|
|
});
|
|
|
}
|
|
|
|
|
|
group.add(nebulaGroup);
|
|
|
group.userData.stars = stars;
|
|
|
}
|
|
|
|
|
|
return group;
|
|
|
})
|
|
|
.customThreeObjectUpdate((obj, d) => {
|
|
|
// [优化] 计算固定在表面的坐标缓存:避免每一帧重复转换巨大的数学运算
|
|
|
if (!obj.userData.coordsInitialized) {
|
|
|
const coords = world.getCoords(d.lat, d.lng, 0.02);
|
|
|
obj.position.copy(coords);
|
|
|
obj.lookAt(centerOrigin);
|
|
|
obj.userData.coordsInitialized = true;
|
|
|
}
|
|
|
|
|
|
const now = Date.now() / 1000;
|
|
|
const isCore = d.type === 'CORE';
|
|
|
|
|
|
const corePulse = Math.sin(now * 3.0 + d.lat);
|
|
|
const coreScale = 1 + corePulse * 0.15;
|
|
|
if(obj.userData.dot) obj.userData.dot.scale.set(coreScale, coreScale, 1);
|
|
|
|
|
|
if (!isCore && obj.userData.stars) {
|
|
|
obj.userData.stars.forEach(star => {
|
|
|
const pulse = (Math.sin(now * star.speed + star.offset) + 1) / 2;
|
|
|
const s = star.baseScale * (0.5 + pulse * 3.0);
|
|
|
star.mesh.scale.set(s, s, 1);
|
|
|
});
|
|
|
}
|
|
|
})
|
|
|
|
|
|
.htmlElementsData(energyNodes)
|
|
|
.htmlElement(d => {
|
|
|
const el = document.createElement('div');
|
|
|
const isCore = d.type === 'CORE';
|
|
|
const colorHex = isCore ? '#ff6b00' : '#13eca4';
|
|
|
const delay = Math.random() * 0.5 + 0.8;
|
|
|
|
|
|
el.className = 'globe-label';
|
|
|
el.setAttribute('data-lat', d.lat);
|
|
|
el.setAttribute('data-lng', d.lng);
|
|
|
|
|
|
el.innerHTML = `
|
|
|
<div class="visibility-wrapper">
|
|
|
<div class="anchor-point">
|
|
|
<div class="hud-container" style="animation-delay: ${delay}s;">
|
|
|
<div class="hud-line" style="background: linear-gradient(to right, ${colorHex}90, ${colorHex}10);"></div>
|
|
|
<div class="hud-card" style="border-left: 3px solid ${colorHex};">
|
|
|
<span class="tracking-widest text-[#10221c]">${d.name}</span>
|
|
|
<span class="tag font-black" style="color: ${colorHex}; background: ${colorHex}15; padding: 2px 5px; border-radius: 4px; font-size: 9px;">${d.type}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
`;
|
|
|
return el;
|
|
|
})
|
|
|
.htmlLat(d => d.lat).htmlLng(d => d.lng).htmlAltitude(0.02);
|
|
|
|
|
|
setTimeout(() => {
|
|
|
const globeMaterial = world.globeMaterial();
|
|
|
const scene = world.scene();
|
|
|
const renderer = world.renderer();
|
|
|
|
|
|
if (renderer) renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1.5));
|
|
|
|
|
|
globeMaterial.color = new THREE.Color('#ffffff');
|
|
|
globeMaterial.emissive = new THREE.Color('#f8fcfa');
|
|
|
globeMaterial.emissiveIntensity = 0.1;
|
|
|
globeMaterial.roughness = 0.8;
|
|
|
globeMaterial.metalness = 0.1;
|
|
|
|
|
|
let hasAmbient = false; let hasDirectional = false;
|
|
|
scene.children.forEach(obj => {
|
|
|
if (obj.type === 'DirectionalLight') { obj.intensity = 2.5; obj.position.set(1, 1, 1); hasDirectional = true; }
|
|
|
if (obj.type === 'AmbientLight') { obj.intensity = 1.2; hasAmbient = true; }
|
|
|
});
|
|
|
if (!hasAmbient) scene.add(new THREE.AmbientLight(0xffffff, 1.2));
|
|
|
if (!hasDirectional) {
|
|
|
const fallbackDirLight = new THREE.DirectionalLight(0xffffff, 2.5);
|
|
|
fallbackDirLight.position.set(1, 1, 1); scene.add(fallbackDirLight);
|
|
|
}
|
|
|
}, 100);
|
|
|
|
|
|
fetch('https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_110m_admin_0_countries.geojson')
|
|
|
.then(res => res.json())
|
|
|
.then(data => world.polygonsData(data.features));
|
|
|
|
|
|
const initialIsMobile = container.clientWidth < 768;
|
|
|
world.pointOfView({ lat: 25, lng: 105, altitude: initialIsMobile ? 3.6 : 2.1 });
|
|
|
|
|
|
world.controls().autoRotate = true;
|
|
|
world.controls().autoRotateSpeed = 0.4;
|
|
|
world.controls().enableDamping = true;
|
|
|
world.controls().enableZoom = false;
|
|
|
|
|
|
// ==========================================
|
|
|
// 【大师级架构:全套生命周期与性能控制器】
|
|
|
// ==========================================
|
|
|
|
|
|
let visibilityAnimId;
|
|
|
let isGlobeInViewport = true;
|
|
|
let cachedLabels = null; // [优化] HUD 标签的坐标运算缓存层
|
|
|
|
|
|
function updateLabelVisibility() {
|
|
|
if (!isGlobeInViewport) return;
|
|
|
|
|
|
const camera = world.camera();
|
|
|
if (camera) {
|
|
|
const camPos = camera.position;
|
|
|
const camVec = new THREE.Vector3(camPos.x, camPos.y, camPos.z).normalize();
|
|
|
|
|
|
// [优化] 只查询一次 DOM 和计算坐标位置
|
|
|
if (!cachedLabels) {
|
|
|
const labels = document.querySelectorAll('.globe-label');
|
|
|
if (labels.length === energyNodes.length) {
|
|
|
cachedLabels = Array.from(labels).map(el => {
|
|
|
const lat = parseFloat(el.getAttribute('data-lat'));
|
|
|
const lng = parseFloat(el.getAttribute('data-lng'));
|
|
|
const pos = world.getCoords(lat, lng, 0);
|
|
|
return {
|
|
|
wrapper: el.querySelector('.visibility-wrapper'),
|
|
|
posVec: new THREE.Vector3(pos.x, pos.y, pos.z).normalize(),
|
|
|
hidden: false
|
|
|
};
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (cachedLabels) {
|
|
|
cachedLabels.forEach(label => {
|
|
|
const dot = label.posVec.dot(camVec);
|
|
|
if (label.wrapper) {
|
|
|
if (dot < 0.25) {
|
|
|
if (!label.hidden) {
|
|
|
label.wrapper.classList.add('hud-hidden');
|
|
|
label.hidden = true;
|
|
|
}
|
|
|
} else {
|
|
|
if (label.hidden) {
|
|
|
label.wrapper.classList.remove('hud-hidden');
|
|
|
label.hidden = false;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
visibilityAnimId = requestAnimationFrame(updateLabelVisibility);
|
|
|
}
|
|
|
|
|
|
// [优化] 为 3D 初始化留出充足的预渲染缓冲期,防止突发的 Shader 编译引发第一次卡顿
|
|
|
let hasRenderedInitialFrames = false;
|
|
|
setTimeout(() => {
|
|
|
hasRenderedInitialFrames = true;
|
|
|
// 缓冲结束后如果处于不可见状态,则安稳休眠
|
|
|
if (!isGlobeInViewport) {
|
|
|
world.pauseAnimation();
|
|
|
if (visibilityAnimId) cancelAnimationFrame(visibilityAnimId);
|
|
|
}
|
|
|
}, 1500);
|
|
|
|
|
|
const observer1 = new IntersectionObserver((entries) => {
|
|
|
entries.forEach(entry => {
|
|
|
if (entry.isIntersecting) {
|
|
|
if (!isGlobeInViewport) {
|
|
|
isGlobeInViewport = true;
|
|
|
world.resumeAnimation();
|
|
|
updateLabelVisibility();
|
|
|
}
|
|
|
} else {
|
|
|
isGlobeInViewport = false;
|
|
|
// 只在完成了初始化预编译缓冲后才暂停动画
|
|
|
if (hasRenderedInitialFrames) {
|
|
|
world.pauseAnimation();
|
|
|
if (visibilityAnimId) cancelAnimationFrame(visibilityAnimId);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
}, { threshold: 0.01 });
|
|
|
|
|
|
observer1.observe(document.querySelector('.globe-module-wrapper'));
|
|
|
|
|
|
const resizeObserver = new ResizeObserver(entries => {
|
|
|
for (let entry of entries) {
|
|
|
if(!isGlobeInViewport) return;
|
|
|
|
|
|
const { width, height } = entry.contentRect;
|
|
|
if(width > 0 && height > 0) {
|
|
|
world.width(width).height(height);
|
|
|
const isMobileSize = width < 768;
|
|
|
world.pointOfView({ altitude: isMobileSize ? 3.6 : 2.1 });
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
resizeObserver.observe(document.querySelector('.globe-module-wrapper'));
|
|
|
|
|
|
</script>
|
|
|
</body>
|
|
|
</html>
|