close

前言

如何計算比例?本文重點講解。今日前端早讀課文章由 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()設置,就能輕鬆實現大屏正確、優雅縮放:

大屏始終不變形

大屏始終充滿窗口

大屏始終不超出窗口

縮放效果如下:

代碼 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期】淺談低代碼平台遠程組件加載方案

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()