vivo 悟空活动中台-基于行为预设的动态布局方案

本文首发于 vivo互联网技术 微信公众号
连接: https://mp.weixin.qq.com/s/CwLAV2j7Uxam01m1p7cXxg
做者:悟空中台研发团队html

【悟空活动中台】系列往期精彩文章:前端

1、写在前面

做为前端工程师,页面布局是基本功。面对悟空中台的海量的活动需求,仅仅有几招常规的布局套路显然是难以招架的,悟空开发者团队从个性化需求中提炼特定场景下的共性特色,设计了多个“创意布局”方案。前端工程师

本文以“满屏”场景下的页面布局思考为切入点,以微组件为元素单元,提供了一种新的布局方案设计思路——基于行为预设的动态布局方案,并详细的分享了设计目的及具体实现方案,对技术基础要求不高,是一篇男女老幼皆宜的“技术甜点”。布局

2、灵感缘起

灵感每每并非凭空产生的,而是与问题的出现造成因果关系,解决方案也鲜有一蹴而就,大多有一个不断完善的演进过程,咱们都执着于发现问题,分析问题,解决问题的轮回。字体

一、问题是什么

1.一、客户端茫茫多,而设计稿只有一个

这是移动端H5页面进行布局时面临的核心问题之一。优化

随着移动端生态的日益繁荣,设备屏幕宽高比从 3:四、9:16 到 9:1九、9:21 ,分辨率从 480p 、720p 到 1080p 甚至 2k ,显然设计师同窗不可能针对每种场景都进行对应的创做,因此通常只就约定的标准尺寸(如常见的 1080 * 1920 )输出一张设计稿。ui

而前端开发同窗在实施样式布局时,就须要能根据设计师的一张设计稿,做出适配各类不一样屏幕尺寸、分辨率的效果。

1.二、避免重复劳做

若是你面对的是 2 个设备,可能你只须要写两套样式去适配;

若是你面对的是 20 个设备,可能累一点也能搞得定;

若是你面对的是 200 个、 2000 个设备呢?仅仅是体力劳动已经彻底不能解决问题,咱们须要有更高效的办法——制定一套规则,遵循该规则的页面可以在运行时本身去适配所在设备。

二、普适性方案

为了实现页面运行时的样式自适应,咱们从一开始的静态布局、流式布局、到响应式布局、弹性布局,目前你们广泛采起的方案是使用rem单位的弹性布局,即基于设备像素比( Device Pixel Ratio,简称 DPR )计算并设置不一样设备中的根字体大小,元素尺寸采起 rem 单位的方案,具体实现此处就再也不赘述。

2.一、优点

面对不一样大小、比例和素质的屏幕,只须要写一套样式,就可以作到对设计稿视觉效果的精准还原;跨屏适配的逻辑代码能够彻底直接复用,配合现有的 px 转 rem 插件,几乎没有额外工做量开销。

2.二、不足

以上方案虽然有着诸多优点,可是有时面对特定场景也会存在适配效果不够理想的问题。

2.2.一、满屏场景

在单页或者滑屏H5场景下,对任何设备,页面内容“刚好”占满视口。打个比方:页面内容就像是一个“万能螺丝钉”,无论任何规格的螺帽(视口),它都能作到“严丝合缝”的填充。

上图展现了不一样规格视口中,页面内容总能刚好占满视口,没有溢出也没有留白;前文所述的普适性方案在满屏场景下就存在一些问题。

2.2.二、元素溢出和页面留白

因为基于 DPR 和 rem 的方案特色是动态适配且对设计稿的精确还原,因此当遇到实际可视区域与设计稿比例不一致的状况,就会出现纵向适配问题:

  • 视口比设计稿“长”时,页面纵向没法填充一屏,出现底部留白

  • 视口比设计稿“短”时,就会出现页面纵向内容没法一屏显示的问题,即元素溢出

2.三、初步优化方案

为了解决纵向适配问题,咱们将页面内容分为背景图和内部元素两部分,并针对性的进行属性调整,初步能够解决问题。

2.3.一、背景适配

对于背景元素,通常有两种方案:

  • 拉伸填充

    令背景直接在横向、纵向进行平铺;缺点是会令背景图片因为拉伸/收缩而产生形变,比例失衡。

background-size: 100% 100%;复制代码
  • 裁切溢出

    在保持背景图比例不变的前提下,使其大小可以彻底cover窗口大小,并将多余的横向/纵向部分裁掉。

background-size: cover;
background-position: center;复制代码

2.3.二、内部元素定位方式

对于页面元素,咱们采用固定定位( fixed ),令其相对于窗口的各个边位置固定。

下图展现了分别相对于视口顶部左边、顶部右边、底部左边和底部右边固定定位的元素:

2.四、“精进”的优化

2.4.一、初步优化方案的问题

这种布局方案能够作到不管是横向仍是纵向,页面内容所占空间始终与视口区域相同,初步知足了“满屏”的需求,可是仍然存在不足

  • 不够灵活

    固定定位的问题在于元素始终是以本身的某条边相对于视口的对应边框进行定位(如:只能是元素顶部相对于窗口顶部位置固定,而不能实现元素底部相对于窗口顶部位置固定的需求)

  • 空间竞争

    因为全部元素根据屏幕实际宽度进行 等比缩放 ,故对屏幕“剩余空间”的利用是静态的,即当屏幕宽高比变化时,全部元素老是 同时 “占据”或者“让出”特定比例的空间,尤为是在空间紧凑的状况下,可能存在非重点内容元素(点缀做用)与重点内容元素“空间竞争”的问题。

下图反映了固定定位在可视区域变小的情景下,元素对“剩余”空间的挤占:

2.4.二、预设方案进行灵活适配

为了进一步提高满屏场景布局的效果,悟空中台团队基于 DPR & rem 布局方案,借鉴了元素相对窗口固定定位的思想,提出并实现了基于行为预设的动态布局方案。

3、预设规则

即经过在用户配置页面的时候提供页面背景图和内部元素的属性、定位行为预设,实现产出页面对不一样视口的良好适配。

一、背景图尺寸预设

1.一、多种方案灵活可选

提供多种背景图填充方式,供用户灵活选择:

  • 默认——不对 background-size 进行设置

  • 拉伸填充——横纵平铺

  • 包含—— contain

  • 覆盖—— cover

  • 重复平铺—— repeat


二、内部元素行为预设

提供配置选项,能够对元素的缩放行为做出灵活的配置以知足实际需求。

2.一、缩放行为预设

缩放行为预设主要解决不一样视口下页面元素间的空间竞争问题。

2.1.一、元素分类

将元素分类为 主要元素 和 次要元素

  • 主要元素

    页面中须要突出的重点内容,在视口尺寸发生变化引发的空间竞争中,处于优点地位;

  • 次要元素

    页面中相对不重点的内容,在视口尺寸发生变化引发的空间竞争中,处于劣势地位;

2.1.二、基准视口与实际视口

基准视口 即与设计稿比例相同的视口,即若是设计稿比例是 9:16 ,则基准视口就是比例为 9:16 的视口;其余比例的视口咱们称之为 非基准视口。

实际视口即页面运行时的视口,根据不一样比例,多是基准视口,也多是非基准视口。

2.1.三、实际视口中的元素缩放行为

当实际视口短于基准视口,主要元素大小与基准视口保持不变,次要元素按视口比例缩小;

当实际视口长于基准视口,主要元素按视口比例放大,次要元素大小与基准视口保持不变。

通过以上缩放行为预设,能够灵活定义不一样元素在实际视口中的缩放行为,解决元素因视口变化出现的空间竞争问题。

2.1.四、元素类型别名

为了使运营同窗更容易理解主要元素和次要元素的预期行为,咱们称放大元素为主要元素的别名,缩小元素为次要元素的别名,其他称为默认元素。

2.二、定位方式预设

定位方式预设为了提高元素定位的灵活性,使得元素内部的定位基准能够根据实际须要任意选取。

2.2.一、锚点

元素内部选取一个定位中心,做为锚点,未来元素的定位都是基于锚点进行计算。

锚点的设置可让元素的定位更加灵活:若是将元素的锚点设置为其底边的中点,那么令锚点吸附视口顶部便可实现元素底部相对视口顶部距离固定,这是常规固定定位没法实现的。

2.2.二、吸附性

对于一个元素,能够预设其锚点吸附于视口的顶部/底部,左边/右边,具体规则以下:

  1. 元素在水平方向或垂直方向上,不能同时吸附对应的两条边;好比不能令一个元素同时吸附视口顶部和视口底部;可是能够另其同时吸附视口顶部和视口左边。

  2. 元素若预设吸附了视口某一条边,则在任意规格的视口中,元素锚点相对于该条边的距离相同(以 rem 为单位)。

  3. 若元素在水平或垂直方向上,并不吸附于任意一条边,则令其相对于该方向上的两条边的距离比例固定;好比若元素同时不吸附于视口左边和右边,则元素相对于视口左边和右边的距离之比固定,值为在页面设计器中,配置页面时该元素距离视口左边和右边的距离之比。

4、预设规则的实现

本部分介绍了预设规则的具体实现,重点在于体现设计思路,示例代码均为伪代码。

一、基准视口与实际视口

1.一、基准视口宽高

描述基准视口的宽度与高度,咱们设基准宽度用 baseW 表示,其值为 10.8 rem (对应设计稿 1080px ),同理基准高度 baseH 的值设置为 21.6 rem 。

1.二、实际视口宽高

描述实际视口宽度与高度,咱们设实际宽度和高度分别为 realWrealH ,且因为使用基于 DPR 和 rem 的方案,容易得出 realW = baseW = 10.8rem ;

这样一来,实际视口与基准视口的差异就在于 realHbaseH 的不一样。

1.三、实际视口高度计算

根据 realW / realH = window.innerWidth / window.innerHeight ,将 realW = 10.8 rem 代入便可求得实际视口的 CSS 高度:

realW = 10.8
realH = (realW * window.innerHeight) / window.innerWidht复制代码

1.四、视口高度比

实际视口与基准视口的比例,设其为 windowHeightRatio ,则

// 计算视口高度比
windowHeightRatio = realH / baseH复制代码

二、元素缩放行为预设的实现

2.一、缩放类型

使用 scaleType 描述元素缩放类型,其可选值有三个—— zoomIn(放大)、 zoomOut(缩小)和 standard(不进行缩放)。

2.二、缩放比 scale

使用 scale 描述元素在实际视口与标准视口下的缩放比,设元素在基准视口下的宽高为 widthheight ,则元素在实际视口下的宽高分别为 baseW * scale 和 baseH * scale 。

2.三、缩放行为目标

对于 scaleType 为 zoomIn 的元素,当实际视口 高于 基准视口时,元素 缩放比 为视口高度比,元素表现为放大;当实际视口 不高于 基准视口时,元素缩放比为 1,元素大小保持不变。即

  • 当 windowHeightRatio > 1 (实际视口大于基准视口)时,元素 sacle = windowHeightRatio

  • 当 windowHeightRatio <= 1 (实际视口小于基准视口)时,元素 sacle = 1

对于 scaleType 为 zoomOut 的元素,当实际视口 低于 基准视口时,元素 缩放比 为视口高度比( realH / baseH ),元素表现为缩小;当实际视口 不低于 基准视口时,元素缩放比为 1,元素大小保持不变。即

  • 当 windowHeightRatio > 1 (实际视口大于基准视口)时,元素 sacle = 1

  • 当 windowHeightRatio < 1 (实际视口大于基准视口)时,元素 sacle = windowHeightRatio

对于 scaleType 为 standard 的元素,表现行为是始终与设计稿尺寸保持一致,故

  • 对于任何 windowHeightRatio ,始终有 sacle = 1

// 根据元素缩放类型肯定元素的实际缩放比
switch (scaleType) {
  case 'zoomIn':
    scale = windowHeightRatio >= 1 ? windowHeightRatio : 1
    break
  case 'zoomOut':
    scale = windowHeightRatio >= 1 ? 1 : windowHeightRatio
    break
  default:
    scale = 1
}复制代码

至此,咱们已经完成了对元素缩放类型的定义及缩放比的计算,接下来咱们要定义并实现的另外一个预设特性——定位特性。

三、元素定位方式预设的实现

3.一、锚点

锚点的设置并不固定,能够灵活根据实际需求的效果进行设置;为便于理解,本例将其设置为元素实际 宽高的中心点

3.二、吸附性

不一样视口内,页面元素的 锚点 相对于视口的某一个的位置是定值,称该元素 吸附 于该条边,视吸附的边的不一样,能够分为 吸顶吸底靠左靠右

对于某个元素,若其在水平或竖直方向并 不吸附 于某一条边,而是相对于顶部到底部或左边到右边的距离是固定比例,则称其为 按比例居中


3.三、元素定位

咱们以视口左上角做为定位坐标系的原点 ( 0, 0 ) ,将元素的吸附性使用元素锚点相对于定位原点的距离进行描述。

令元素与基准视口顶部及左边的距离为 baseTop 和 baseLeft;

元素与实际视口顶部及左边的距离为 realTop 和 realLeft。


3.3.1 特元素与可视区域顶部距离 realTop 的计算

(1)吸顶元素

吸顶元素的特性是元素 锚点与视口顶部距离固定,即

  • 不一样视口中,元素的 高度的一半元素顶部到到屏幕顶部 的距离的 是不变的。

根据特性有以下换算关系:

height / 2 + baseTop = height * scale / 2 + realTop

由 realH = baseH * scale 获得

realTop = height / 2 + baseTop - (height * scale) / 2复制代码

(2) 吸底元素

特性是元素 锚点与视口底部的距离固定,即

  • 不一样视口中,元素的 高度的一半元素底部到到屏幕底部 的距离的 是不变的。

故应有以下换算关系:

baseH - ( baseTop + height / 2 ) = realH - ( realTop + height * scale / 2 )

求得

realTop = realH - baseH + (baseTop + height / 2) - (height * scale) / 2复制代码

(3)按比例居中元素

特性是元素 锚点距视口顶部和底部的距离成固定比例,即

  • 不一样视口中,元素 高度的一半加上元素顶部到屏幕顶部的距离的和 的值,与元素 高度的一半加上元素底部到屏幕底部的距离的和 的值,这两个值 相等

故应有以下换算关系:

( height / 2 + baseTops ) / baseH = ( height * scale / 2 + realTop ) / realH

求得

realTop = (realH / baseH) * (height / 2 + baseTops) - (height * scale) / 2复制代码

3.3.二、元素与可视区域左边框距离 realLeft 的计算

(1)靠左元素

对于靠左元素,特色是 锚点距离视口左边框的距离固定,即

  • 不一样视口中,元素元素 宽度的一半与元素左边到屏幕左边 的距离 是固定的。

故应有以下换算关系:

baseLeft + width / 2 = realLeft + width * scale / 2

求得

realLeft = baseLeft + width / 2 - (width * scale) / 2复制代码

(2)靠右元素

计算过程同上文,能够获得

realLeft = realW - baseW + ( baseLeft + width / 2 ) - width * scale / 2复制代码

(3)按比例居中元素

根据 元素锚点到屏幕左右边框距离相等 ,能够获得

realLeft = (realW / baseW) * (baseLeft + width / 2) - (width * scale) / 2复制代码

因为咱们基于 rem 和 DPR 的布局方案的一个“准则”是视口宽度老是 10.8rem ,即 realW 实际和 baseW 在数值上相等,因此上述结果能够简化为:、

realLeft = ( baseLeft + width / 2 ) - width * scale / 2复制代码

至此,咱们已经完成了对元素预设规则——元素缩放特性和元素定位特性的实现,接下来须要使用这两种特性对元素的综合样式进行描述。

四、元素最终样式

4.一、定位方案的选择

4.1.一、简单场景

对于单一的“满屏”需求,如一个单独的满屏页面,咱们只须要对其中的元素使用 固定定位(fixed)方案结合前面几个步骤求得的 scale , realTop 和 realLeft 求得样式便可,举个栗子:

style = `
  top: ${realTop}rem;
  left: ${realLeft}rem;
  width: ${width}rem;
  height: ${height}rem;
  transform: scale(${scale});
`复制代码

4.1.二、较为复杂的场景

若是咱们的页面须要由一连串的“满屏”页面组成,而且能够进行“满屏”页面的切换,实现相似幻灯片同样的效果,则实际上每一个“满屏”的页面实际上是咱们最终页面的一个具有“满屏”特性的“容器”,容器内部的元素在进行布局时,须要相对于容器进行绝对定位( absolute )。

4.1.3 使用锚点进行样式表达

并且既然咱们已经有了元素 锚点 的概念,使用元素锚点的偏移量进行定位是更合乎情理的,锚点便是 CSS 中的 transform-origin 属性,即 transform-origin : center ,假设元素均处于默认起始位置 ( top = left = 0 ),咱们使用 transform 属性对元素的偏移位置进行设置:

锚点竖直方向原位置:baseAnchorY = height / 2

锚点竖直方向目标位置:realAnchorY = realTop + height * scale / 2

根据以上能够求得:

锚点竖直方向的偏移量:offsetVertical = realAnchorY - baseAnchorY = realTop + height * scale / 2 - height / 2

同理求得锚点水平方向的偏移量:offsetHorizontal = realAnchorX - baseAnchorX

最终得到元素样式为:

style = `
  top: 0px;
  left: 0px; 
  width: ${width}rem;
  height: ${height}rem;
  transform-origin: center; // 锚点设置
  transform: translateX(${offsetVertical}rem) translateY(${offsetHorizontal}rem) scale(${style.scale});
`复制代码

5、预设方案在生产中的应用

一、集成形式

目前基于行为预设的动态布局方案已经做为 悟空活动中台 上单页满屏场景的默认布局配置方案,用户能够经过简单的两步操做,即可调选中元素的吸附和缩放特性进行预设:

二、产出实例

悟空平台已经产出许多应用了的线上专题,好比经典的vivo 浏览器年终策划 | 2018 大事鉴


6、写在最后

基于行为预设的动态布局方案 必定程度上实现了根据视口尺寸对元素定位和大小的动态设置,达到了“恰到好处的突出重点”的效果。根据业务现实状况,预设方案也能够有多种不一样的灵活实现,好比元素的响应式缩放、吸附特征以及锚点位置的设置能够根据需求动态调整。

若是本文可以对你的布局设计带来一点点微小灵感的话,那真是深感荣幸。感谢阅读。

更多内容敬请关注 vivo 互联网技术 微信公众号

注:转载文章请先与微信号:Labs2020 联系。

相关文章
相关标签/搜索