大屏应用中的动态缩放适配工具

ScreenScaler

一个强大的大屏缩放适配器,专为大屏应用开发设计。支持多种缩放模式,提供完整的 TypeScript 类型支持。

✨ 特性

  • 🎯 多种缩放模式: 支持自动、宽度、高度、拉伸、无缩放五种模式
  • 📱 响应式设计: 自动响应窗口大小变化
  • 🎨 设计稿适配: 支持任意设计稿尺寸
  • 💪 TypeScript: 完整的类型定义支持
  • 🚀 轻量级: 无依赖,压缩后小于 10KB
  • 🔧 易于使用: 简单的 API 设计
  • 🎛️ 灵活配置: 丰富的配置选项
  • 📊 实时信息: 提供详细的缩放信息回调

📦 安装

bash 复制代码
npm install @scqilin/screen-scaler
bash 复制代码
yarn add @scqilin/screen-scaler
bash 复制代码
pnpm add @scqilin/screen-scaler

🚀 快速开始

ES Module

typescript 复制代码
import { ScreenScaler } from '@scqilin/screen-scaler';

const scaler = new ScreenScaler({
  container: '#app',
  designWidth: 1920,
  designHeight: 1080,
  mode: 'auto'
});

CommonJS

javascript 复制代码
const { ScreenScaler } = require('@scqilin/screen-scaler');

const scaler = new ScreenScaler({
  container: document.getElementById('app'),
  designWidth: 1920,
  designHeight: 1080,
  mode: 'auto'
});

UMD (浏览器)

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>

📖 API 文档

构造函数

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); // 当前缩放比例
updateConfig(config: Partial<ScreenScalerConfig>): void

更新配置。

typescript 复制代码
scaler.updateConfig({
  designWidth: 1600,
  designHeight: 900,
  mode: 'width'
});
resize(): void

手动触发重新缩放。

typescript 复制代码
scaler.resize();
destroy(): void

销毁实例,清理事件监听器。

typescript 复制代码
scaler.destroy();
isDestroyed(): boolean

检查实例是否已销毁。

typescript 复制代码
if (!scaler.isDestroyed()) {
  scaler.resize();
}

缩放信息 (ScaleInfo)

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 3 集成

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>

React 集成

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 
  });
}

🎯 最佳实践

1. 选择合适的缩放模式

  • auto: 大多数情况下的最佳选择,保持设计稿比例
  • width: 适用于横向滚动或宽度固定的场景
  • height: 适用于纵向滚动或高度固定的场景
  • stretch: 需要填满整个屏幕时使用
  • none: 调试或特殊需求时使用

2. 合理设置设计稿尺寸

typescript 复制代码
// 推荐的设计稿尺寸
const commonSizes = {
  fullHD: { width: 1920, height: 1080 },    // 全高清
  ultraWide: { width: 2560, height: 1080 }, // 超宽屏
  fourK: { width: 3840, height: 2160 },     // 4K
  tablet: { width: 1024, height: 768 }      // 平板
};

3. 性能优化

typescript 复制代码
// 在组件销毁时记得清理
const scaler = new ScreenScaler(config);

// 页面卸载前销毁
window.addEventListener('beforeunload', () => {
  scaler.destroy();
});

4. 错误处理

typescript 复制代码
try {
  const scaler = new ScreenScaler({
    container: '#app',
    designWidth: 1920,
    designHeight: 1080
  });
} catch (error) {
  console.error('ScreenScaler 初始化失败:', error);
}

5. 容器样式注意事项

⚠️ 重要提示 :容器元素的 borderpadding 等样式会影响尺寸计算,可能导致缩放计算错误。

css 复制代码
/* ❌ 避免在容器上使用这些样式 */
.container {
  border: 2px solid #ccc;     /* 会影响宽高计算 */
  padding: 20px;              /* 会影响内容区域计算 */
  box-sizing: content-box;     /* 默认盒模型会导致计算偏差 */
}

/* ✅ 推荐的容器样式 */
.container {
  box-sizing: border-box;      /* 使用 border-box 盒模型 */
  /* 或者使用内部元素来添加装饰 */
}

/* ✅ 或者将装饰样式应用到父容器 */
.wrapper {
  border: 2px solid #ccc;
  padding: 20px;
}
.container {
  /* ScreenScaler 的目标容器保持简洁 */
}

🐛 已知问题

滚动条边界计算误差

在某些边界情况下,当内容尺寸介于需要滚动条和不需要滚动条之间时,缩放计算可能存在轻微误差。这通常发生在:

  • 高度适配模式:当缩放后的宽度刚好等于或略大于屏幕宽度时
  • 宽度适配模式:当缩放后的高度刚好等于或略大于屏幕高度时

影响场景

typescript 复制代码
// 例如:设计尺寸为 1920x1080,屏幕尺寸为 1920x1000
// 在 height 模式下,缩放后宽度可能刚好触及滚动条临界点
const scaler = new ScreenScaler({
  container: '#app',
  designWidth: 1920,
  designHeight: 1080,
  mode: 'height'  // 可能出现计算误差
});

临时解决方案

  • 避免使用刚好等于屏幕尺寸的设计稿
  • 在边界情况下可以考虑使用 auto 模式
  • 或者手动调整设计稿尺寸,增加一些缓冲空间

🤝 贡献

欢迎提交 Issue 和 Pull Request!

📄 许可证

MIT License

🔗 相关链接

相关推荐
喝拿铁写前端3 分钟前
技术是决策与代价的平衡 —— 超大系统从 Vue 2 向 Vue 3 演进的思考
前端·vue.js·架构
拾光拾趣录10 分钟前
虚拟滚动 + 加载:让万级列表丝般顺滑
前端·javascript
然我19 分钟前
数组的创建与遍历:从入门到精通,这些坑你踩过吗? 🧐
前端·javascript·面试
豆豆(设计前端)27 分钟前
如何成为高级前端开发者:系统化成长路径。
前端·javascript·vue.js·面试·electron
今天你写算法了吗31 分钟前
ScratchCard刮刮卡交互元素的实现
前端·javascript
FogLetter1 小时前
深入浅出 JavaScript 数组:从基础到高级玩法
前端·javascript
一小池勺1 小时前
🚀 clsx vs shadcn/ui的cn函数:前端类名拼接工具大PK
前端
lens941 小时前
RSC、SSR傻傻分不清?一文搞懂所有渲染概念!
前端·next.js
spionbo1 小时前
前端部署VuePress Theme Hope主题部署到gitlab,使用pnpm构建,再同步到netlify绑定腾讯云域名实现
前端
小华同学ai1 小时前
惊喜! Github 10k+ star 的国产流程图框架,LogicFlow 能解你的图编辑痛点?
前端·后端·github