vue大屏适配方案

前言

开发过大屏的铁汁们应该知道,前期最头疼的就是大屏适配,由于大屏项目需要在市面上不是很常见的显示器上进行展示,所以要根据不同的尺寸进行适配,今天我将为大家分享的我使用的大屏适配方案,话不多说,直接上效果图。

效果图

上面所展示的只是其中一种模式,其中一共有四种模式,分别为1-居中留白(按比例伸缩);、2-居中留白(若不超出屏则不拉伸);、3-窄边铺满(长边滚动)、4-铺满全屏。


准备工作

首先,我们需要把使用到的依赖进行安装:

npm i element-resize-detector

npm i animejs

npm i jquery

然后,在vuex中定义以下变量和方法:

 state: {
    mode: 1, //1-居中留白(按比例伸缩); 2-居中留白(若不超出屏则不拉伸); 3-窄边铺满(长边滚动); 4-铺满全屏
    exw: 40,
    left: 0,
    top: 0,
    orderWork: {},
    warn: {},
    fontSize: 30,
  },
mutations: {
    increment(state, fs) {
      state.fontSize = fs;
    },
    exMode(state, mode) {
      state.mode = mode;
    },
    addExW(state, exw) {
      state.exw = exw;
    },
    addLeft(state, left) {
      state.left = left;
    },
    addTop(state, top) {
      state.top = top;
    },
  },

最后,需要在main.js中定义我们需要用到的全局方法:

// 以下为vue3的写法
import ElementResizeDetectorMaker from "element-resize-detector";
import anime from "animejs";
import jquery from "jquery";

const app = createApp(App);

app.config.globalProperties.$erd = ElementResizeDetectorMaker();
app.config.globalProperties.$anime = anime;
app.config.globalProperties.$jquery = jquery;

app.use(store).use(router).use(ElementPlus).mount("#app");


// 以下为vue2的写法
import Vue from 'vue'
import ElementResizeDetectorMaker from "element-resize-detector";
import anime from "animejs";
import jquery from "jquery";

Vue.prototype.$erd = ElementResizeDetectorMaker();
Vue.prototype.$anime = anime;
Vue.prototype.$jquery = $jquery;

实现

在App.vue中书写以下代码:

<template>
  <div id="app" :style="{ padding: pad }" class="hidden">
    <div ref="appBox" class="app-box" :style="{ width: tw, height: th }">
      <router-view />
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      pad: "0",
      w: 4160,
      h: 1248,
      fs: 30, //基本字体大小
      tw: "100%",
      th: "100%",
      speed: 2,
      ani: null,
    };
  },
  created() {},
  computed: {
    mode() {
      return this.$store.state.mode;
    },
  },
  watch: {
    mode() {
      this.$jquery(this.$refs.appBox).css("transform", "none");
      this.calc();
    },
  },
  mounted() {
    this.calc();
    this.$nextTick(() => {
      document.addEventListener("keydown", (e) => this.turnMode(e), true);
      this.$erd.listenTo(document.querySelector("html"), () => {
        this.$jquery(this.$refs.appBox).css("transform", "none");
        this.calc();
      });

      this.$store.commit("addExW", this.$jquery(this.$refs.ex).outerWidth());
    });
  },
  methods: {
    calc: function () {
      let fs = this.fs;
      let html = document.querySelector("html");
      let sc = this.w / this.h;
      let ww = parseFloat(
        document.defaultView.getComputedStyle(html, null).width
      );
      let wh = parseFloat(
        document.defaultView.getComputedStyle(html, null).height
      );
      if (this.mode <= 2) {
        let isEnough = this.h <= wh && this.w <= ww && this.mode == 2;
        if (isEnough) {
          this.pad = wh / 2 - this.h / 2 + "px " + (ww / 2 - this.w / 2) + "px";
        } else {
          if (sc < ww / wh) {
            this.pad = "0 " + (ww / 2 - (wh * sc) / 2) + "px";
            fs = (wh * fs) / this.h;
          } else {
            this.pad = wh / 2 - ww / sc / 2 + "px 0";
            fs = (ww * fs) / this.w;
          }
        }
        this.tw = "100%";
        this.th = "100%";

        this.$store.commit(
          "addLeft",
          isEnough
            ? ww / 2 - this.w / 2
            : sc < ww / wh
            ? ww / 2 - (wh * sc) / 2
            : 0
        );
        this.$store.commit(
          "addTop",
          isEnough
            ? wh / 2 - this.h / 2
            : sc < ww / wh
            ? 0
            : wh / 2 - ww / sc / 2
        );
      } else if (this.mode == 3) {
        this.pad = "0";
        if (sc < ww / wh) {
          this.tw = ww + "px";
          this.th = ww / sc + "px";
          fs = (ww * fs) / this.w;
          this.$nextTick(() => {
            document.removeEventListener(
              "keydown",
              (e) => this.trans(e, 1),
              true
            );
            document.addEventListener("keydown", (e) => this.trans(e, 1), true);
            this.mouseWheel(
              this.$refs.appBox,
              () => this.trans({ keyCode: 38 }, 1, 240),
              () => this.trans({ keyCode: 40 }, 1, 240)
            );
          });
        } else {
          this.tw = wh * sc + "px";
          this.th = wh + "px";
          fs = (wh * fs) / this.h;
          this.$nextTick(() => {
            document.removeEventListener(
              "keydown",
              (e) => this.trans(e, 0),
              true
            );
            document.addEventListener("keydown", (e) => this.trans(e, 0), true);
            this.mouseWheel(
              this.$refs.appBox,
              () => this.trans({ keyCode: 37 }, 0, 240),
              () => this.trans({ keyCode: 39 }, 0, 240)
            );
          });
        }

        this.$store.commit("addLeft", 0);
        this.$store.commit("addTop", 0);
      } else if (this.mode == 4) {
        this.pad = "0";
        this.tw = "100%";
        this.th = "100%";
        fs = sc < ww / wh ? (wh * fs) / this.h : (ww * fs) / this.w;

        this.$store.commit("addLeft", 0);
        this.$store.commit("addTop", 0);
      }
      html.style["font-size"] = parseInt(fs) + "px";
      this.$store.commit("increment", fs);
    },
    trans: function (e, s, st) {
      let ts = s
        ? this.$jquery(this.$refs.appBox).outerHeight()
        : this.$jquery(this.$refs.appBox).outerWidth();
      let ws = s
        ? this.$jquery(this.$refs.appBox).parent().outerHeight()
        : this.$jquery(this.$refs.appBox).parent().outerWidth();
      let event = e || window.event;
      let code = event.keyCode || event.which;
      let of = parseFloat(
        this.$jquery(this.$refs.appBox).css("transform")
          ? this.$jquery(this.$refs.appBox).css("transform").split(",")[
              s ? 5 : 4
            ] || 0
          : 0
      );
      let step = st || 120;
      if (code == (s ? 38 : 37) && of < 0) {
        let m = of + step > 0 ? 0 : of + step;
        this.run(this.$refs.appBox, s, m - of);
      } else if (code == (s ? 40 : 39) && ts + of - ws > 0) {
        let m = ts + (of - step) - ws > 0 ? of - step : ws - ts;
        this.run(this.$refs.appBox, s, m - of);
      }
      return false;
    },
    run: function (el, s, dis) {
      this.$anime.remove(el);
      this.ani = null;
      let obj = {
        targets: el,
        duration: parseInt(Math.abs(dis) / this.speed),
        easing: "linear",
      };
      if (s) {
        obj.translateY = "+=" + dis;
      } else {
        obj.translateX = "+=" + dis;
      }
      this.ani = this.$anime(obj);
    },
    mouseWheel: function (ele, fn1, fn2) {
      function wheelDelta(ev) {
        // 使火狐浏览器 和标准浏览器的 滚轮数值返回一致
        return ev.wheelDelta ? ev.wheelDelta : ev.detail * -40;
      }
      function clack(ev) {
        if (wheelDelta(ev) < 0) {
          fn2.call(ele);
        } else {
          fn1.call(ele);
        }
      }
      if (navigator.userAgent.match(/Firefox/gi)) {
        ele.addEventListener("DOMMouseScroll", function (ev) {
          // 火狐浏览器
          ev = ev || window.event;
          ev.preventDefault();
          clack(ev);
        });
      } else {
        //其他浏览器 chrome ie
        if (ele.addEventListener) {
          ele.addEventListener(
            "mousewheel",
            function (ev) {
              ev = ev || window.event;
              ev.returnValue ? (ev.returnValue = false) : ev.preventDefault();
              clack(ev);
            },
            { passive: false }
          );
        } else {
          ele.attachEvent("onmousewheel", function (ev) {
            ev = ev || window.event;
            if (ev.returnValue) {
              ev.returnValue = false;
            }
            clack(ev);
          });
        }
      }
    },
    turnMode: function (e) {
      let event = e || window.event;
      let code = event.keyCode || event.which;

      let obj = {
        49: 1,
        50: 3,
      };
      let mode = obj[code] || this.mode;
      this.$store.commit("exMode", mode);
    },
    exBtn: function () {
      let mode = this.mode == 1 ? 3 : 1;
      this.$store.commit("exMode", mode);
    },
  },
};
</script>
<style scoped>
.app-box {
  box-sizing: border-box;
  overflow: hidden;
  background-size: 100% 100%;
  user-select: none;
  background-color: darkorange;
}
</style>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #fff;
  background-color: #fff;

  width: 100vw;
  height: 100vh;
  box-sizing: border-box;
  font-size: 1rem;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/726724.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL Server和Server启动程序(一)

MySQL Server mysqld&#xff0c;也称为MySQL Server&#xff0c;是一个单线程多任务的程序&#xff0c;它在MySQL安装中执行大部分工作。它不会生成额外的进程。MySQL Server管理对包含数据库和表的MySQL数据目录的访问。数据目录也是其他信息&#xff08;如日志文件和状态文…

Windows Server配置iSCSI,做ESXI共享存储

1&#xff1a;使用一台Windows Server2022主机配置iSCSI&#xff0c;准备给ESXI8.0做共享存储使用。有一些ESXI的功能必须使用共享存储才行&#xff0c;比如HA的功能。 2&#xff1a;登录系统&#xff0c;点击添加角色和功能。 3&#xff1a;之后一路下一步&#xff0c;在选择…

健身器械行业外贸ERP管理降本增效解决方案

随着经济的迅速发展&#xff0c;以及健身锻炼的普及&#xff0c;人们对健身器材的需求量也在大幅度增加。欧美市场增长迅猛&#xff0c;家用健身器材热度飙升&#xff0c;尤其是跑步机、健身单车等轻便型家用健身器材&#xff0c;备受消费者青睐。 出口的主要国家包括&#xf…

Git 和 TortoiseGit 安装和配置(图文详解)

使用git&#xff0c;需要在Windows上需要安装两个软件&#xff1a;1&#xff09;Git 2&#xff09;TortoiseGit 若需要&#xff0c;可以下载TortoiseGit汉化语言包。 注意&#xff1a;tortoiseGit是在安装了Git的基础上运行的&#xff0c;所以需要先安装Git&#xff0c;后安装…

智慧校园导航系统:技术驱动下的校园管理与师生体验革新

随着智慧校园建设的不断推进&#xff0c;校园导航系统作为提升校园管理效率、优化师生出行体验的重要工具&#xff0c;正逐渐成为各大高校的标配。本文将重点介绍维小帮智慧校园导航系统&#xff0c;如何通过创新的设计和功能&#xff0c;解决校园导航中的种种难题&#xff0c;…

1分钟带你部署本地Llama3大模型

介绍 LLaMa 3由Meta于2024年4月18日正式发布&#xff0c;这一版本是对先前LLaMa系列的重大升级。新发布的模型包括8B&#xff08;80亿参数&#xff09;和70B&#xff08;700亿参数&#xff09;两个版本&#xff0c;这两个版本在一系列行业标准基准测试中展示了最先进的性能。 从…

低版本火狐浏览器报错:class is a reserved identifier

低版本火狐浏览器报错&#xff1a;class is a reserved identifier 原因&#xff1a;react-dnd&#xff0c;dnd-core 等node包的相关依赖有过更新&#xff0c;使得在低版本火狐浏览器中不支持 class 解决方法&#xff1a;在使用webpack打包构建时&#xff0c;编译排除node_modu…

7,KQM模块的驱动

1&#xff0c;查资料&#xff0c;查模块的通信接口&#xff08;单片机和模块之间采用什么方式通信&#xff09;硬件接口&#xff0c;驱动方式(串口驱动用串口发送接收PC10&#xff0c;PC11) 只用了三个脚&#xff1a;VCC &#xff27;&#xff2e;&#xff24; &#xff34;&…

pdf只要前几页,pdf怎么只要前几页

在现代办公和学习环境中&#xff0c;PDF文件已成为我们日常处理信息的重要工具。然而&#xff0c;有时我们并不需要整个PDF文件的内容&#xff0c;而只是其中的几页。那么&#xff0c;如何高效地提取PDF文件中的特定页面呢&#xff1f;本文将为您介绍几种实用的方法。 打开 “ …

Python在Word文档中插入图片,设置文字环绕

在Word文档中插入图片能够提供更直观的信息&#xff0c;使文档变得更加生动和具有吸引力&#xff0c;从而增强阅读体验。插入图片时&#xff0c;我们还可以调整图片大小&#xff0c;以及设置合适的文字环绕方式&#xff0c;确保文字和图片之间的排版不会混乱&#xff0c;达到最…

SVN学习(002 svn冲突解决)

尚硅谷SVN高级教程(svn操作详解) 总时长 4:53:00 共72P 此文章包含第20p-第p29的内容 冲突 产生冲突的操作 &#xff08;第一种 相互不影响的操作&#xff09; 用户1修改第二行 用户2修改第四行 用户1提交 用户2提交&#xff0c;提交的时候会提示版本已过时 这时将用…

树莓派4B学习笔记11:PC端网线SSH连接树莓派_网线连接请求超时问题解决

今日继续学习树莓派4B 4G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1&#xff1a; 今日学习使用网线连接树莓派&#xff0c;网线可以提供更…

STM32学习笔记(六)--引脚重映射详解

STM32F103C8T6引脚定义&#xff1a; 在STM32微控制器中&#xff0c;外设引脚的复用功能&#xff08;Alternate Function&#xff0c;AF&#xff09;有时会出现冲突&#xff0c;例如当USART2_CTS和TIM2_CH1同时需要使用相同的引脚时。此时&#xff0c;可以通过引脚重映射功能&am…

【方法】如何在ZIP文件中添加或删除文件?

ZIP文件是我们在日常工作中常用的压缩格式。有时候&#xff0c;我们需要在已有的ZIP文件中添加或删除文件。下面来看看具体如何操作。 首先&#xff0c;我们要确保安装了ZIP文件管理软件&#xff0c;如WinRAR、7-Zip或Windows自带的文件资源管理器。 添加文件&#xff1a; 使…

redhat-devtoolset备忘

参考&#xff1a; User Guide Red Hat Developer Toolset 12 | Red Hat Customer Portal https://access.redhat.com/documentation/en-us/red_hat_developer_toolset/12/html-single/user_guide/index Red Hat Devtoolset 是 Red Hat 提供的一组开发工具集合&#xff0c;主要用…

1994年美国人口普查数据 分类预测与集成学习

对于分类预测学习任务&#xff0c;从指定的数据源读取数据&#xff0c;对数据进行必要的处理&#xff0c;选取合适的特征&#xff0c;构造分类模型&#xff0c;确定一个人的年收入是否超过50K。 数据来源&#xff1a;1994年美国人口普查数据库。数据存放在data目录中&#xff0…

【K8s】专题五(5):Kubernetes 配置之热更新工具 Reloader

以下内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01;如果对您有帮助&#xff0c;烦请点赞、关注、转发&#xff01;欢迎扫码关注个人公众号&#xff01; 目录 一、基本介绍 二、工作原理 三、部署方法 四、使用方法 一、基本介绍 Reloader 是一个用…

基于STM32和人工智能的智能农业监测系统

目录 引言环境准备智能农业监测系统基础代码实现&#xff1a;实现智能农业监测系统 4.1 数据采集模块4.2 数据处理与分析4.3 控制系统4.4 用户界面与数据可视化应用场景&#xff1a;智能农业管理与优化问题解决方案与优化收尾与总结 1. 引言 智能农业监测系统通过结合STM32嵌…

手机照片同步到群辉NAS

手机中最宝贵的数据莫过于“照片”,这些包含美好回忆的数字信息是不能丢失的。NAS的作用就是存储,其中最重要的一项功能就是手机照片的同步。 在群辉NAS丰富的套件中,“Synology Photos”就是解决这个功能,今天我们来看看如何操作。 一、安装套件 打开群晖套件中心→所有…

【拉曼光谱数据处理2024】拉曼数据处理的主要问题和常见方法

一、主要问题分类与解决方法比较 二、常见问题在光谱图上的显示 1、从上到下依次是 理想光谱 理想光谱宇宙尖峰 理想光谱高斯噪声 理想光谱S型背景噪声 理想光谱尖峰高斯噪声S型背景噪声