likes
comments
collection
share

记一次大屏可视化适配踩坑之路

作者站长头像
站长
· 阅读数 13

前言

最近被安排一个大屏适配的工作,是一个远古的大屏项目,且是react项目,当初做这个项目的人也已离职,接手这样的项目是很头痛的。但还是得做下去。

需求

打开项目的代码,发现这个项目是只支持1920*1080分辨率的屏幕的,而这次客户需要在7680*2160分辨率的屏幕上显示,这就出现问题了。(记住这个分辨率,有大坑)

问题排查与解决

经过调研,加上我们这个是老项目,rem/vw什么方案其实都不太适合,又已知原有项目中是使用flex布局的,所以我们就选用transform scale方式来进行适配了。

方案确定,那就开始实现了,这个其实也蛮简单的。

原理就是:

  1. 获取屏幕的宽度(sw)和高度(sh)
  2. 已知我们设计稿宽高1920*1080 (w*h)
  3. 根据宽度比率(sw / w)进行缩放
  4. 监听页面的resize事件
  5. 移除页面的resize事件

这里偷个懒,就不放代码了,我是直接使用第三方库DataV的全屏容器。

import { FullScreenContainer } from '@jiaminghi/data-view-react'

render() {
    return (
      <FullScreenContainer>
        <div className={styles.home}>
          <Title/>
          <RouterTab/>
          {this._getBodyContainer()}
        </div>
      </FullScreenContainer>
    );
  }

在主DOM上包裹一层全屏容器。

:全屏模式下效果最好。但我们的大屏最终也是要在大屏上全屏展示的,所以其他非全屏下的小问题,就不管了。

修改完,我们就发布了,但还是出现了问题,客户提出,底部没有展示全。

继续排查,long time

这里推荐一个本地调试不同分辨率的小方法:

1、打开Chrome控制台

2、点击设置按钮,切换到设备栏

记一次大屏可视化适配踩坑之路

3、添加一个你想要调试的屏幕分辨率

记一次大屏可视化适配踩坑之路

4、添加完成后,点击如下图标

记一次大屏可视化适配踩坑之路

进入这个模式后,切换到你刚添加的分辨率就可以了

记一次大屏可视化适配踩坑之路


继续说问题,客户说是7680*2160,我也是在这个分辨率下调试的,完全复现不了问题,一度崩溃。后来还是让客户打开控制台看了下,发现我们代码检测到的分辨率是3840*1080

好的,我们换个分辨率继续调试,重现了这个问题,是因为某一块设置了最小高度,在客户的分辨率下,这个最小高度太大了,就导致页面元素超出当前网页了。

解决也很简单,要不设置个更小的高度,要不直接注释掉。

在本地一预览,咦,解决了,全显示出来了。


但新的问题出现了,首次加载,第一个页面中所有的echart表全部都宽高错乱,没有铺满所属的容器。但当我们切换到其他页面再切换回来,发现图表展示正常了。

问题分析:

应该是在组件挂载后虽然对图表设置了宽高,但是canvas并没有重新绘制。

解决方案:

1、使用定时器,让它在首次渲染完成后再重绘一次。

2、我们需要在屏幕大小改变时,也要重绘图表。

import debounce from "lodash.debounce"

// 组件挂载
componentDidMount() {
    this.charts = echarts.init(document.getElementById("chart"));
    this.charts.setOption({...})
    
    // 解决首次加载图表无法自适应的问题
    this.timer = setTimeout(() => {
        this.charts && this.charts.resize()
    },300)
    
    // 解决窗口大小变化时,图表无法自适应的问题
    this.__resizeHandler = debounce(() => {
            if(this.charts) {
                this.charts.resize()
            }
        }, 100)

    window.addEventListener('resize', this.__resizeHandler)
}

// 组件卸载时
componentWillUnmount() {
    if(!this.charts) return

    window.removeEventListener('resize', this.__resizeHandler)
    clearTimeout(this.timer)
    this.charts = null
}

在浏览器中调试,首次加载页面中的图表时,图表就正常显示了。


解决方案可能还不够完善,但可以解决当下客户在屏幕上展示了。