可视化大屏适配方案

创作背景

在做可视化大屏项目的时候,适配不同分辨率屏幕的电脑是最头疼的问题,那么,有没有一种方案,可以解决大屏适配问题呢。

在不懈的努力查找以及总结后,得到了一套,个人认为比较科学的适配方案。

线上demo例子

方案一

设计图宽高比例固定,并且跟随页面变化,等比例缩放

效果图

前端只需要按照设计图(px)单位设计开发即可,效果如图:

可视化大屏适配方案_第1张图片可视化大屏适配方案_第2张图片

 无论窗口缩放,屏幕放大缩小,我们的可视化界面都可以按照设计图比例正常展示,不会出现字体模块爆出,或者拉伸问题。这就是我想要的适配方案。

实现代码

html

给最外层的盒子(body也行)加上标识(id, 或ref)

xxx(反正就是整个可视化页面内容)

css

这里仅展示id标识符的css样式

#appRef {
  width: 1920px; /* 设计图宽 */
  height: 1080px; /* 设计图高 */
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  transform-origin: left top;
  overflow: hidden;
}

draw.js(html写法)

为了方便copy一点,这里就把普通html开发的适配js写法直接奉上

// * 默认缩放值
const scale = {
  width: '1',
  height: '1',
}
 
// * 设计稿尺寸(px)
const baseWidth = 1920
const baseHeight = 1080
 
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
 
let drawTiming = null
calcRate()
window.addEventListener('resize', resize)

// * 初始化页面比例
function calcRate () {
  const appRef = document.getElementById("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%)`
    }
  }
}

// * 窗口大小变化
function resize () {
  clearTimeout(drawTiming)
  // 加延迟是为了更好的看到变化的过程,不需要的可以不用
  drawTiming = setTimeout(() => {
    calcRate()
  }, 200)
}

 draw.js(vue写法)

vue开发的同理,为了方便copy,代码直接奉上

// * 默认缩放值
const scale = {
  width: '1',
  height: '1',
}
 
// * 设计稿尺寸(px)
const baseWidth = 1920
const baseHeight = 1080
 
// * 需保持的比例
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
 
export default {
  data() {
    return {
      drawTiming: null // 定时函数
    }
  },
  mounted () {
    this.calcRate()
    window.addEventListener('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)
    }
  },
  beforeDestroy () {
    window.removeEventListener('resize', this.resize)
  },
}

使用(html开发)

在所有script的最后面引入就行,如图:

可视化大屏适配方案_第3张图片

 使用(vue开发)

使用mixin混入引入(或者其他方式也行,个人习惯)


方案二

自适应全屏,不管屏幕宽高比如何,都以铺满全屏的形式进行展示。(适用于页面布局为百分比、或者flex自适应布局)

效果图

可视化大屏适配方案_第4张图片

可视化大屏适配方案_第5张图片可视化大屏适配方案_第6张图片 

实现代码

draw.js(方案2)

const appRef = document.getElementById("appRef")
// 初始化页面
calcRate()

window.addEventListener('resize', calcRate)

function calcRate () {
  if (!appRef) return 
  // 获取浏览器缩放比例
  const browserRoom = getZoom()
  /**
   * 1. 先将宽高乘上浏览器缩放倍数x
   * 2. 再将整个页面用scale缩放 1/x 倍
   * 在视觉上,就感觉页面没有缩放
  */
  // 宽高
  const w = window.innerWidth * browserRoom
  const h = window.innerHeight * browserRoom
  // scale缩放比例
  const scl = parseFloat((1 / browserRoom).toFixed(5))
  
  // 页面重绘处理
  appRef.style.width = `${w}px`
  appRef.style.height = `${h}px`
  appRef.style.transform = `scale(${scl}, ${scl}) translate(-50%, -50%)`
  // 页面重绘完成后,再进行echarts重绘,保证echarts图表的自适应性
  myChart.resize()
  myChart2.resize()

}

// 获取浏览器缩放比例
function getZoom() {
  let ratio = 0,
    screen = window.screen,
    ua = navigator.userAgent.toLowerCase();
  if (window.devicePixelRatio !== undefined) {
    ratio = window.devicePixelRatio;
  } else if (~ua.indexOf('msie')) {  
    if (screen.deviceXDPI && screen.logicalXDPI) {
      ratio = screen.deviceXDPI / screen.logicalXDPI;
    }
  } else if (window.outerWidth !== undefined && window.innerWidth !== undefined) {
    ratio = window.outerWidth / window.innerWidth;
  }
  if (ratio){
    ratio = Math.round(ratio * 100);
  }
  return parseFloat(ratio/100).toFixed(2);
}

总结:只要是按照设计图,正常开发的大屏项目,此方案基本都能很好的完成适配,切记别在项目中用rem单位就行,这玩意儿不行,拜拜~

你可能感兴趣的:(javascript,前端,javascript,html,大屏端)