@scqilin/screen-scaler
Version:
A powerful screen scaling adapter for big screen applications with TypeScript support
409 lines (319 loc) • 9.87 kB
Markdown
一个强大的大屏缩放适配器,专为大屏应用开发设计。支持多种缩放模式,提供完整的 TypeScript 类型支持。
- 🎯 **多种缩放模式**: 支持自动、宽度、高度、拉伸、无缩放五种模式
- 📱 **响应式设计**: 自动响应窗口大小变化
- 🎨 **设计稿适配**: 支持任意设计稿尺寸
- 💪 **TypeScript**: 完整的类型定义支持
- 🚀 **轻量级**: 无依赖,压缩后小于 10KB
- 🔧 **易于使用**: 简单的 API 设计
- 🎛️ **灵活配置**: 丰富的配置选项
- 📊 **实时信息**: 提供详细的缩放信息回调
```bash
npm install @scqilin/screen-scaler
```
```bash
yarn add @scqilin/screen-scaler
```
```bash
pnpm add @scqilin/screen-scaler
```
```typescript
import { ScreenScaler } from '@scqilin/screen-scaler';
const scaler = new ScreenScaler({
container: '#app',
designWidth: 1920,
designHeight: 1080,
mode: 'auto'
});
```
```javascript
const { ScreenScaler } = require('@scqilin/screen-scaler');
const scaler = new ScreenScaler({
container: document.getElementById('app'),
designWidth: 1920,
designHeight: 1080,
mode: 'auto'
});
```
```html
<script src="https://unpkg.com/@scqilin/screen-scaler/dist/index.umd.js"></script>
<script>
const scaler = new ScreenScaler.ScreenScaler({
container: '#app',
designWidth: 1920,
designHeight: 1080,
mode: 'auto'
});
</script>
```
```typescript
new ScreenScaler(config: ScreenScalerConfig)
```
### 配置选项 (ScreenScalerConfig)
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|------|------|------|--------|------|
| `container` | `HTMLElement \| string` | ✅ | - | 目标容器元素或选择器 |
| `designWidth` | `number` | ✅ | - | 设计稿宽度 |
| `designHeight` | `number` | ✅ | - | 设计稿高度 |
| `mode` | `ScaleMode` | ❌ | `'auto'` | 缩放模式 |
| `autoResize` | `boolean` | ❌ | `true` | 是否自动响应窗口变化 |
| `onScaleChange` | `function` | ❌ | - | 缩放变化回调函数 |
### 缩放模式 (ScaleMode)
| 模式 | 描述 | 适用场景 |
|------|------|----------|
| `'none'` | 不进行缩放 | 原始尺寸显示 |
| `'auto'` | 等比缩放,保持宽高比 | 大多数场景的最佳选择 |
| `'width'` | 根据宽度等比缩放 | 宽度固定,高度自适应 |
| `'height'` | 根据高度等比缩放 | 高度固定,宽度自适应 |
| `'stretch'` | 拉伸填满容器 | 需要填满整个屏幕 |
### 实例方法
#### `getScaleInfo(): ScaleInfo`
获取当前缩放信息。
```typescript
const info = scaler.getScaleInfo();
console.log(info.scale.ratio); // 当前缩放比例
```
更新配置。
```typescript
scaler.updateConfig({
designWidth: 1600,
designHeight: 900,
mode: 'width'
});
```
手动触发重新缩放。
```typescript
scaler.resize();
```
销毁实例,清理事件监听器。
```typescript
scaler.destroy();
```
检查实例是否已销毁。
```typescript
if (!scaler.isDestroyed()) {
scaler.resize();
}
```
```typescript
interface ScaleInfo {
mode: ScaleMode; // 当前缩放模式
scale: {
x: number; // X轴缩放比例
y: number; // Y轴缩放比例
ratio: number; // 等比缩放比例
};
screen: {
width: number; // 屏幕宽度
height: number; // 屏幕高度
};
design: {
width: number; // 设计稿宽度
height: number; // 设计稿高度
};
scaled: {
width: number; // 缩放后宽度
height: number; // 缩放后高度
};
offset: {
x: number; // X轴偏移量
y: number; // Y轴偏移量
};
}
```
```typescript
import { ScreenScaler } from '@scqilin/screen-scaler';
// 创建缩放器实例
const scaler = new ScreenScaler({
container: '#app',
designWidth: 1920,
designHeight: 1080,
mode: 'auto',
onScaleChange: (info) => {
console.log(`当前缩放比例: ${info.scale.ratio}`);
}
});
```
```vue
<template>
<div ref="containerRef" class="screen-container">
<div class="content">
<!-- 你的内容 -->
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { ScreenScaler } from '@scqilin/screen-scaler';
const containerRef = ref<HTMLElement>();
let scaler: ScreenScaler | null = null;
onMounted(() => {
if (containerRef.value) {
scaler = new ScreenScaler({
container: containerRef.value.querySelector('.content')!,
designWidth: 1920,
designHeight: 1080,
mode: 'auto'
});
}
});
onUnmounted(() => {
scaler?.destroy();
});
</script>
```
```tsx
import React, { useRef, useEffect } from 'react';
import { ScreenScaler } from '@scqilin/screen-scaler';
const BigScreen: React.FC = () => {
const containerRef = useRef<HTMLDivElement>(null);
const scalerRef = useRef<ScreenScaler | null>(null);
useEffect(() => {
if (containerRef.current) {
scalerRef.current = new ScreenScaler({
container: containerRef.current,
designWidth: 1920,
designHeight: 1080,
mode: 'auto'
});
}
return () => {
scalerRef.current?.destroy();
};
}, []);
return (
<div className="screen-wrapper">
<div ref={containerRef} className="screen-content">
{/* 你的内容 */}
</div>
</div>
);
};
```
```typescript
import { ScreenScaler } from '@scqilin/screen-scaler';
const scaler = new ScreenScaler({
container: '#app',
designWidth: 1920,
designHeight: 1080,
mode: 'auto'
});
// 响应用户设置
function handleModeChange(mode: 'auto' | 'width' | 'height' | 'stretch' | 'none') {
scaler.updateConfig({ mode });
}
// 响应设计尺寸变化
function handleSizeChange(width: number, height: number) {
scaler.updateConfig({
designWidth: width,
designHeight: height
});
}
```
- **auto**: 大多数情况下的最佳选择,保持设计稿比例
- **width**: 适用于横向滚动或宽度固定的场景
- **height**: 适用于纵向滚动或高度固定的场景
- **stretch**: 需要填满整个屏幕时使用
- **none**: 调试或特殊需求时使用
```typescript
// 推荐的设计稿尺寸
const commonSizes = {
fullHD: { width: 1920, height: 1080 }, // 全高清
ultraWide: { width: 2560, height: 1080 }, // 超宽屏
fourK: { width: 3840, height: 2160 }, // 4K
tablet: { width: 1024, height: 768 } // 平板
};
```
```typescript
// 在组件销毁时记得清理
const scaler = new ScreenScaler(config);
// 页面卸载前销毁
window.addEventListener('beforeunload', () => {
scaler.destroy();
});
```
```typescript
try {
const scaler = new ScreenScaler({
container: '#app',
designWidth: 1920,
designHeight: 1080
});
} catch (error) {
console.error('ScreenScaler 初始化失败:', error);
}
```
⚠️ **重要提示**:容器元素的 `border`、`padding` 等样式会影响尺寸计算,可能导致缩放计算错误。
```css
/* ❌ 避免在容器上使用这些样式 */
.container {
border: 2px solid
padding: 20px; /* 会影响内容区域计算 */
box-sizing: content-box; /* 默认盒模型会导致计算偏差 */
}
/* ✅ 推荐的容器样式 */
.container {
box-sizing: border-box; /* 使用 border-box 盒模型 */
/* 或者使用内部元素来添加装饰 */
}
/* ✅ 或者将装饰样式应用到父容器 */
.wrapper {
border: 2px solid
padding: 20px;
}
.container {
/* ScreenScaler 的目标容器保持简洁 */
}
```
在某些边界情况下,当内容尺寸介于需要滚动条和不需要滚动条之间时,缩放计算可能存在轻微误差。这通常发生在:
- **高度适配模式**:当缩放后的宽度刚好等于或略大于屏幕宽度时
- **宽度适配模式**:当缩放后的高度刚好等于或略大于屏幕高度时
**影响场景**:
```typescript
// 例如:设计尺寸为 1920x1080,屏幕尺寸为 1920x1000
// 在 height 模式下,缩放后宽度可能刚好触及滚动条临界点
const scaler = new ScreenScaler({
container: '#app',
designWidth: 1920,
designHeight: 1080,
mode: 'height' // 可能出现计算误差
});
```
**临时解决方案**:
- 避免使用刚好等于屏幕尺寸的设计稿
- 在边界情况下可以考虑使用 `auto` 模式
- 或者手动调整设计稿尺寸,增加一些缓冲空间
欢迎提交 Issue 和 Pull Request!
[](./LICENSE)
- [GitHub 仓库](https://github.com/scqilin/screen-scaler)
- [NPM 包](https://www.npmjs.com/package/@scqilin/screen-scaler)
- [示例演示](https://scqilin.github.io/screen-scaler/)