这几天在做大屏项目的屏幕适配。
看到别人提到过使用flexible.js可以完成大屏的适配。我也尝试了一下,但是并没有成功。
参考了一下别人的项目的适配。
简单描述一下这个适配大屏代码的思路,主要通过css中的transform来完成,思路比较简单。
首先算出来固定的宽高比列,将大屏的容器ref设置为appRef,监听浏览器窗口的resize操作,每次resize以后重新进行一次宽和高的计算。
当前窗口相对于固定的长高比例更长时,如下图所示,需要根据窗口高度值重新计算缩放比例,通过transform对大屏容器进行放缩scale,移动translate操作让容器位于窗口中央。
同理窗口相对于固定的长高比例更长时,需要根据窗口长度值计算缩放比例。
实现适配工具,drawMixin.js函数:
// 屏幕适配 mixin 函数
// * 默认缩放值
const scale = {
width: '1',
height: '1',
}
// * 设计稿尺寸(px)
const baseWidth = 1920
const baseHeight = 1080
// * 需保持的比例(默认1.77778)
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
export default {
data() {
return {
// * 定时函数
drawTiming: null
}
},
mounted () {
this.calcRate()
window.addEventListener('resize', this.resize)
},
beforeDestroy () {
window.removeEventListener('resize', this.resize)
},
methods: {
calcRate () {
const appRef = this.$refs["appRef"]
if (!appRef) return
// 当前宽高比
const currentRate = parseFloat((window.innerWidth / window.innerHeight).toFixed(5))
if (appRef) {
if (currentRate > baseProportion) {
// 表示更宽
scale.width = ((window.innerHeight * baseProportion) / baseWidth).toFixed(5)
scale.height = (window.innerHeight / baseHeight).toFixed(5)
appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`
} else {
// 表示更高
scale.height = ((window.innerWidth / baseProportion) / baseHeight).toFixed(5)
scale.width = (window.innerWidth / baseWidth).toFixed(5)
appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`
}
}
},
resize () {
clearTimeout(this.drawTiming)
this.drawTiming = setTimeout(() => {
this.calcRate()
}, 200)
}
},
}
在大屏的index.vue文件中添加:
import drawMixin from "@/utils/drawMixin";
mixins: [drawMixin],
(mixins是一个js对象,可以包含我们组件中script项中的任意功能选项,如data、components、methods 、created、computed等等。将共用的功能以对象的方式传入 mixins选项中,当组件使用 mixins对象时所有mixins对象的选项都将被混入该组件本身的选项中来。)
但是由于这次做的大屏有一个地图下钻的功能,在初始化进行一次transform scale以后,鼠标点击地图区域,会产生偏移(下钻进另一个区域…),如果大屏在不使用地图下钻的情况下,这种方法还是比较有效的。后续有机会的话会改进一下。
---------------------------------------------------------------后续改进来了-----------------------------------------------------------------------
查了一下,如果项目中有用到高德地图或者百度地图,用scale缩放的话经纬度会对不上,大屏一般都有地图,所以如果用scale的话地图这也是一个坑。
解决方案:嵌入iframe
把要展示的地图单独作为一个界面,在路径里面添加:
{
path: '/map',
component: () => import('@/components/Screen/Center/Map'),
hidden: true
},
然后在大屏的页面里,通过把地图引入:
其中src属性对应的就是在路径中的path。MapView是我以前放的地图组件,把它备注掉改成用iframe的方式引入就可以。
<div class="content">
<!-- <Map area={area} onAreaChange={onAreaChange} year={year} /> -->
<!-- <Mapview></Mapview> -->
<iframe
class="map_iframe"
width="1200px"
height="953px"
src="map"
frameBorder="0"
/>
</div>
以前没有试着用过iframe引入,在设置路径上还试了一会儿错。
可以直接Fn+F12调出检查台,鼠标悬浮上iframe的src处,会显示src要跳转的完整路径,我这里的本地就是http://localhost/map。
顺便mark一下比较好的大屏项目。
Vue大屏可视化
👇这里的适配就是参考了这个项目的代码。