Vue3 大屏适配组件(Scale / Rem 双方案一键切换)

  • 一键切换「整体 Scale 缩放」「Rem 等分适配」
  • 窗口自动监听 resize
  • 适配设计稿 1920*1080
  • Vue3 全局直接引入用

一、新建组件 ScreenAdapter.vue

xml 复制代码
<template>
   <div class="screen-adapter" :class="{ 'scale-mode': type === 'scale' }">
    <!-- 大屏所有内容插槽 -->
    <slot />
  </div>
</template>

<script setup>
import { onMounted, onUnmounted } from 'vue';

const props = defineProps({
  // 适配模式:scale / rem
  type: {
    type: String,
    default: 'scale', // 默认用不变形的scale
    validator: val => ['scale', 'rem'].includes(val)
  },
  // 设计稿宽高
  designWidth: {
    type: Number,
    default: 1920
  },
  designHeight: {
    type: Number,
    default: 1080
  }
});

let resizeFn = null;

// 1. Scale 整体缩放适配
function initScale() {
  const wrap = document.querySelector('.screen-adapter');
  if (!wrap) return;

  const clientW = document.documentElement.clientWidth;
  const clientH = document.documentElement.clientHeight;

  const scaleW = clientW / props.designWidth;
  const scaleH = clientH / props.designHeight;
  const scale = Math.min(scaleW, scaleH);

  wrap.style.transform = `translate(-50%, -50%) scale(${scale})`;
}

// 2. Rem 等分适配 设计稿px直接写rem
function initRem() {
  const clientW = document.documentElement.clientWidth;
  // 把屏幕分成100份 1rem = 1%屏幕宽
  document.documentElement.style.fontSize = clientW / 100 + 'px';
}

// 初始化适配
function adapterInit() {
  if (props.type === 'scale') {
    initScale();
  } else {
    initRem();
  }
}

onMounted(() => {
  adapterInit();
  resizeFn = adapterInit;
  window.addEventListener('resize', resizeFn);
});

onUnmounted(() => {
  window.removeEventListener('resize', resizeFn);
});
</script>

<style scoped>
html,
body {
  margin: 0;
  height: 100%;
  overflow: hidden;
}

.screen-adapter {
  position: fixed;
  left: 50%;
  top: 50%;
  transform-origin: 0 0;
}

/* Scale模式固定画布大小 */
.scale-mode {
  width: 1920px;
  height: 1080px;
}
</style>

二、页面中使用

1. 用 Scale 模式(推荐交付、地图大屏、不变形)

xml 复制代码
<template>
  <!-- 只用包一层,内部全部按1920*1080写px即可 -->
  <ScreenAdapter type="scale">
    <!-- 你的大屏页面内容 -->
    <div class="title">智慧公路大屏</div>
  </ScreenAdapter>
</template>

<script setup>
import ScreenAdapter from '@/components/ScreenAdapter.vue';
</script>

<style>
.title {
  /* 直接写px,不用任何换算 */
  font-size: 36px;
  width: 400px;
  height: 80px;
  line-height: 80px;
  text-align: center;
}
</style>

2. 切换 Rem 模式(内部项目、铺满全屏)

ini 复制代码
<ScreenAdapter type="rem">
  内部大屏内容
</ScreenAdapter>

Rem 用法规则设计稿多少 px,直接写多少 rem:

  • 设计稿 200px → width: 200rem
  • 字体 28px → font-size: 28rem不用计算、不用除以任何数。

三、两种模式使用场景记住

  1. type="scale"
  • 对外交付、政府大屏、Mapbox/L7/GIS 地图
  • 优点:不变形、像素级还原、适配所有屏
  • 写法:全部写 px
  1. type="rem"
  • 内部后台、运维大屏、工期紧
  • 优点:全屏无留白、开发快
  • 写法:设计稿 px 直接换成 rem

四、关键注意点

  1. Scale 模式下所有弹窗、ECharts、地图都要包在插槽里面,不要单独挂 body
  2. 不需要再写任何额外适配 JS,组件已经封装好监听 resize
  3. 以后所有大屏页面,直接套这个组件,改个 type 就能切换适配方案
相关推荐
库拉镜像AI牛牛1 小时前
短剧内容自动化生产:知漫剧工作室落地教程
大数据·服务器·前端·人工智能·语音识别
律宏阔1 小时前
Flutter 列表图片内存优化:CachedNetworkImage 与 ClipRRect 的取舍
前端·flutter
行者全栈架构师1 小时前
【鸿蒙心迹】相册文搜图工程化落地:HarmonyOS 7.0 端侧 AI 检索全链路实战与 5 个踩坑解法
前端
律宏阔1 小时前
Dart 3 Record:解决 Future.wait 异构返回值的类型问题
前端·flutter
Seraphina361 小时前
DVWA(XSS Reflected/Stored High,CSRF Low)
前端·xss·csrf
默_笙2 小时前
🍔 中间件不只是打日志:四个钩子、一次短路,和自带的工具
前端·javascript
程序员老赵3 小时前
Docker 部署 Dolibarr:轻松搭建开源 ERP/CRM 平台
运维·前端·后端
星禾元亨3 小时前
同一件事有三份资料,AI 该信哪一份?冲突判定、优先级链与处置流程
前端·人工智能
Dovis(誓平步青云)3 小时前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑
穆梓兰煊3 小时前
TS5.7 vs 裸JS:AI应用少3坑
前端