四时宝库

程序员的知识宝库

InnerEye低代码大屏——响应式布局实现

01 前言


在大数据时代,企业信息化得到井喷式发展。作为数据链条的终端环节,数据的可视化呈现和分析,也越来越得到业务分析师和企业决策者的认可、重视。


数据可视化辅助决策


02 InnerEye低代码大屏:精美大屏,极速配置


为了更好地赋能一线业务的分析决策,作为OPPO内部最大的自研可视化BI平台——InnerEye,近期上线了低代码大屏。大屏可以看作是一种报表看板的美化升级,且更加专注于核心指标的呈现,对于团队的目标管理具有一定的牵引作用。其广泛应用于业绩汇报、活动战报、展厅播放、美化看板和系统监控等场景。InnerEye大屏除了精美,同时具备低代码配置化能力,能将以前需要3~4周的大屏开发周期,最快缩短到了小时级,体现出了较强的降本增效能力,大大解决了业务急需短期输出精美大屏、又无技术人力的痛点。


合作案例(海外业务、通信)


03 响应式布局的实现方案:transform:scale(value)


除了介绍InnerEye大屏的基础能力,笔者也将推出系列技术文章来介绍“InnerEye低代码大屏相关技术实现”。由于大屏在视觉效果、多尺寸屏幕适配这两方面,有更为严苛的需求,笔者将优先分享InnerEye大屏的响应式布局实现方案。


不同尺寸屏幕的适配


有接触过h5开发的前端同学,相信对百分比、媒体查询、rem、vw/vh等布局方案信手拈来。然而综合视觉效果、实现难度、代码可维护性和浏览器兼容性这四个维度,css3的transform:scale()方案有更为出色的表现,故笔者采用之(百度的sugar BI亦采用此方案),下面将具体介绍scale方案的实现。


css3 transform: scale()方案


04 scale值的计算(重点和难点)


核心逻辑

一个好的大屏适配方案,在屏幕窗口变化时,通常需要满足如下3点:

1、大屏尺寸不变形

2、有一边(宽或高)撑满整个窗口(在不变形的前提下)

3、另外一边不能超出窗口(一边撑满窗口的前提下)

scale方案的核心逻辑在于:将大屏的初始化尺寸设置为1920 * 1080,即宽高比为16 :9,通过控制大屏元素的transform: scale值来实现大屏的不变形缩放。

而其重点和难点,就在于scale值的计算(需满足上述3个条件)。我们可以通过梳理缩放流程,来理解scale值的获取。

缩放流程

1、大屏初始化尺寸,ORIGIN_WIDTH = 1920, ORIGIN_HEIGH = 1080, 宽高比为16 :9

2、窗口缩放完成后,假定大屏的最新尺寸分别为newWidth, newHeight

3、大屏随着窗口的变化而变化,要求不变形,即宽高比始终为16 :9,有公式如下:


16 : 9 = ORIGIN_WIDTH / ORIGIN_HEIGHT = newWidth / newHeight


4、大屏随着窗口的变化而变化,要求至少有一边(宽或高),始终充满窗口,即:


newWidth = window.innerWidth  或 newHeight = window.innerHeight


进一步有:

scale_width = window.innerWidth / ORIGIN_WIDTH (当大屏的宽度撑满窗口时)
scale_height = window.innerHeight / ORIGIN_HEIGHT (当大屏的高度撑满窗口时)


scale = scale_width 或 scale_height


5、一边撑满整个窗口,同时要求在保证不变形的前提下,另外一边不能超出窗口,那么具体选哪一边撑满窗口?

由于大屏在缩放时需要保证不变形,即宽高是等比例缩放,且scale_width和scale_height本身也是极值(对应边已经撑满了窗口),我们只能选scale_width和scale_height中较小的一个,以保证另外一边不超窗口,即:


scale = min(scale_width, scale_height)


我们可以对几种极端情况进行分类讨论来辅助理解:

5.1. 在窗口(初始化尺寸为 1920 * 1080,16 :9)放大时

A:假定窗口宽度不变,高度变大时,大屏只能取宽度撑满窗口的宽度(较小),否则另一边会超出窗口;

即有:

newWidth等于window.innerWidth => scale = window.innerWidth / ORIGIN_WIDTH,
即
scale = scale_width


又由于:

window.innerWidth / ORIGIN_WIDTH < window.innerHeight / ORIGIN_HEIGHT,
即
scale_width < scale_height    


可知:

scale = min(scale_width, scale_height)


B:假定窗口宽度放大,高度不变时,大屏只能取高度撑满窗口的高度(较小),否则另外一边会超出窗口;


即有:

newHeight等于window.innerHeight => scale = window.innerHeight / ORIGIN_HEIGHT,
即
scale = scale_height


又由于:

window.innerWidth / ORIGIN_WIDTH > window.innerHeight / ORIGIN_HEIGHT,
即
scale_width > scale_height      


可知:

scale = min(scale_width, scale_height)


5.2. 在窗口(初始化尺寸为 1920 * 1080,16 :9)缩小时

A: 假定窗口宽度不变,高度缩小,大屏只能取高度撑满窗口的高度(较小),否则另外一边会超出窗口;

即有:

newHeight等于window.innerHeight => scale = window.innerHeight / ORIGIN_HEIGHT,
即
scale = scale_height


又由于:

window.innerWidth / ORIGIN_WIDTH > window.innerHeight / ORIGIN_HEIGHT,
即
scale_width > scale_height  


可知:

scale = min(scale_width, scale_height)


B: 假定窗口宽度缩小,高度不变时,大屏只能取宽度撑满窗口的宽度(较小),否则另外一边会超出窗口;

即有:

newWidth等于window.innerWidth => scale = window.innerWidth / ORIGIN_WIDTH,
即
scale = scale_width


又由于:

window.innerWidth / ORIGIN_WIDTH < window.innerHeight / ORIGIN_HEIGHT,
即
scale_width < scale_height


可知:

scale = min(scale_width, scale_height)


6. 综上5.1和5.2结论,可知:


scale = min(scale_width, scale_height)


最终的计算公式为:

scale = min(window.innerWidth / ORGIN_WIDTH, window.innerHeight / ORIGIN_HEIGHT)


所以,只要通过如上公式获取scale值,并通过transform: scale()设置,就能轻松实现大屏正确、优雅缩放:

a. 大屏始终不变形

b. 大屏始终充满窗口

c. 大屏始终不超出窗口


缩放效果如下:


代码demo


05 其他优化:缩放过程


在大屏适配方案中,同样有如下3点需要优化:

1、减少缩放卡顿:通过防抖实现

2、如果窗口宽度过宽,大屏始终水平居中

3、如果窗口高度过高,大屏始终吸顶显示

由于并不是核心要点、难点,为避免篇幅过长,就不再展开,感兴趣可自行参考文末代码。


06 参考


  • sugar BI:《百度云——电商618大屏》https://sugar.aipage.com/dashboard/5f81db321ff3e080e9f09168c923854f


  • 代码demo:
  • https://codesandbox.io/s/vue-scale-box-6unbe0?file=/src/components/ScaleBox.vue:451-641&resolutionWidth=559&resolutionHeight=377


#作者简介


Jamter OPPO数据中心高级前端工程师


负责OPPO内部最大的自研可视化BI平台——InnerEye前端组,有多年的大数据领域前端经验,专注可视化、低代码和大前端。


来源:微信公众号:OPPO数智技术

出处:https://mp.weixin.qq.com/s/V4od3XsUg04Wub1O3otz5Q

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接