在做可视化大屏项目难免会考虑到屏幕适配的难题,如果有一个适配各种屏幕的基础容器组件处理这个事情,我们就可以放心写业务,下面介绍在vue中如何通过锁定宽高比的方式来进行屏幕适配。
组件特点
1.自动监听浏览器窗口变化,动态计算出高宽比,无视页面放大缩小
2.适用于各种屏幕,常用作项目最外层基础容器
3.突破浏览器中 font-size 最小 12px 限制
组件实现
新增LargeScreenContainer.vue
文件,在文件里面创建一个外层包裹容器,根据屏幕的可视区尺寸与设计稿尺寸得到一个宽高缩放比例,根据比例去对外层包裹容器进行缩放,以适应屏幕
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
| <template> <div> <div id="well-container" :ref="refName"> <template v-if="ready"> <slot></slot> </template> </div> </div> </template>
<script> import { debounce } from '@/utils/util.js'
export default { name: 'largeScreenContainer', props: { options: Object }, data() { return { refName: 'WellContainer', width: 0, height: 0, originalWidth: 0, originalHeight: 0, ready: false, dom: null, observer: null } }, methods: { initSize() { return new Promise((resolve) => { this.$nextTick(() => { this.dom = document.getElementById('well-container') if (this.options && this.options.width && this.options.height) { this.width = this.options.width this.height = this.options.height } else { this.width = this.dom.clientWidth this.height = this.dom.clientHeight } if (!this.originalWidth || !this.originalHeight) { this.originalWidth = window.screen.width this.originalHeight = window.screen.height } resolve() }) }) }, updateSize() { if (this.width && this.height) { this.dom.style.width = `${this.width}px` this.dom.style.height = `${this.height}px` } else { this.dom.style.width = `${this.originalWidth}px` this.dom.style.height = `${this.originalHeight}px` } }, updateScale() { const currentWidth = document.body.clientWidth const currentHeight = document.body.clientHeight const realWidth = this.width || this.originalWidth const realHeight = this.height || this.originalHeight console.log(currentWidth, currentHeight) const widthScale = currentWidth / realWidth const heightScale = currentHeight / realHeight this.dom && (this.dom.style.transform = `scale(${widthScale}, ${heightScale})`) }, async onResize() { await this.initSize() this.updateScale() this.$emit('resize') }, initMutationObserver() { const MutationObserver = window.MutationObserver this.observer = new MutationObserver(this.onResize) this.observer.observe(this.dom, { attributes: true, attributeFilter: ['style'], attributeOldValue: true }) }, removeMutationObserver() { if (this.observer) { this.observer.disconnect() this.observer.takeRecords() this.observer = null } }, resize() { debounce(this.onResize, 100) } }, async mounted() { await this.initSize() this.updateSize() this.updateScale() window.addEventListener('resize', this.resize) this.initMutationObserver() this.ready = true }, beforeDestroy() { window.removeEventListener('resize', this.resize) this.removeMutationObserver() } } </script>
<style lang="scss" scoped>
#well-container { position: fixed; top: 0; left: 0; overflow: hidden; transform-origin: left top; z-index: 999; } </style>
|
依赖文件 util.js,参考如下:
组件的使用
1 2 3 4 5
| <large-screen-container :options="{width:1920,height:1080}" > </large-screen-container>
|
核心原理
1 2 3 4 5
| const widthScale = currentWidth / realWidth const heightScale = currentHeight / realHeight
this.dom && (this.dom.style.transform = `scale(${widthScale}, ${heightScale})`)
|
1.宽度度缩放比例(widthScale)= 分辨率宽高/props 传入宽高(可视宽高)
2.高度缩放比例(heightScale) = 分辨率高度/props 传入高度(可视高度)
3.通过 transform 的属性缩放容器的大