大屏数据可视化解决方案

一、 分辨率

分辨率 典型设备 字体大小 布局策略 单位选择
1920×1080 普通台式显示器、高端笔记本、会议平板 14px-18px 响应式栅格 rem、%、px
2560×1440 普通台式显示器、高端笔记本、会议平板 14px-18px 响应式栅格 rem、%、px
3840×2160 专业显示器、指挥中心、展厅LED/液晶拼接屏、数字标牌、电视墙 >=24px,甚至40px+ 固定比例布局+视口单位 vw/vh、vmin
5120×2880 专业显示器、指挥中心、展厅LED/液晶拼接屏、数字标牌、电视墙 >=24px,甚至40px+ 固定比例布局+视口单位 vw/vh、vmin
7680×4320 专业显示器、指挥中心、展厅LED/液晶拼接屏、数字标牌、电视墙 >=24px,甚至40px+ 固定比例布局+视口单位 vw/vh、vmin
拼接屏(如 3840×1080 多屏) 专业显示器、指挥中心、展厅LED/液晶拼接屏、数字标牌、电视墙 >=24px,甚至40px+ 固定比例布局+视口单位 vw/vh、vmin

超大屏

常见分辨率

  • 3840×2160(4K UHD)

  • 5120×2880(5K)

  • 7680×4320(8K)

  • 或拼接屏(如 3840×1080 多屏)

典型设备

  • 专业显示器、指挥中心、展厅LED/液晶拼接屏、数字标牌、电视墙

字体大小

  • =24px,甚至40px+

布局策略

  • 固定比例布局+视口单位

单位选择

  • vw/vh、vmin

开发注意点

  • 禁用滚动条:超大屏通常是全屏展示,因此需要禁用滚动条

  • 使用vw/vh + clamp() 控制元素大小,确保在4k/8k下比例协调

  • 测试正式设备: 浏览器模拟器无法还原观看距离和像素密度。

  • 1px边框在8k屏上可能看不到,建议使用2px+

二 、开发方案

1. 等比例大屏/超大屏

  • transform: scale() + 容器包裹(最稳定)

2. 超大长屏幕

  • 场景 1:超宽拼接屏(如 3840×1080、5760×1080)------ 常见于数据看板、监控墙

垂直方向:严格按 1080px 高度布局(保证字体、组件高度可读)

水平方向:使用 响应式栅格 / 弹性布局 / 动态列数,填满整个宽度

实现:

【1】禁用全局 scale,改用 vw + rem

复制代码
/* 根字体基于高度固定,避免文字随宽度无限变大 */

html {
  <!-- 16px × (当前屏幕高度 / 设计稿高度) 如果屏幕分辨率高度不是1080,可以直接替换这个公式 -->
  font-size: calc(1080px / 1080 * 16px); /* 固定为 16px,或根据需求微调 */
}

/* 主容器高度固定为 1080px,宽度 100% */
.dashboard {
  width: 100vw;
  height: 1080px; /* 关键:高度锁定 */
  overflow: hidden;
}

【2】水平区域使用弹性布局或 CSS Grid

复制代码
<template>
  <div class="dashboard">
    <Header class="header" />
    <div class="content">
      <!-- 使用 Grid 自动分配列宽 -->
      <ChartCard v-for="item in charts" :key="item.id" />
    </div>
  </div>

</template>
<style scoped>
.content {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); /* 自适应列数 */
  height: calc(100% - 80px);
  gap: 20px;
  padding: 20px;
}

</style>

【3】关键元素使用 vh 控制高度(可选)

复制代码
.card {
  height: 30vh; /* 约 324px @1080p,比例合理 */
}

三 、缩放方案-代码封装

screenAdaptive.ts

复制代码
interface AdaptiveOptions {
  designWidth?: number;     // 设计稿宽度,默认 1920
  designHeight?: number;    // 设计稿高度,默认 1080
  mode?: 'width' | 'height' | 'auto' | 'widthAndHeight'; // 缩放模式
  containerSelector?: string; // 容器选择器,默认 .screen
  transformOrigin?: string; // transform-origin,默认 top left
};
//定义默认配置项
const DefaultContainerSelector = '.screen';
const DEFAULT_OPTIONS: Required<AdaptiveOptions> = {
  designWidth: 1920,
  designHeight: 1080,
  mode: 'auto', // auto = 等比缩放(取 min(scaleX, scaleY))
  containerSelector: DefaultContainerSelector,
  transformOrigin: 'top left'
};

let resizeTimer: number | null = null;

export const initScreenAdaptive = (options: AdaptiveOptions = {}) => {
  const opts = { ...DEFAULT_OPTIONS, ...options };
  const { designWidth, designHeight, mode, containerSelector, transformOrigin } = opts;

  const adapt = () => {
    const container = document.querySelector<HTMLElement>(containerSelector);
    if (!container) return;

    const screenWidth = window.innerWidth;
    const screenHeight = window.innerHeight;

    let scale: number = 1;
    let scaleX: number = 1;
    let scaleY: number = 1;
    if (mode === 'width') {
      // 仅按宽度缩放(高度可能溢出)
      scale = screenWidth / designWidth;
    } else if (mode === 'height') {
      // 仅按高度缩放(宽度可能溢出)
      scale = screenHeight / designHeight;
    } else if (mode === 'widthAndHeight') {
      // 宽高都按比例缩放
      scaleX = screenWidth / designWidth;
      scaleY = screenHeight / designHeight;
    } else {
      // auto: 等比缩放,保证完整显示(类似 background-size: contain)
      const scaleX = screenWidth / designWidth;
      const scaleY = screenHeight / designHeight;
      scale = Math.min(scaleX, scaleY);
    }
    
    // 设置容器尺寸和缩放
    container.style.width = `${designWidth}px`;
    container.style.height = `${designHeight}px`;
    container.style.transform = mode === 'widthAndHeight' ? `scale(${scaleX}, ${scaleY})` : `scale(${scale})`;
    container.style.transformOrigin = transformOrigin;
  };

  // 首次执行
  adapt();

  // 监听窗口变化(带防抖)
  const onResize = () => {
    if (resizeTimer) {
      clearTimeout(resizeTimer);
    }
    resizeTimer = window.setTimeout(adapt, 100);
  };

  window.addEventListener('resize', onResize);

  // 返回销毁函数(可选)
  return () => {
    window.removeEventListener('resize', onResize);
    if (resizeTimer) clearTimeout(resizeTimer);
  };
}

// 将 页面坐标(clientX, clientY)转换为 设计稿坐标
export const getDesignCoords = (
  clientX: number,
  clientY: number,
  containerSelector = DefaultContainerSelector
): { x: number; y: number } => {
  const container = document.querySelector<HTMLElement>(containerSelector);
  if (!container) {
    return { x: clientX, y: clientY };
  }

  // 获取容器的边界和 transform 值
  const rect = container.getBoundingClientRect();
  const style = window.getComputedStyle(container);
  const transform = style.transform;

  let scaleX = 1;
  let scaleY = 1;

  if (transform && transform !== 'none') {
    // 解析 matrix( a, b, c, d, tx, ty )
    const matrix = new DOMMatrix(transform);
    scaleX = matrix.a; // scaleX
    scaleY = matrix.d; // scaleY
  }

  // 将页面坐标转换为容器内的原始设计稿坐标
  const x = (clientX - rect.left) / scaleX;
  const y = (clientY - rect.top) / scaleY;

  return { x, y };
}

使用方法:

【1】引入

复制代码
import { initScreenAdaptive } from './screenAdaptive';

【2】使用

复制代码
//定义设计稿的分辨率
const DesignDraftWidth = 1920;
const DesignDraftHeight = 1080;

//dom加载完成后,进行可视窗口大小判断
if (window.innerWidth > DesignDraftWidth) {
    initScreenAdaptive({
    	 designWidth: DesignDraftWidth,
      designHeight: DesignDraftHeight,
      mode: 'height',
      transformOrigin: 'center'
    });
} 

//div容器需要配置默认样式名称.screen(也可以自定义)
<div class='screen'>
	/* 这里存放需要缩放的dom元素 */
</div>

注意

对于大多数组件库的弹框、抽屉等组件默认绑定到是body标签上,故无法进行缩放,只有把这些组件绑定到你的包裹容器(.srceen)才可以实现缩放

相关推荐
极光代码工作室3 天前
基于数据仓库的电商数据分析平台
大数据·hadoop·python·spark·数据可视化
柳杉3 天前
我用Threejs 搓了一个 3D 中国地图设计器,开箱即用
前端·three.js·数据可视化
小的博客5 天前
Oh-My-Posh安装及使用
学习·数据可视化
周庆猛8 天前
Babylon.js 多灯场景在 Windows 上报错:VERTEX shader uniform block count exceeds GL_MAX_VE
前端·数据可视化
一晌小贪欢8 天前
第26节:自动化办公——利用 Python 自动生成动态分析报告 (PPT/PDF)
开发语言·python·数据分析·自动化·powerpoint·pandas·数据可视化
山海鲸实战案例分享8 天前
【数字孪生实战案例】怎样为二维孪生组件新增测绘功能?~山海鲸可视化
数字孪生·数据可视化·零代码·测绘·实战案例·山海鲸可视化·二维孪生
小哈机器人8 天前
Phantom Bridge:一个基于WebRTC的ROS2远程可视化与遥操作工具
机器人·webrtc·数据可视化
极光代码工作室9 天前
基于数据分析的电影票房预测系统
大数据·python·数据分析·spark·数据可视化
一晌小贪欢10 天前
第22节:相关性分析——协方差、相关系数与热力图解读
开发语言·python·数据分析·pandas·数据可视化