大屏屏幕自适应大小的JS写法(带滚动条)
目前已知的可以让大屏实现缩放的vue插件有:
vue3-scale-box 等
具体可以在npm上找一下相关文档参考,
他们有一个问题就是所有内容只能显示在一屏里,这不免会造成图像的拉伸,所以解决方案就是采用滚动条的设计去容纳大屏的更多内容,直接上代码:
// web定稿尺寸 1920*1080 let initPageW = 1920, initPageH = 1080 class ResizeBox { _contentApp = '' _content = '' constructor(contentApp: string, content: string) { this._contentApp = contentApp this._content = content } animateResize() { var _jsc: any = document.getElementById(this._contentApp), _body: any = document.getElementById(this._content) if (!_jsc || !_body) { return } let WH = window.innerHeight, WW = window.innerWidth, _jscH = _jsc.offsetHeight // 缩放 if (this._contentApp.indexOf('header-') > -1) { //头部的高度就是160px固定的 WH = 160 } else { WH = WH - 160 } let minScale = Math.floor((WW / initPageW) * 10000) / 10000 let minHeightScale = Math.floor((WH / initPageH) * 10000) / 10000 // 浏览器的滚滚动条宽度 8px,这里的8是因为css对滚动条的样式做了调整 // 内容区高度缩放后如果超过窗口高度,说明出现滚动条,可视区域宽度会缩小8px 重新计算缩放比, if (_jscH * minScale > WH) { minScale = Math.floor(((WW - 8) / initPageW) * 10000) / 10000 } _jsc.style.transform = 'scale(' + minScale + ',' + minScale + ')' _jsc.style.margin = '0 0' if (_body) { _body.style.height = _jscH * minHeightScale + 'px' } } debounce(func: any, wait?: any, immediate?: any) { let timeout: any, args: any, context: any, timestamp: any, result: any const later = function () { // 据上一次触发时间间隔 const last = +new Date() - timestamp // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait if (last < wait && last > 0) { timeout = setTimeout(later, wait - last) } else { timeout = null // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用 if (!immediate) { result = func.apply(context, args) if (!timeout) context = args = null } } } return function (...args: any) { // @ts-ignore context = this timestamp = +new Date() const callNow = immediate && !timeout // 如果延时不存在,重新设定延时 if (!timeout) timeout = setTimeout(later, wait) if (callNow) { result = func.apply(context, args) context = args = null } return result } } } export { ResizeBox }
调用:
<template> <!-- 我的头部组件,高度是160px --> <digital-header /> <div id="industry-content" style="position: relative"> <div id="industry-content-app" style=" width: 1920px; margin: 0 auto; transform: scale(1); transform-origin: 0 0; " > <div class="industry"> 这里就写具体内容,样式大小之类的都按照设计稿的宽高写即可 </div> </div> </div> </template> <script setup lang="ts"> import digitalHeader from '~/views/digitalCockpit/components/header.vue' import { onMounted } from 'vue-demi' import { ResizeBox } from '~/utils/resize' onMounted(() => { const resizeBox = new ResizeBox('industry-content-app', 'industry-content') // 初始化调用 resizeBox.animateResize() // 这里用addEventListener方法添加resize是因为每个页面都需要一个resize方法,如果用window.onresize的话就只能有一个页面是生效的 window.addEventListener( 'resize', resizeBox.debounce(function () { resizeBox.animateResize() }, 500) ) }) </script> <style scoped lang="scss"> .industry { &::before{ content: ''; height: 160px; display: block; } } </style>
其中头部组件的实现ID要加个header-的前缀,内容如下:
<template> <div id="header-content" style="position: fixed; top: 0; z-index: 1; background: #fff" > <div id="header-content-app" style=" width: 1920px; margin: 0 auto; transform: scale(1); transform-origin: 0 0; " > 头部的内容 </div> </div> </template> <script setup lang="ts"> import { h, onMounted } from 'vue-demi' import { ResizeBox } from '~/utils/resize' onMounted(() => { const resizeBox = new ResizeBox('header-content-app', 'header-content') resizeBox.animateResize() window.addEventListener( 'resize', resizeBox.debounce(function () { resizeBox.animateResize() }, 500) ) }) </script> <style scoped lang="scss"> .big-screen-header { padding: 10px; box-sizing: border-box; width: 100%; height: 160px; } </style> <style lang="scss"></style>
积累小的知识,才能成就大的智慧,希望网上少一些复制多一些原创有用的答案