【第2766期】InnerEye低代码大屏:响应式布局实现
前言
如何计算比例?本文重点讲解。今日前端早读课文章由 OPPO@Jamter 分享,@剑涛投稿,公号:OPPO 数智技术授权。
@Jamter,OPPO 数据中心高级前端工程师,负责 OPPO 内部最大的自研可视化 BI 平台 ——InnerEye 前端组,有多年的大数据领域前端经验,专注可视化、低代码和大前端。
正文从这开始~~
在大数据时代,企业信息化得到井喷式发展。作为数据链条的终端环节,数据的可视化呈现和分析,也越来越得到业务分析师和企业决策者的认可、重视。
InnerEye低代码大屏:精美大屏,极速配置
为了更好地赋能一线业务的分析决策,作为 OPPO 内部最大的自研可视化 BI 平台 ——InnerEye,近期上线了低代码大屏。大屏可以看作是一种报表看板的美化升级,且更加专注于核心指标的呈现,对于团队的目标管理具有一定的牵引作用。其广泛应用于业绩汇报、活动战报、展厅播放、美化看板和系统监控等场景。
InnerEye 大屏除了精美,同时具备低代码配置化能力,能将以前需要 3~4 周的大屏开发周期,最快缩短到了小时级,体现出了较强的降本增效能力,大大解决了业务急需短期输出精美大屏、又无技术人力的痛点。
响应式布局的实现方案:transform:scale (value)
除了介绍 InnerEye 大屏的基础能力,笔者也将推出系列技术文章来介绍 “InnerEye 低代码大屏相关技术实现”。由于大屏在视觉效果、多尺寸屏幕适配这两方面,有更为严苛的需求,笔者将优先分享 InnerEye 大屏的响应式布局实现方案。
有接触过 h5 开发的前端同学,相信对百分比、媒体查询、rem、vw/vh 等布局方案信手拈来。然而综合视觉效果、实现难度、代码可维护性和浏览器兼容性这四个维度,css3 的 transform:scale()
方案有更为出色的表现,故笔者采用之(百度的 sugar BI 亦采用此方案),下面将具体介绍 scale 方案的实现。
css3 transform: scale()
方案
scale 值的计算(重点和难点)
核心逻辑
一个好的大屏适配方案,在屏幕窗口变化时,通常需要满足如下 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()
设置,就能轻松实现大屏正确、优雅缩放:
大屏始终不变形
大屏始终充满窗口
大屏始终不超出窗口
缩放效果如下:
其他优化:缩放过程
在大屏适配方案中,同样有如下 3 点需要优化:
减少缩放卡顿:通过防抖实现
如果窗口宽度过宽,大屏始终水平居中
如果窗口高度过高,大屏始终吸顶显示
由于并不是核心要点、难点,为避免篇幅过长,就不再展开,感兴趣可自行参考文末代码。
参考
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
原文:https://mp.weixin.qq.com/s/fnoaiwlHJm_OM6USGwUiMw
关于【低代码】相关推荐,欢迎读者自荐投稿,前端早读课等你来。+v:zhgb_f2er
【第2699期】Sunmao:一个真正可扩展的低代码 UI 框架
【第2697期】浅谈低代码平台远程组件加载方案