This commit is contained in:
张成
2025-08-25 15:24:23 +08:00
parent a993c55d3f
commit c4148d9eb6
11 changed files with 3220 additions and 2589 deletions

View File

@@ -0,0 +1,353 @@
/**
* 响应式助手 - 替代媒体查询的JavaScript解决方案
* 动态检测屏幕尺寸并添加相应的响应式类名
*/
class ResponsiveHelper {
constructor() {
// 响应式断点定义
this.breakpoints = {
xs: 380,
sm: 480,
md: 620,
lg: 768,
xl: 992,
xxl: 1200,
xxxl: 1500,
xxxxl: 1600
};
// 当前屏幕尺寸
this.currentSize = '';
// 初始化
this.init();
}
/**
* 初始化响应式助手
*/
init() {
// 添加容器查询支持检测
this.addContainerQuerySupport();
// 检测初始屏幕尺寸
this.detectScreenSize();
// 监听窗口大小变化
this.addResizeListener();
// 监听方向变化
this.addOrientationListener();
// 添加触摸设备检测
this.detectTouchDevice();
// 添加高分辨率屏幕检测
this.detectHighDPI();
}
/**
* 检测当前屏幕尺寸并添加相应类名
*/
detectScreenSize() {
const width = window.innerWidth;
let newSize = '';
// 根据宽度确定屏幕尺寸
if (width <= this.breakpoints.xs) {
newSize = 'xs';
} else if (width <= this.breakpoints.sm) {
newSize = 'sm';
} else if (width <= this.breakpoints.md) {
newSize = 'md';
} else if (width <= this.breakpoints.lg) {
newSize = 'lg';
} else if (width <= this.breakpoints.xl) {
newSize = 'xl';
} else if (width <= this.breakpoints.xxl) {
newSize = 'xxl';
} else if (width <= this.breakpoints.xxxl) {
newSize = 'xxxl';
} else {
newSize = 'xxxxl';
}
// 如果尺寸发生变化,更新类名
if (newSize !== this.currentSize) {
this.updateScreenClasses(newSize);
this.currentSize = newSize;
}
}
/**
* 更新屏幕尺寸相关的CSS类名
*/
updateScreenClasses(newSize) {
const body = document.body;
const html = document.documentElement;
// 移除旧的屏幕尺寸类名
const oldClasses = Object.values(this.breakpoints).map(size => `screen-${size}`);
body.classList.remove(...oldClasses);
html.classList.remove(...oldClasses);
// 添加新的屏幕尺寸类名
body.classList.add(`screen-${newSize}`);
html.classList.add(`screen-${newSize}`);
// 添加响应式容器类名
this.addResponsiveContainerClasses();
// 触发自定义事件
this.triggerScreenChangeEvent(newSize);
}
/**
* 添加响应式容器类名
*/
addResponsiveContainerClasses() {
const containers = document.querySelectorAll('.responsive-container');
containers.forEach(container => {
const width = container.offsetWidth;
let containerSize = '';
// 根据容器宽度确定尺寸
if (width <= this.breakpoints.xs) {
containerSize = 'xs';
} else if (width <= this.breakpoints.sm) {
containerSize = 'sm';
} else if (width <= this.breakpoints.md) {
containerSize = 'md';
} else if (width <= this.breakpoints.lg) {
containerSize = 'lg';
} else if (width <= this.breakpoints.xl) {
containerSize = 'xl';
} else if (width <= this.breakpoints.xxl) {
containerSize = 'xxl';
} else if (width <= this.breakpoints.xxxl) {
containerSize = 'xxxl';
} else {
containerSize = 'xxxxl';
}
// 移除旧的容器尺寸类名
const oldContainerClasses = Object.values(this.breakpoints).map(size => `container-${size}`);
container.classList.remove(...oldContainerClasses);
// 添加新的容器尺寸类名
container.classList.add(`container-${containerSize}`);
});
}
/**
* 添加容器查询支持
*/
addContainerQuerySupport() {
// 检测浏览器是否支持容器查询
if (CSS.supports('container-type', 'inline-size')) {
document.documentElement.classList.add('supports-container-queries');
} else {
document.documentElement.classList.add('no-container-queries');
// 为不支持容器查询的浏览器提供回退方案
this.addContainerQueryPolyfill();
}
}
/**
* 容器查询回退方案
*/
addContainerQueryPolyfill() {
// 创建 ResizeObserver 来监听容器大小变化
if (window.ResizeObserver) {
const containers = document.querySelectorAll('.responsive-container');
containers.forEach(container => {
const resizeObserver = new ResizeObserver(() => {
this.addResponsiveContainerClasses();
});
resizeObserver.observe(container);
});
}
}
/**
* 添加窗口大小变化监听器
*/
addResizeListener() {
let resizeTimeout;
window.addEventListener('resize', () => {
// 使用防抖优化性能
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(() => {
this.detectScreenSize();
}, 100);
});
}
/**
* 添加方向变化监听器
*/
addOrientationListener() {
window.addEventListener('orientationchange', () => {
// 方向变化后延迟检测,确保布局已更新
setTimeout(() => {
this.detectScreenSize();
}, 100);
});
}
/**
* 检测触摸设备
*/
detectTouchDevice() {
if ('ontouchstart' in window || navigator.maxTouchPoints > 0) {
document.documentElement.classList.add('touch-device');
} else {
document.documentElement.classList.add('no-touch-device');
}
}
/**
* 检测高分辨率屏幕
*/
detectHighDPI() {
const dpr = window.devicePixelRatio || 1;
if (dpr >= 2) {
document.documentElement.classList.add('high-dpi');
} else {
document.documentElement.classList.add('low-dpi');
}
}
/**
* 触发屏幕变化事件
*/
triggerScreenChangeEvent(newSize) {
const event = new CustomEvent('screenSizeChange', {
detail: {
size: newSize,
width: window.innerWidth,
height: window.innerHeight,
breakpoint: this.breakpoints[newSize]
}
});
window.dispatchEvent(event);
}
/**
* 获取当前屏幕尺寸信息
*/
getCurrentScreenInfo() {
return {
size: this.currentSize,
width: window.innerWidth,
height: window.innerHeight,
breakpoint: this.breakpoints[this.currentSize],
isMobile: this.currentSize === 'xs' || this.currentSize === 'sm' || this.currentSize === 'md',
isTablet: this.currentSize === 'lg',
isDesktop: this.currentSize === 'xl' || this.currentSize === 'xxl' || this.currentSize === 'xxxl' || this.currentSize === 'xxxxl'
};
}
/**
* 检查是否匹配特定断点
*/
matchesBreakpoint(breakpoint) {
const width = window.innerWidth;
return width <= this.breakpoints[breakpoint];
}
/**
* 添加响应式工具方法
*/
addResponsiveUtils() {
// 添加响应式显示/隐藏方法
window.responsiveShow = (element, breakpoint = 'lg') => {
if (this.matchesBreakpoint(breakpoint)) {
element.style.display = 'block';
} else {
element.style.display = 'none';
}
};
window.responsiveHide = (element, breakpoint = 'lg') => {
if (this.matchesBreakpoint(breakpoint)) {
element.style.display = 'none';
} else {
element.style.display = 'block';
}
};
// 添加响应式类名切换方法
window.responsiveToggleClass = (element, className, breakpoint = 'lg') => {
if (this.matchesBreakpoint(breakpoint)) {
element.classList.add(className);
} else {
element.classList.remove(className);
}
};
}
/**
* 销毁响应式助手
*/
destroy() {
// 移除事件监听器
window.removeEventListener('resize', this.detectScreenSize);
window.removeEventListener('orientationchange', this.detectScreenSize);
// 移除类名
const body = document.body;
const html = document.documentElement;
const oldClasses = Object.values(this.breakpoints).map(size => `screen-${size}`);
body.classList.remove(...oldClasses);
html.classList.remove(...oldClasses);
}
}
// 创建全局实例
window.responsiveHelper = new ResponsiveHelper();
// 添加响应式工具方法
window.responsiveHelper.addResponsiveUtils();
// 导出类(如果使用模块系统)
if (typeof module !== 'undefined' && module.exports) {
module.exports = ResponsiveHelper;
}
// 使用示例:
/*
// 监听屏幕尺寸变化
window.addEventListener('screenSizeChange', (event) => {
console.log('屏幕尺寸变化:', event.detail);
// 根据屏幕尺寸执行不同逻辑
if (event.detail.size === 'xs' || event.detail.size === 'sm') {
// 移动端逻辑
console.log('移动端设备');
} else if (event.detail.size === 'lg') {
// 平板逻辑
console.log('平板设备');
} else {
// 桌面端逻辑
console.log('桌面端设备');
}
});
// 检查当前屏幕信息
const screenInfo = window.responsiveHelper.getCurrentScreenInfo();
console.log('当前屏幕信息:', screenInfo);
// 使用响应式工具方法
const element = document.querySelector('.my-element');
window.responsiveShow(element, 'md'); // 在中等屏幕以下显示
window.responsiveHide(element, 'lg'); // 在大屏幕以上隐藏
window.responsiveToggleClass(element, 'mobile-style', 'md'); // 在中等屏幕以下添加移动端样式
*/