手机百度移动适配切图解决方案介绍

我们知道移动开发上面有个设备像素比:window.devicePixelRatio,现在在开发页面的时候,一定会在head中添加个viewportmeta类似下面的代码:

<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">

但是随着手机屏幕越来越大,于是页面会遇见下面的问题,手机屏幕越大,右边留白越多,字体越小也不清晰,影响体验:

iPhone5页面
iPhone6 Plus页面

介绍下REM

rem是以document.documentElement(即<html>标签)的font-size为基准的,举例说明:

  • html的font-size:10px
  • 那么1rem = 10px

手百Rem切图方案

为了切图方便,我们手百使用了Rem切图,首先类似淘宝的flexible方案,会在页面head中引入一个flexible.js

为了计算方便,我们将documentElement的font-size设置为页面宽度的10%,代码如下:

var docEl = document.documentElement;
var width = docEl.getBoundingClientRect().width;
var rem = width / 10;
docEl.style.fontSize = rem + 'px';

同时配合js获取dpr动态设置的viewport。切图布局的时候,需要计算rem,为了方便我们使用sass写了一个rem函数和mixin:

$rem-baseline: 75px !default;
@function rem-convert($to, $values...) {
  $result: ();
  $separator: rem-separator($values);

  @each $value in $values {
    @if type-of($value) == "number" and unit($value) == ""{
        $value: $value * 1px;
    }
    @if type-of($value) == "number" and unit($value) == "rem" and $to == "px" {
      $result: append($result, $value / 1rem * $rem-baseline, $separator);
    } @else if type-of($value) == "number" and unit($value) == "px" and $to == "rem" {
      $result: append($result, $value / ($rem-baseline / 1rem), $separator);
    } @else if type-of($value) == "list" {
      $result: append($result, rem-convert($to, $value...), $separator);
    } @else {
      $result: append($result, $value, $separator);
    }
  }

  @return $result;
}

@function rem($values...) {
  @if $rem-px-only {
    @return rem-convert(px, $values...);
  } @else {
    @return rem-convert(rem, $values...);
  }
}

@mixin rem($properties, $values...) {
  @if type-of($properties) == "map" {
    @each $property in map-keys($properties) {
      @include rem($property, map-get($properties, $property));
    }
  } @else {
    @each $property in $properties {
      @if $rem-fallback or $rem-px-only {
        #{$property}: rem-convert(px, $values...);
      }
      @if not $rem-px-only {
        #{$property}: rem-convert(rem, $values...);
      }
    }
  }
}
//
.demo{
    height: rem(300px);
    @include rem(padding, 10px 20px);
}

sass变量 $rem-baseline 是基准值,以设计图宽度/10为准,这样设计后,就可以直接用视觉稿的尺寸大小切图了。

举个例子

720px的视觉稿中有个360x360的div。

普通切图

使用普通方法切页面,设置:

<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">

这样采用iPhone5为基准手机切图,需要计算:需要切图的图层width/(视觉稿width/基准手机设备宽度) 即:360/(720/320)=160px

Rem切图

  • 设置$rem-baseline为720/10,即72px
  • 使用rem进行计算:width: rem(360px)

算一算

  1. html字体:1rem=640px/10=64px
  2. viewport:scale = 1/dpr = 0.5
  3. css的宽:360px/72px = 5rem
  4. 5rem 64px 0.5 = 160px

字体问题

字体的大小是根据<body>标签的font-size,为了计算方便,$font-baseline设置为12px,所以需要根据不同的设备像素比设置不同的font-size,然后配合sass的mixin fontsize设置字体大小

[data-dpr="1"] body{
    font-size: $font-baseline;
}
[data-dpr="2"] body{
    font-size: $font-baseline * 2;
}
[data-dpr="2.5"] body{
    font-size: $font-baseline * 2.5;
}
[data-dpr="2.75"] body{
    font-size: $font-baseline * 2.75;
}
[data-dpr="3"] body{
    font-size: $font-baseline * 3;
}
.demo{
    @include fontsize(24px);
}

总结

关于设备上面的切图就说到这里,想了解更多,看下我之前的内部分享:移动适配切图方案