查看原文
其他

【第2766期】InnerEye低代码大屏:响应式布局实现

OPPO数智技术 前端早读课 2022-10-28

前言

如何计算比例?本文重点讲解。今日前端早读课文章由 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 = 1920ORIGIN_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() 设置,就能轻松实现大屏正确、优雅缩放:

  • 大屏始终不变形

  • 大屏始终充满窗口

  • 大屏始终不超出窗口

缩放效果如下:

代码 demo

其他优化:缩放过程

在大屏适配方案中,同样有如下 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期】浅谈低代码平台远程组件加载方案

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存