1
This commit is contained in:
@@ -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'
|
||||
|
||||
349
src/static/animation_helper.js
Normal file
349
src/static/animation_helper.js
Normal 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;
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user