This commit is contained in:
张成
2025-08-25 15:28:08 +08:00
parent c4148d9eb6
commit 1ad48b234c
3 changed files with 382 additions and 29 deletions

View File

@@ -3,6 +3,7 @@ import './assets/css/common.css'
import './assets/css/animations.css'
import 'swiper/css/swiper.min.css'
import 'es6-promise/auto'
import './static/animation_helper'
import Vue from 'vue'
import App from './App.vue'
import Vuex from 'vuex'

View File

@@ -0,0 +1,349 @@
/**
* 动画助手 - 处理滚动触发动画和交互动画
*/
class AnimationHelper {
constructor() {
this.animatedElements = [];
this.isInitialized = false;
this.observer = null;
this.init();
}
/**
* 初始化动画助手
*/
init() {
if (this.isInitialized) return;
// 设置Intersection Observer
this.setupIntersectionObserver();
// 添加滚动事件监听
this.addScrollListeners();
// 初始化页面加载动画
this.initPageLoadAnimations();
this.isInitialized = true;
}
/**
* 设置Intersection Observer用于滚动触发动画
*/
setupIntersectionObserver() {
if (!window.IntersectionObserver) {
// 降级处理:直接显示所有元素
this.showAllElements();
return;
}
this.observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.animateElement(entry.target);
}
});
}, {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
});
}
/**
* 添加滚动事件监听
*/
addScrollListeners() {
// 监听滚动事件,用于视差效果
window.addEventListener('scroll', this.handleScroll.bind(this), { passive: true });
// 监听窗口大小变化
window.addEventListener('resize', this.handleResize.bind(this), { passive: true });
}
/**
* 处理滚动事件
*/
handleScroll() {
this.updateParallaxEffects();
this.updateScrollProgress();
}
/**
* 处理窗口大小变化
*/
handleResize() {
// 重新计算动画元素位置
this.recalculateAnimations();
}
/**
* 初始化页面加载动画
*/
initPageLoadAnimations() {
// 为页面加载动画添加延迟
setTimeout(() => {
this.animatePageLoad();
}, 100);
}
/**
* 页面加载动画
*/
animatePageLoad() {
// 标题动画
const titles = document.querySelectorAll('.section-title.animate-on-scroll');
titles.forEach((title, index) => {
setTimeout(() => {
title.classList.add('visible');
}, index * 200);
});
// 内容动画
const contentElements = document.querySelectorAll('.animate-stagger');
contentElements.forEach((container, containerIndex) => {
const children = container.children;
Array.from(children).forEach((child, childIndex) => {
setTimeout(() => {
child.style.opacity = '1';
child.style.transform = 'translateY(0)';
}, (containerIndex * 300) + (childIndex * 100));
});
});
}
/**
* 为元素添加滚动触发动画
*/
addScrollAnimation(element, options = {}) {
if (!element) return;
const defaultOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px',
animationClass: 'animate-in',
delay: 0
};
const config = { ...defaultOptions, ...options };
// 添加动画类
element.classList.add('scroll-animate');
// 设置延迟
if (config.delay > 0) {
element.style.transitionDelay = `${config.delay}s`;
}
// 添加到观察列表
if (this.observer) {
this.observer.observe(element);
}
this.animatedElements.push(element);
}
/**
* 为多个元素添加交错动画
*/
addStaggerAnimation(container, options = {}) {
if (!container) return;
const defaultOptions = {
delay: 0.1,
staggerDelay: 0.1,
animationClass: 'visible'
};
const config = { ...defaultOptions, ...options };
// 添加交错动画类
container.classList.add('animate-stagger');
// 为子元素设置初始状态
const children = Array.from(container.children);
children.forEach((child, index) => {
child.style.opacity = '0';
child.style.transform = 'translateY(30px)';
child.style.transitionDelay = `${config.delay + (index * config.staggerDelay)}s`;
});
// 添加到观察列表
if (this.observer) {
this.observer.observe(container);
}
this.animatedElements.push(container);
}
/**
* 触发元素动画
*/
animateElement(element) {
if (!element) return;
// 添加可见类
if (element.classList.contains('scroll-animate')) {
element.classList.add('animate-in');
} else if (element.classList.contains('animate-stagger')) {
element.classList.add('visible');
}
// 触发自定义事件
element.dispatchEvent(new CustomEvent('animationStart', {
detail: { element, type: 'scroll' }
}));
}
/**
* 手动触发动画
*/
triggerAnimation(element, animationClass = 'animate-in') {
if (!element) return;
element.classList.add(animationClass);
// 触发自定义事件
element.dispatchEvent(new CustomEvent('animationTrigger', {
detail: { element, animationClass }
}));
}
/**
* 重置元素动画状态
*/
resetAnimation(element) {
if (!element) return;
element.classList.remove('animate-in', 'visible');
element.style.transitionDelay = '';
// 重置样式
if (element.classList.contains('scroll-animate')) {
element.style.opacity = '0';
element.style.transform = 'translateY(50px)';
} else if (element.classList.contains('animate-stagger')) {
const children = Array.from(element.children);
children.forEach(child => {
child.style.opacity = '0';
child.style.transform = 'translateY(30px)';
});
}
}
/**
* 更新视差效果
*/
updateParallaxEffects() {
const parallaxElements = document.querySelectorAll('[data-parallax]');
const scrolled = window.pageYOffset;
parallaxElements.forEach(element => {
const speed = parseFloat(element.dataset.parallax) || 0.5;
const yPos = -(scrolled * speed);
element.style.transform = `translateY(${yPos}px)`;
});
}
/**
* 更新滚动进度
*/
updateScrollProgress() {
const progressElements = document.querySelectorAll('[data-scroll-progress]');
const scrolled = window.pageYOffset;
const maxScroll = document.documentElement.scrollHeight - window.innerHeight;
const progress = (scrolled / maxScroll) * 100;
progressElements.forEach(element => {
if (element.dataset.scrollProgress === 'bar') {
element.style.width = `${progress}%`;
} else if (element.dataset.scrollProgress === 'number') {
element.textContent = Math.round(progress);
}
});
}
/**
* 重新计算动画
*/
recalculateAnimations() {
// 重新观察所有元素
this.animatedElements.forEach(element => {
if (this.observer) {
this.observer.unobserve(element);
this.observer.observe(element);
}
});
}
/**
* 显示所有元素(降级处理)
*/
showAllElements() {
const scrollElements = document.querySelectorAll('.scroll-animate, .animate-stagger');
scrollElements.forEach(element => {
if (element.classList.contains('scroll-animate')) {
element.classList.add('animate-in');
} else if (element.classList.contains('animate-stagger')) {
element.classList.add('visible');
}
});
}
/**
* 添加鼠标悬停动画
*/
addHoverAnimation(element, animationType = 'scale') {
if (!element) return;
const animations = {
scale: 'hover-scale',
lift: 'hover-lift',
rotate: 'hover-rotate',
glow: 'hover-glow',
bounce: 'hover-bounce'
};
const animationClass = animations[animationType] || 'hover-scale';
element.classList.add(animationClass);
}
/**
* 添加点击动画
*/
addClickAnimation(element, animationType = 'pulse') {
if (!element) return;
element.addEventListener('click', () => {
element.classList.add(`animate ${animationType}`);
// 动画结束后移除类
setTimeout(() => {
element.classList.remove(`animate ${animationType}`);
}, 1000);
});
}
/**
* 销毁动画助手
*/
destroy() {
if (this.observer) {
this.observer.disconnect();
}
window.removeEventListener('scroll', this.handleScroll);
window.removeEventListener('resize', this.handleResize);
this.animatedElements = [];
this.isInitialized = false;
}
}
// 创建全局实例
window.animationHelper = new AnimationHelper();
// 导出类(如果使用模块系统)
if (typeof module !== 'undefined' && module.exports) {
module.exports = AnimationHelper;
}

View File

@@ -1,9 +1,12 @@
<template>
<div>
<!-- 滚动进度条 -->
<div class="scroll-progress-bar" data-scroll-progress="bar"></div>
<ihead></ihead>
<!-- 现代化横幅区域 -->
<div class="banner">
<div class="banner" data-parallax="0.3">
<swiper ref="swiper" :options="swiperOption">
<swiper-slide v-for="banner in banners" :key="banner.img">
<div class="banner-content">
@@ -31,21 +34,21 @@
<p class="section-subtitle animate-on-scroll">上海丙维数字科技有限公司成立于2018年专注于AI交付内容为客户提供高质量的数字化解决方案</p>
</div>
<div class="intro-content">
<div class="intro-card">
<div class="card-icon">🏢</div>
<div class="intro-content animate-stagger">
<div class="intro-card hover-lift">
<div class="card-icon animate pulse infinite">🏢</div>
<h3>公司概况</h3>
<p>成立于2018年10月22日注册资本600万元人民币总部位于上海市宝山区高逸路112-118号3幢6422室</p>
</div>
<div class="intro-card">
<div class="card-icon">🎯</div>
<div class="intro-card hover-lift">
<div class="card-icon animate pulse infinite delay-1s">🎯</div>
<h3>核心使命</h3>
<p>致力于计算机软硬件网络科技信息科技领域的技术开发咨询转让和服务</p>
</div>
<div class="intro-card">
<div class="card-icon">🚀</div>
<div class="intro-card hover-lift">
<div class="card-icon animate pulse infinite delay-2s">🚀</div>
<h3>AI转型</h3>
<p>2022年成功转型AI交付领域围绕客户需求提供智能应用解决方案</p>
</div>
@@ -56,10 +59,10 @@
<!-- 核心优势展示 -->
<div class="core-advantages">
<div class="container">
<h2 class="section-title">核心优势</h2>
<div class="advantages-grid">
<div class="advantage-item" v-for="advantage in advantages" :key="advantage.title">
<div class="advantage-icon">{{advantage.icon}}</div>
<h2 class="section-title animate-on-scroll">核心优势</h2>
<div class="advantages-grid animate-stagger">
<div class="advantage-item hover-scale" v-for="advantage in advantages" :key="advantage.title">
<div class="advantage-icon animate bounce delay-1s">{{advantage.icon}}</div>
<h3>{{advantage.title}}</h3>
<p>{{advantage.description}}</p>
</div>
@@ -70,10 +73,10 @@
<!-- 业务领域展示 -->
<div class="business-areas">
<div class="container">
<h2 class="section-title">业务领域</h2>
<div class="areas-grid">
<div class="area-item" v-for="area in businessAreas" :key="area.name">
<div class="area-icon">{{area.icon}}</div>
<h2 class="section-title animate-on-scroll">业务领域</h2>
<div class="areas-grid animate-stagger">
<div class="area-item hover-glow" v-for="area in businessAreas" :key="area.name">
<div class="area-icon animate wobble delay-2s">{{area.icon}}</div>
<h3>{{area.name}}</h3>
<p>{{area.description}}</p>
<ul class="area-features">
@@ -86,7 +89,7 @@
<!-- 原有产品展示区域 -->
<div class="scrollToContentWrapper">
<a href="javascript:void(0)" id="scrollToBoxes" class="scrollToContent bottomShadowSegmentLight">
<a href="javascript:void(0)" id="scrollToBoxes" class="scrollToContent bottomShadowSegmentLight animate bounce infinite">
<img src="../assets/img/svg/ic_caret.svg" alt="">
</a>
</div>
@@ -94,11 +97,11 @@
<!-- 产品展示区域 -->
<div class="products-section">
<div class="container">
<h2 class="section-title">核心解决方案</h2>
<p class="section-subtitle">为不同行业提供专业的技术解决方案助力企业数字化转型</p>
<h2 class="section-title animate-on-scroll">核心解决方案</h2>
<p class="section-subtitle animate-on-scroll">为不同行业提供专业的技术解决方案助力企业数字化转型</p>
<div id="pageBoxesContainer" class="page pageBoxes">
<div class="box" v-for="product in productData" :key="product.name">
<div id="pageBoxesContainer" class="page pageBoxes animate-stagger">
<div class="box hover-lift" v-for="product in productData" :key="product.name">
<div class="product-image">
<img width="100%" :src="product.img" />
<div class="product-overlay">
@@ -126,24 +129,24 @@
<!-- 联系我们区域 -->
<div class="contact-section">
<div class="container">
<h2 class="section-title">联系我们</h2>
<div class="contact-info">
<div class="contact-item">
<div class="contact-icon">📍</div>
<h2 class="section-title animate-on-scroll">联系我们</h2>
<div class="contact-info animate-stagger">
<div class="contact-item hover-scale">
<div class="contact-icon animate heartBeat infinite">📍</div>
<div>
<h4>注册地址</h4>
<p>上海市宝山区高逸路112-118号3幢6422室</p>
</div>
</div>
<div class="contact-item">
<div class="contact-icon">📞</div>
<div class="contact-item hover-scale">
<div class="contact-icon animate heartBeat infinite delay-1s">📞</div>
<div>
<h4>联系电话</h4>
<p>13817819452</p>
</div>
</div>
<div class="contact-item">
<div class="contact-icon">🌐</div>
<div class="contact-item hover-scale">
<div class="contact-icon animate heartBeat infinite delay-2s">🌐</div>
<div>
<h4>官方网站</h4>
<p>www.bimwe.com</p>