vue3大屏实现;使用使用CSS Grid实现大屏

发布于:2025-02-11 ⋅ 阅读:(38) ⋅ 点赞:(0)

一、效果

1.效果

  • 方案:采用CSS的Grid布局,实现首页大屏模块划分和自适应功能;

  • 布局: 大屏主要内容,高宽比是1920*1080;即16:9的宽高比按照该比例,自适应放大缩小;直至放大到高度撑满或者宽度先撑满为止;未撑满的那一方直接留下黑色背影即可。

  • 全屏功能 :代码里自带逻辑

  • 优点: 该方案可以保证大屏的页面比列协调,不会变成扁平或者瘦高。

  • 大屏布局
    这里是引用

2.使用CSS Grid

CSS Grid Generator工具

使用
在这里插入图片描述

3.插件

使用element-resize-detector监听尺寸变化

"element-resize-detector": "^1.2.4",

4.html代码

<template>
  <div ref="digitalEvaluationContent"
    :class="['page-view', 'digital-evaluation-content', fullScreen ? 'full-screen' : '']">
    <div ref="digitalEvaluation" class="digital-evaluation">
      <div class="parent">
        <div class="div1">
          <div class="title_name">div1系统名称XXXXX</div>
          <div class="time_box">
            <span>
              <el-icon :size="16" class="el-icon-class">
                <Calendar />
              </el-icon>
              <span style="display: inline-block; width: 170px;">{{currentDateTime}}</span>
            </span>

            <span class="ml cursor" style="color: blue;" @click="fullScreenFun">
              <el-icon :size="16" class="el-icon-class">
                <FullScreen />
              </el-icon>
              {{ fullScreen ? '退出' : '' }}全屏
            </span>

          </div>
        </div>
        <div class="div2">
          div2
        </div>
        <div class="div3">
          div3:css等设置依旧生效-这里有个 margin-bottom: 60px;
          <div>1</div>
        </div>
        <div class="div4">
          div4
        </div>
        <div class="div5">
          div5
        </div>
        <div class="div6">
          div6-依旧可以设置高度 height: 100px
        </div>
        <div class="div7">
          div7
        </div>
        <div class="div8">
          div8是自定义的一个div
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, unref, onMounted, onBeforeUnmount, onUnmounted } from 'vue'
import { Calendar, FullScreen, } from '@element-plus/icons-vue'
import elementResizeDetectorMaker from 'element-resize-detector'

const digitalEvaluationContent = ref(null)
const digitalEvaluation = ref(null)
let currentDateTime = ref('')
const fullScreen = ref(false)

const formatDateTime = (dateTime) => {
  const year = dateTime.getFullYear();
  const month = ('0' + (dateTime.getMonth() + 1)).slice(-2);
  const date = ('0' + dateTime.getDate()).slice(-2);
  const hours = ('0' + dateTime.getHours()).slice(-2);
  const minutes = ('0' + dateTime.getMinutes()).slice(-2);
  const seconds = ('0' + dateTime.getSeconds()).slice(-2);
  return `${year}年${month}月${date}日 ${hours}:${minutes}:${seconds}`
}

// 自适应
function resizeContent() {
  const erd = elementResizeDetectorMaker()
  erd.listenTo(unref(digitalEvaluationContent), () => {
    // * 默认缩放值
    const scale = {
      width: '1',
      height: '1'
    }

    // * 设计稿尺寸(px)
    const baseWidth = 1920
    const baseHeight = 1080

    // * 需保持的比例(默认16:9)
    const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))

    const box = unref(digitalEvaluationContent)

    const appRef = unref(digitalEvaluation)
    if (!appRef) return
    // 当前宽高比
    const currentRate = parseFloat((box.clientWidth / box.clientHeight).toFixed(5))
    if (appRef) {
      if (currentRate > baseProportion) {
        // 表示更宽
        scale.width = ((box.clientHeight * baseProportion) / baseWidth).toFixed(5)
        scale.height = (box.clientHeight / baseHeight).toFixed(5)
      } else {
        // 表示更高
        scale.height = (box.clientWidth / baseProportion / baseHeight).toFixed(5)
        scale.width = (box.clientWidth / baseWidth).toFixed(5)
      }
      appRef.style.transform = `scale(${scale.width}, ${scale.height})`
    }
  })
}

// 全屏
function fullScreenFun() {
  fullScreen.value = !fullScreen.value
  if (fullScreen.value) {
    if (document.documentElement.RequestFullScreen) {
      document.documentElement.RequestFullScreen()
    }
    // 兼容火狐
    // console.log(document.documentElement.mozRequestFullScreen)
    if (document.documentElement.mozRequestFullScreen) {
      document.documentElement.mozRequestFullScreen()
    }
    // 兼容谷歌等可以webkitRequestFullScreen也可以webkitRequestFullscreen
    if (document.documentElement.webkitRequestFullScreen) {
      document.documentElement.webkitRequestFullScreen()
    }
    // 兼容IE,只能写msRequestFullscreen
    if (document.documentElement.msRequestFullscreen) {
      document.documentElement.msRequestFullscreen()
    }
  } else {
    if (document.exitFullScreen) {
      document.exitFullscreen()
    }
    // 兼容火狐
    // console.log(document.mozExitFullScreen)
    if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen()
    }
    // 兼容谷歌等
    if (document.webkitExitFullscreen) {
      document.webkitExitFullscreen()
    }
    // 兼容IE
    if (document.msExitFullscreen) {
      document.msExitFullscreen()
    }
  }
}

// 监听尺寸变化
const listenResize = () => {
  if (!checkFull()) {
    fullScreen.value = false
    // console.log('退出全屏');
  }
};

// 判断全屏
const checkFull = () => {
  //判断浏览器是否处于全屏状态 (需要考虑兼容问题)
  let isFull =
    //火狐浏览器
    document.mozFullScreen ||
    document.fullScreen ||
    //谷歌浏览器及Webkit内核浏览器
    document.webkitIsFullScreen ||
    document.webkitRequestFullScreen ||
    document.mozRequestFullScreen ||
    document.msFullscreenEnabled;
  if (isFull === undefined) {
    isFull = false;
  }
  return isFull;
};

// 五分钟轮询
let timer = ref(undefined) // 计时器

// 系统标题
const systemName = ref("")
onMounted(() => {
  window.addEventListener("resize", listenResize);
  systemName.value = localStorage.getItem("systemName") || "调度网络综合网管"
  currentDateTime.value = formatDateTime(new Date())
  setInterval(() => {
    currentDateTime.value = formatDateTime(new Date())
  }, 1000);
  resizeContent()
})

onBeforeUnmount(() => {
  // 清除定时器
  clearInterval(timer.value)
});

onUnmounted(() => {
  window.removeEventListener("resize", listenResize);
})
</script>
<style lang="scss" scoped src="./index.scss"></style>

5.index.scss代码

.pall {
  padding: 16px 16px;
}

.pr {
  padding-right: 16px;
}

.pl {
  padding-left: 16px;
}

.pt {
  padding-top: 12px;
}

.pb {
  padding-bottom: 12px;
}

.mr {
  margin-right: 16px;
}

.ml {
  margin-left: 16px;
}

.mt {
  margin-top: 12px;
}

.mb {
  margin-bottom: 12px;
}

.m0 {
  margin: 0;
}
.page-view {
  height: 100%;
  width: 100%;
}

:deep .loading-container {
  background: none;
}

.full-screen {
  position: fixed !important;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9;
}

.digital-evaluation-content {
  // overflow: hidden;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #000000;
}

.digital-evaluation {
  width: 1920px;
  height: 1080px;
  color: #fff;

  .parent {
    position: relative;
    padding: 0px 20px;
    width: 1920px;
    height: 100%;
    display: grid;
    // grid-template-columns: 1fr 900px 1fr;
    // grid-template-rows: 86px repeat(3, 1fr);
    grid-template-rows: 125px repeat(6, 1fr); // 7行=125px + 6等份
    grid-template-columns: 447px repeat(1, 1fr) 447px; // 三列=447px + 1等份 + 447px
    grid-column-gap: 20px;
    grid-row-gap: 20px;
    background-color: #1fff;

    background-image: url("@/assets/homeImg/bj.jpg");
    background-repeat: no-repeat;
    background-size: 100% 100%;
  }

  .div1 {
    // 占据几行几列 再默认 1 1
    grid-area: span 1 / span 3 / span 1 / span 1;
    position: relative;
    overflow: hidden;
    // height: 403px; //单独设置
    // pointer-events: none;
    background-color: #132222;
    opacity: 0.7;

    .title_name {
      position: absolute;
      text-align: center;
      font-size: 38px;
      left: 0;
      right: 0;
      margin: 0 auto;
      line-height: 86px;
      font-weight: 500;
      letter-spacing: 6px;
      font-style: italic; // 斜体
      z-index: 5;

      // 渐变字体
      background: linear-gradient(0deg, #eb0e0e 30%, #ffffff 60%, #fff 100%);
      -webkit-text-fill-color: transparent;
      background-clip: text;
      -moz-background-clip: text;
      -webkit-background-clip: text;
    }

    .time_box {
      background-color: #48ce82;
      position: absolute;
      z-index: 999;
      text-align: center;
      left: 0;
      right: 0;
      top: 80px;
      font-size: 14px;

      .el-icon-class {
        position: relative;
        top: 3px;
      }
    }
  }
  .div2 {
    grid-area: span 2 / span 1 / span 1 / span 1;
    background-color: #132222;
    opacity: 0.7;
  }
  .div3 {
    padding: 0 10px;
    grid-area: span 6 / span 1 / span 1 / span 1;
    background-color: #132222;
    opacity: 0.7;
  }
  .div4 {
    grid-area: span 4 / span 1 / span 1 / span 1;
    background-color: #132222;
    opacity: 0.7;
  }
  .div5 {
    grid-area: span 3 / span 1 / span 1 / span 1;
    background-color: #132222;
    opacity: 0.7;
  }
  .div6 {
    grid-area: span 2 / span 1 / span 1 / span 1;
    background-color: #132222;
    height: 100px;
    opacity: 0.7;
  }
  .div7 {
    height: 160px;
    grid-area: span 1 / span 1 / span 1 / span 1;
    background-color: #132222;
    opacity: 0.7;
  }
  .div8 {
    cursor: pointer;
    position: absolute;
    bottom: 0;
    left: 50%;
    height: 30px;
    line-height: 30px;
    transform: translateX(-50%);
    color: #00fffb;
    // grid-area: span 1 / span 1 / span 1 / span 2;
    background-color: #132222;
    opacity: 0.7;
  }
}