Skip to content

数据大屏适配方案

推荐的方式就是:rem + vh/vw + flex 布局 搭配百分比布局,就完全够用了

rem 适配

rem 是相对于根元素 html 的字体大小的单位,rem 可以根据屏幕大小进行适配,但是 rem 会继承父元素的字体大小,所以需要设置根元素的字体大小,一般设置为 16px,这样 1rem 就等于 16px,这样就可以根据屏幕大小进行适配了

主要适配元素的字体大小,内边距和外边距等,下面的代码主要用于初始化根元素的字体大小

基本使用

ts
// 设计稿尺寸(px)
const DESIGN_WIDTH = 1920;
const DESIGN_HEIGHT = 1080;

// 基准字体大小(px)
const BASE_FONT_SIZE = 16;

// 最小缩放比例
const MIN_SCALE = 0.5;

/**
 * 初始化适配方案
 * @param {Object} options 配置选项
 * @param {Number} options.designWidth 设计稿宽度
 * @param {Number} options.designHeight 设计稿高度
 * @param {Number} options.baseFontSize 基准字体大小
 * @param {Number} options.minScale 最小缩放比例
 * @param {Boolean} options.widthHeightRatio 是否保持宽高比
 */
export function initScreenAdapter(options = {}) {
  const designWidth = options.designWidth || DESIGN_WIDTH;
  const designHeight = options.designHeight || DESIGN_HEIGHT;
  const baseFontSize = options.baseFontSize || BASE_FONT_SIZE;
  const minScale = options.minScale || MIN_SCALE;
  const widthHeightRatio = options.widthHeightRatio !== undefined ? options.widthHeightRatio : true;

  // 设置根元素字体大小
  function setRootFontSize() {
    const html = document.documentElement;
    const width = html.clientWidth;
    const height = html.clientHeight;

    // 计算缩放比例
    let scale = width / designWidth;

    // 是否保持宽高比
    if (widthHeightRatio) {
      const heightScale = height / designHeight;
      // 取最小的缩放比例,确保内容完全展示
      scale = Math.min(scale, heightScale);
    }

    // 确保缩放比例不小于最小值
    scale = Math.max(scale, minScale);

    // 设置根元素字体大小,基于rem的适配核心
    const fontSize = baseFontSize * scale;
    html.style.fontSize = `${fontSize}px`;

    // 添加调试信息
    console.log(`Screen adapted: scale=${scale}, fontSize=${fontSize}px`);

    // 设置缩放比例变量,用于vw/vh配合使用
    html.style.setProperty('--scale-ratio', scale);

    // 设置设计稿尺寸变量,方便组件内部使用
    html.style.setProperty('--design-width', `${designWidth}px`);
    html.style.setProperty('--design-height', `${designHeight}px`);
  }

  // 初始化时设置
  setRootFontSize();

  // 窗口大小变化时重新计算
  window.addEventListener('resize', setRootFontSize);

  // 返回清除函数
  return () => {
    window.removeEventListener('resize', setRootFontSize);
  };
}

/**
 * 将px转换为rem
 * @param {Number} px 像素值
 * @returns {String} rem值
 */
export function pxToRem(px) {
  if (typeof px === 'number' || !isNaN(parseFloat(px))) {
    return `${parseFloat(px) / BASE_FONT_SIZE}rem`;
  }
  return px; // 如果不是数字,原样返回
}

/**
 * 获取当前缩放比例
 * @returns {Number} 当前缩放比例
 */
export function getCurrentScale() {
  const scaleRatio = getComputedStyle(document.documentElement).getPropertyValue('--scale-ratio');
  return parseFloat(scaleRatio) || 1;
}

在需要适配的页面引入这个文件

ts
import { initScreenAdapter } from './utils/screen.js';

// 初始化屏幕适配
cleanupAdapter = initScreenAdapter({
  designWidth: 1920,
  designHeight: 1080,
  baseFontSize: 16,
  minScale: 0.5,
  widthHeightRatio: true,
});

VsCode 插件推荐

vh/vw 适配

vhvw 是相对于屏幕视口的百分比单位,vh 是相对于屏幕高度的百分比,vw 是相对于屏幕宽度的百分比,vhvw 可以根据屏幕大小进行适配。

主要用来适配元素容器的宽高

通过 scss 的函数可以实现将 px 转换为 vhvw

scss
// 使用 scss 的 math 函数,https://sass-lang.com/documentation/breaking-changes/slash-div
@use 'sass:math';

// 默认设计稿的宽度
$designWidth: 1920;
// 默认设计稿的高度
$designHeight: 1080;

// px 转为 vw 的函数
@function vw($px) {
  @return math.div($px, $designWidth) * 100vw;
}

// px 转为 vh 的函数
@function vh($px) {
  @return math.div($px, $designHeight) * 100vh;
}

定义 JS 样式处理函数(如果遇到了通过 JS 来定义样式的时候使用)

ts
// 定义设计稿的宽高
const designWidth = 1920;
const designHeight = 1080;

// px转vw
export const px2vw = (_px) => {
  return (_px * 100.0) / designWidth + 'vw';
};

export const px2vh = (_px) => {
  return (_px * 100.0) / designHeight + 'vh';
};

export const px2font = (_px) => {
  return (_px * 100.0) / designWidth + 'vw';
};

resize 事件

resize 事件是浏览器窗口大小发生变化时触发的事件,通过监听这个事件可以实现屏幕适配

ts
function resizeListener() {
  // 执行相关图表的适配逻辑
}
window.addEventListener('resize', resizeListener);

window.removeEventListener('resize', resizeListener);