大屏自适应方案

大屏自适应方案

整体缩放

利用已有的工具vue3-scal等对大屏进行整体缩放,该方案很好,但不适用带有地图的项目,缩放后地图点击事件获取的坐标等会因为缩放产生偏移

局部缩放

仅针对某个容器盒子进行缩放,使用自定义指令的方案,使用起来方便快捷

typescript 复制代码
import type { App, DirectiveBinding } from 'vue';

/**
 * 缩放指令(设计稿固定1920*1080)
 * @directive 根据1920*1080设计稿自动缩放(v-scale)
 * @directive 支持多种基准点配置和缩放模式
 * @directive 默认无参数设计稿缩放,左上角基准点 会有压缩变形
 * @directive 参数ratio 固定比例缩放  value 为缩放比例
 * @directive 参数origin 按照设计稿比例,以高度比例缩放或者以宽度比例缩放  value 为 'X' 'Y' 默认是 'Y', 例如,浏览器高度小于设计稿高度 value 为 'Y'
 *
 * 修饰符 top-right top-center bottom-left bottom-right bottom-center center ,用于缩放后的盒子固定到哪个位置显示
 *
 * @example
 * v-scale - 默认设计稿缩放,左上角基准点
 * v-scale.top-right - 设计稿缩放,右上角基准点
 * v-scale:ratio="0.5" - 固定比例缩放
 * v-scale:origin.top-right="'Y'" - 无压缩缩放
 */
export function scaleDirective(app: App) {
  // 设计稿尺寸常量
  const DESIGN_WIDTH = 1920;
  const DESIGN_HEIGHT = 1080;

  // 统一的缩放指令
  app.directive('scale', {
    mounted(el: HTMLElement, binding: DirectiveBinding) {
      // 获取基准点配置
      const origin = getOriginFromBinding(binding);
      // 根据参数判断缩放模式
      if (binding.arg === 'ratio') {
        // 固定比例缩放模式
        const ratio = binding.value || 1;
        el.style.transform = `scale(${ratio})`;
        el.style.transformOrigin = origin;
        el.style.willChange = 'transform';
      } else if (binding.arg === 'origin') {
        // 无压缩变形缩放模式
        const updateScale = () => {
          const { innerWidth: vw, innerHeight: vh } = window;
          // 计算缩放比例(固定1920*1080设计稿)
          const scaleX = vw / DESIGN_WIDTH;
          const scaleY = vh / DESIGN_HEIGHT;
          const ratio = binding?.value === 'X' ? scaleX : scaleY;
          el.style.transform = `scale(${ratio})`;
          el.style.transformOrigin = origin;
          el.style.willChange = 'transform';
        };
        // 初始缩放
        updateScale();

        // 监听窗口大小变化
        window.addEventListener('resize', updateScale);

        // 存储更新函数,便于卸载时移除监听器
        (el as any)._scaleUpdate = updateScale;
      } else {
        // 默认设计稿缩放模式
        const updateScale = () => {
          const { innerWidth: vw, innerHeight: vh } = window;

          // 计算缩放比例(固定1920*1080设计稿)
          const scaleX = vw / DESIGN_WIDTH;
          const scaleY = vh / DESIGN_HEIGHT;

          // 应用缩放和基准点
          el.style.transform = `scale(${scaleX}, ${scaleY})`; // 这种缩放可能会变形
          // el.style.transform = `scale(${scaleY})`;// 保持宽高比缩放
          el.style.transformOrigin = origin;
          el.style.willChange = 'transform';
        };

        // 初始缩放
        updateScale();

        // 监听窗口大小变化
        window.addEventListener('resize', updateScale);

        // 存储更新函数,便于卸载时移除监听器
        (el as any)._scaleUpdate = updateScale;
      }
    },
    beforeUnmount(el: HTMLElement) {
      // 清理事件监听器(仅设计稿缩放模式需要)
      if ((el as any)._scaleUpdate) {
        window.removeEventListener('resize', (el as any)._scaleUpdate);
      }
    }
  });
}

/**
 * 从绑定对象获取基准点配置
 */
function getOriginFromBinding(binding: DirectiveBinding): string {
  // 从修饰符获取
  const modifiers = binding.modifiers;

  if (modifiers.topLeft || modifiers['top-left']) return 'top left';
  if (modifiers.topRight || modifiers['top-right']) return 'top right';
  if (modifiers.topCenter || modifiers['top-center']) return 'top center';
  if (modifiers.bottomLeft || modifiers['bottom-left']) return 'bottom left';
  if (modifiers.bottomRight || modifiers['bottom-right']) return 'bottom right';
  if (modifiers.bottomCenter || modifiers['bottom-center']) return 'bottom center';
  if (modifiers.center) return 'center';

  // 默认左上角
  return 'top left';
}

使用方法

typescript 复制代码
<template>
  // 这个会变形 因为缩放分别取的是高度和宽度的缩放比例
  <div v-scale.top-left class="panel-left">
    <PanelLeft />
  </div>
  // 这个不会变形
  <div v-scale:origin.top-right class="panel-right">
    <PanelRight />
  </div>
</template>
相关推荐
JustHappy19 小时前
古法编程秘籍(七):互联网到底是什么?把两台电脑怎么说话搞懂就够了
前端·后端·网络协议
snow@li19 小时前
SEO-文章标题:写文章时候,分类+主标题+大纲+解释 作为标题 / 不点进去也知道全文覆盖什么 / 标题即架构
前端
kyriewen20 小时前
Git Commit 前自动修复代码风格?配置 Husky + lint-staged,从此 CR 只聊逻辑
前端·git·面试
岁月宁静20 小时前
RAG 文档摄入全链路,从原理到生产落地
vue.js·人工智能·python
小和尚同志20 小时前
AI 自动化测试探索(一):Playwright MCP
前端·人工智能·aigc
老马识途2.020 小时前
在AI的帮助下理解spring的启动过程
java·前端·spring
徐小夕21 小时前
Loop Engineering 深度解析与实战指南(全网最全)
前端·算法·github
运筹vivo@21 小时前
Python ContextVar 底层机制与内存模型拆解
前端·数据库·python
#麻辣小龙虾#1 天前
基于vue3.0开发一款【固废与废气运维管理系统】(支持源码)
前端·vue.js·vue3
Cosolar1 天前
Docsify零构建文档站完全指南:从快速搭建到企业级部署
前端·开源·github