关于移动端横纵两个方向长度固定的屏幕适配方案

背景

大部分app的适配只需要针对一个维度进行适配就行了, 以为另外一个维度是可以上下拖动, 即理论上是无限大小的. 但是之前公司做的一个移动端的项目, 需要两个维度都固定, 无法拖动. 这就导致了必须针对不同屏幕比设计不同的设计稿, 同时使用相应长宽比的css规则

方案

采用@media中的min-aspect-ratiomax-aspect-ratio

假设设计师给出了 4/3, 667/375, 2/1两款长宽比的设计稿, 只需要让长宽比更接近4/3选择 4/3的css规则, 让接近2/1的采用2/1的规则, 于是我们需要算出两列之间的中间值

@media (max-aspect-ratio: 3501/2250) {
     编写响应 4:3 设计稿上的规则
}

@media (min-aspect-ratio: 3501/2250) and (max-aspect-ratio: 1417/750){
     编写响应 667:375 设计稿上的规则
}

@media (min-aspect-ratio: 1417/750) {
     编写响应 2:1 设计稿上的规则
}

这个方案的麻烦点在于每次新添加一个新的长宽比设置的话, 就需要重新计算这些值, 还需要对所有css文件添加@media规则, 因此如果使用webpack打包项目的话, 可以编写一个简单的loader来做这些事情

编写思路

// step1 添加当前有的设计稿
let arr = [
  {
    w: 4,
    h: 3
  },
  {
    w: 667,
    h: 375
  },
  {
    w: 2,
    h: 1
  }
].map(v => {
  return {
    ...v,
    type: `v-${v.w}-${v.h}`
  }
})

// step2 根据长宽比大小排序
arr = arr.sort((v1, v2) => v1.w/v1.h - v2.w/v2.h)

// step3 计算与相邻配置的平均值
arr.forEach((val, idx) => {
  if (idx === 0) {
    val.media = `@media (max-aspect-ratio: ${cal(val, arr[idx + 1])})`
  } else if (idx === arr.length - 1) {
    val.media = `@media (min-aspect-ratio: ${cal(val, arr[idx - 1])})`
  } else {
    val.media = `@media (max-aspect-ratio: ${cal(val, arr[idx + 1])}) and (min-aspect-ratio: ${cal(val, arr[idx - 1])})`
  }
})
/*
[ { w: 4, 
    h: 3, 
    type: 'v-4-3', 
    media: '@media (max-aspect-ratio: 3501/2250)' }, 
  { w: 667, 
    h: 375, 
    type: 'v-667-375', 
    media: '@media (max-aspect-ratio: 1417/750) and (min-aspect-ratio: 3501/2250)' }, 
  { w: 2, 
    h: 1, 
    type: 'v-2-1', 
    media: '@media (min-aspect-ratio: 1417/750)' } ] 
*/

step4: 在响应的css文件标示标志, 方便loader处理使用哪个@media查询

// index.css

/*v-4-3 标示*/

step5: loader读取每一个css文件, 尝试读取标识符

const regex = /(v-[\d]+-[\d]+)/
const type = regex.exec(source)
if (type === null) return source // 没有标识符, 不做处理
const item = arr.find(v => v.type === type)
if (item === null) return source// 没有对应的适配规则
return `${item.media} { ${source} }` // 包上媒体查询语句返回

以上就可以简单实现我们的方案了

采用根目录的类名来做适配

也可以直接在根目录上设置当前设备长宽比最近接近的类名, 然后去匹配对应规则

<app class="v-4-3">
   <child-component></child-component>
</app>

.v-4-3 p {
  ...
}

.v-2-1 p {
  ...
}

前面的v-x-y 也可以使用之前类似的方案用一个loader去动态添加

核心代码

// 配置 ratio.js
const ratios = [
  {
    value: 4/3,
    clazz: 'v-4-3'
  },
  {
    value: 1334/750,
    clazz: ''
  }
]

// 计算当前设备应该采用哪一个, 最接近的长宽比
export const calRatio = (docE) => {
  let w = docE.clientWidth
  let h = docE.clientHeight
  // h 会有可能为0吗 ?
  const r = w / h
  // 找到最接近的比例, 返回对应的class
  // 3个数的排序, 无需太多要求
  return ratios.sort((a, b) => {
    return Math.abs(a.value - r) - Math.abs(b.value - r)
  })[0].clazz
}

// App.vue
<div id="app" :class="ratio">
    ...
  </div>

created () {
    this.initRatio()
    window.addEventListener('resize', () => {
      this.initRatio()
    })
  },
  destroyed() {
    window.removeEventListener('resize', () => {
      this.initRatio()
    })
  },
  methods: {
    initRatio () {
      const doc = document.documentElement
      this.ratio = calRatio(doc)
    }
  }

// css 
<style scoped>
/* v-4-3 */
p {
  color: red;
}
</style>

<style scoped>
p {
  color: skyblue;
}
</style>

demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352