前言
如何計算比例?本文重點講解。今日前端早讀課文章由 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期】淺談低代碼平台遠程組件加載方案