Files
DDCZ/js/ui/UIUtils.js
KQL ab50931347 初始化多多畅职企业内推平台项目
功能特性:
- 3D地球动画与中国地图可视化
- 省份/城市/企业搜索功能
- 308家企业数据展示
- 响应式设计(PC端和移动端)
- 企业详情页面与业务板块展示
- 官网新闻轮播图

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-22 19:38:14 +08:00

202 lines
6.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ===================================
UI工具函数
=================================== */
import { CONFIG } from '../config.js';
export class UIUtils {
/**
* 切换界面显示/隐藏
* @param {HTMLElement} hideElement - 要隐藏的元素
* @param {HTMLElement} showElement - 要显示的元素
* @param {Function} onComplete - 完成回调
*/
static switchInterface(hideElement, showElement, onComplete) {
const duration = CONFIG.animation.ui.fadeDuration;
gsap.to(hideElement, {
opacity: 0,
duration: duration,
onComplete: () => {
hideElement.style.display = 'none';
showElement.style.display = 'block';
gsap.to(showElement, {
opacity: 1,
duration: duration,
onComplete: onComplete
});
}
});
}
/**
* 批量显示元素(带渐入动画)
* @param {string} selector - CSS选择器
* @param {object} options - 动画选项
*/
static staggerShow(selector, options = {}) {
const defaults = {
opacity: 1,
y: 0,
duration: 0.6,
stagger: CONFIG.animation.ui.cardStagger,
delay: CONFIG.animation.ui.cardDelay,
ease: "power2.out"
};
gsap.to(selector, { ...defaults, ...options });
}
/**
* 移动端触摸事件适配
* @param {HTMLElement} element - 目标元素
* @param {object} handlers - 事件处理器 { onTap, onSwipe }
*/
static bindTouchEvents(element, handlers) {
let startX = 0;
let startY = 0;
let startTime = 0;
element.addEventListener('touchstart', (e) => {
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
startTime = Date.now();
});
element.addEventListener('touchend', (e) => {
const endX = e.changedTouches[0].clientX;
const endY = e.changedTouches[0].clientY;
const endTime = Date.now();
const deltaX = endX - startX;
const deltaY = endY - startY;
const deltaTime = endTime - startTime;
// 判断是点击还是滑动
if (Math.abs(deltaX) < 10 && Math.abs(deltaY) < 10 && deltaTime < 300) {
// 点击
if (handlers.onTap) handlers.onTap(e);
} else {
// 滑动
if (handlers.onSwipe) {
const direction = Math.abs(deltaX) > Math.abs(deltaY)
? (deltaX > 0 ? 'right' : 'left')
: (deltaY > 0 ? 'down' : 'up');
handlers.onSwipe(direction, e);
}
}
});
}
/**
* 防抖函数
* @param {Function} func - 要防抖的函数
* @param {number} wait - 等待时间(毫秒)
* @returns {Function}
*/
static debounce(func, wait = 300) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
/**
* 节流函数
* @param {Function} func - 要节流的函数
* @param {number} limit - 限制间隔(毫秒)
* @returns {Function}
*/
static throttle(func, limit = 100) {
let inThrottle;
return function executedFunction(...args) {
if (!inThrottle) {
func(...args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
/**
* 检测是否为移动设备
* @returns {boolean}
*/
static isMobile() {
return window.innerWidth <= CONFIG.mobile.breakpoint;
}
/**
* 获取安全区域内边距
* @returns {object} { top, bottom, left, right }
*/
static getSafeAreaInsets() {
const computed = getComputedStyle(document.documentElement);
return {
top: parseInt(computed.getPropertyValue('env(safe-area-inset-top)')) || 0,
bottom: parseInt(computed.getPropertyValue('env(safe-area-inset-bottom)')) || 0,
left: parseInt(computed.getPropertyValue('env(safe-area-inset-left)')) || 0,
right: parseInt(computed.getPropertyValue('env(safe-area-inset-right)')) || 0
};
}
/**
* 初始化陀螺仪控制(移动端视差)
* @param {Function} callback - 回调函数,接收 (beta, gamma) 参数
*/
static initGyroscope(callback) {
if (!this.isMobile()) return;
if (window.DeviceOrientationEvent) {
window.addEventListener('deviceorientation', (e) => {
const beta = e.beta || 0; // 前后倾斜(-180 ~ 180
const gamma = e.gamma || 0; // 左右倾斜(-90 ~ 90
callback(beta, gamma);
});
}
}
/**
* 显示加载提示
* @param {string} text - 提示文本
*/
static showLoading(text = '加载中...') {
const existing = document.getElementById('loading-overlay');
if (existing) return;
const overlay = document.createElement('div');
overlay.id = 'loading-overlay';
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
color: #38bdf8;
font-size: 1rem;
`;
overlay.innerText = text;
document.body.appendChild(overlay);
}
/**
* 隐藏加载提示
*/
static hideLoading() {
const overlay = document.getElementById('loading-overlay');
if (overlay) {
overlay.remove();
}
}
}