大屏自适应方案

大屏自适应方案

整体缩放

利用已有的工具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>
相关推荐
闲猫10 分钟前
Spring AI 对接Deepseek ChatModel 聊天对话
java·前端·spring
paopaokaka_luck1 小时前
英语单词学习系统的设计与实现(基于艾宾浩斯遗忘曲线的智能复习机制、语音朗读、多题型测试与错题自动收录、Echarts图形化分析)
vue.js·spring boot·后端·echarts
自信的未来2 小时前
JSON 工具|Web Worker 工程化打包 + 语法自动修复 + 多语言代码生成实战
java·前端·json
全栈前端老曹2 小时前
【MongoDB】安全与权限管理 —— 用户认证、角色权限、SSL 加密
前端·javascript·数据库·安全·mongodb·nosql·ssl
zhangxingchao3 小时前
AI大模型核心八:从 Agent Skill、长文档 RAG 到知识库更新与训练策略
前端·人工智能·后端
zhangxingchao4 小时前
AI大模型核心七:从 Workflow、RAG、记忆治理到幂等性
前端·人工智能·后端
gyx_这个杀手不太冷静4 小时前
Agent开发进阶指南(第 1 章):AI Agent 到底是什么?
前端·agent·ai编程
小小小小宇5 小时前
模型相关知识
前端
小小小小宇5 小时前
模型相关知识二
前端
IT_陈寒5 小时前
Python装饰器竟然偷偷改了函数名?这个坑我爬了三天
前端·人工智能·后端