移动端适配 px转换rem

因为新的活动或需求,需要对本身不支持适配移动端的网站做部分页面需要移动端适配,对之前的页面又不能造成影响,年初碰到此类需求,对此做记录与分享,请大家指教。

框架Angular8 + ng-zorro
Angular8框架本身也有支持移动端的UI组件库ng-zorro mobile,因为项目并不是移动端与网页端分开,担心引入移动UI组件后会对本身网页造成影响,并且免于设计再次设计移动端的设计图,在考虑最小修改成本后,做粗略的移动端适配–px转换rem适配移动端。

实现思路类似flexible,通过js来调整html的字体大小,而在页面中的制作稿则统一使用rem这个单位来制作,主要是改变了dpr和document的font-size大小。
首先 将主流机型进行声明 以下声明 iPhone android google firefox blackberry 等等

const appleIphoneReg = /iPhone/i;
const appleIpodReg = /iPod/i;
const appleTabletReg = /iPad/i;
const androidPhoneReg = /\bAndroid(?:.+)Mobile\b/i; // Match 'Android' AND 'Mobile'
const androidTabletReg = /Android/i;
const amazonPhoneReg = /(?:SD4930UR|\bSilk(?:.+)Mobile\b)/i; // Match 'Silk' AND 'Mobile'
const amazonTabletReg = /Silk/i;
const windowsPhoneReg = /Windows Phone/i;
const windowsTabletReg = /\bWindows(?:.+)ARM\b/i; // Match 'Windows' AND 'ARM'
const otherBlackBerryReg = /BlackBerry/i;
const otherBlackBerry10Reg = /BB10/i;
const otherOperaReg = /Opera Mini/i;
const otherChromeReg = /\b(CriOS|Chrome)(?:.+)Mobile/i;
const otherFirefoxReg = /Mobile(?:.+)Firefox\b/i; // Match 'Mobile' AND 'Firefox'

识别运行环境 return 正在使用哪种设备浏览页面

function matchDevice(regex, userAgent) {
  return regex.test(userAgent);
}
function deviceType(userAgent) {
  userAgent = userAgent || (typeof navigator !== 'undefined' ? navigator.userAgent : '');

  let tmp = userAgent.split('[FBAN');
  if (typeof tmp[1] !== 'undefined') {
    userAgent = tmp[0];
  }

  tmp = userAgent.split('Twitter');
  if (typeof tmp[1] !== 'undefined') {
    userAgent = tmp[0];
  }

  const result = {
    apple: {
      phone: matchDevice(appleIphoneReg, userAgent) && !matchDevice(windowsPhoneReg, userAgent),
      ipod: matchDevice(appleIpodReg, userAgent),
      tablet: !matchDevice(appleIphoneReg, userAgent) && matchDevice(appleTabletReg, userAgent) && !matchDevice(windowsPhoneReg, userAgent),
      device: (matchDevice(appleIphoneReg, userAgent) || matchDevice(appleIpodReg, userAgent) || matchDevice(appleTabletReg, userAgent)) && !matchDevice(windowsPhoneReg, userAgent),
    },
    amazon: {
      phone: matchDevice(amazonPhoneReg, userAgent),
      tablet: !matchDevice(amazonPhoneReg, userAgent) && matchDevice(amazonTabletReg, userAgent), 
      device: matchDevice(amazonPhoneReg, userAgent) || matchDevice(amazonTabletReg, userAgent),
    },
    android: {
      phone: (!matchDevice(windowsPhoneReg, userAgent) && matchDevice(amazonPhoneReg, userAgent)) || (!matchDevice(windowsPhoneReg, userAgent) && matchDevice(androidPhoneReg, userAgent)),
      tablet: !matchDevice(windowsPhoneReg, userAgent) && !matchDevice(amazonPhoneReg, userAgent) && !matchDevice(androidPhoneReg, userAgent) && (matchDevice(amazonTabletReg, userAgent) || matchDevice(androidTabletReg, userAgent)),
      device: (!matchDevice(windowsPhoneReg, userAgent) && (matchDevice(amazonPhoneReg, userAgent) || matchDevice(amazonTabletReg, userAgent) || matchDevice(androidPhoneReg, userAgent) || matchDevice(androidTabletReg, userAgent))) || matchDevice(/\bokhttp\b/i, userAgent),
    },
    windows: {
      phone: matchDevice(windowsPhoneReg, userAgent),
      tablet: matchDevice(windowsTabletReg, userAgent),
      device: matchDevice(windowsPhoneReg, userAgent) || matchDevice(windowsTabletReg, userAgent),
    },
    other: {
      blackberry: matchDevice(otherBlackBerryReg, userAgent),
      blackberry10: matchDevice(otherBlackBerry10Reg, userAgent),
      opera: matchDevice(otherOperaReg, userAgent),
      firefox: matchDevice(otherFirefoxReg, userAgent),
      chrome: matchDevice(otherChromeReg, userAgent),
      device: matchDevice(otherBlackBerryReg, userAgent) || matchDevice(otherBlackBerry10Reg, userAgent) || matchDevice(otherOperaReg, userAgent) || matchDevice(otherFirefoxReg, userAgent) || matchDevice(otherChromeReg, userAgent),
    },
    any: false,
    phone: false,
    tablet: false,
  };

  result.any = result.apple.device || result.android.device || result.windows.device || result.other.device;
  result.phone = result.apple.phone || result.android.phone || result.windows.phone;
  result.tablet = result.apple.tablet || result.android.tablet || result.windows.tablet;
  return result;
}

页面加载时自运行函数,此函数会在标签上增加一个data-dpr属性和font-size样式,根据不同的设备计算dpr

(function (win, adapt) {
  if (deviceType().any) {
    var doc = win.document;
    var docEl = doc.documentElement;
    var dpr = 0;
    var tid;
    var fn = adapt.fn || (adapt.fn = {});

    dpr = parseInt(window.devicePixelRatio);

    docEl.setAttribute('data-dpr', dpr);

    function refreshRem() {
      var width = docEl.getBoundingClientRect().width;
      if (width / dpr > 540) {
        width = 540 * dpr;
      }
      var rem = width / 10;
      docEl.style.fontSize = rem + 'px';
      fn.rem = win.rem = rem;
    }

    win.addEventListener('resize', function () {
      clearTimeout(tid);
      tid = setTimeout(refreshRem, 300);
    }, false);
    win.addEventListener('pageshow', function (e) {
      if (e.persisted) {
        clearTimeout(tid);
        tid = setTimeout(refreshRem, 300);
      }
    }, false);

    if (doc.readyState === 'complete') {
      doc.body.style.fontSize = 12 * dpr + 'px';
    } else {
      doc.addEventListener('DOMContentLoaded', function (e) {
        doc.body.style.fontSize = 12 * dpr + 'px';
      }, false);
    }

    refreshRem();

    fn.dpr = win.dpr = dpr;
    fn.refreshRem = refreshRem;
    fn.rem2px = function (d) {
      var val = parseFloat(d) * this.rem;
      if (typeof d === 'string' && d.match(/rem$/)) {
        val += 'px';
      }
      return val;
    }
    fn.px2rem = function (d) {
      var val = parseFloat(d) / this.rem;
      if (typeof d === 'string' && d.match(/px$/)) {
        val += 'rem';
      }
      return val;
    }
  }
})(window, window['adapt'] || (window['adapt'] = {}));

底层js就是以上代码实现,

判断此时是在哪种设备上运行 引入一个三方件判断是否为手机浏览器
import isMobile from 'ismobilejs';
deviceDetection: any = isMobile(navigator.userAgent);

使用时 在页面加载开始判断,根据deviceDetection.any判断运行环境,写不同的代码来适配移动端
PC:
<div class="about-wrap"></div>
移动端:
<div class="phone-about"></div>

css中,以设计稿尺寸为准,假设我们的设计稿宽是640的,则html的字体大小则被设为64px.则相当于1rem=64px。
我们设计稿基准为375

$ratio: 75; //基准font-size

@function pr($px) {
  @return $px / $ratio * 1rem;
}

按照设计稿尺寸*2,设置长宽,例如width:34px;我们使用时就应该如下:
width: pr(68);
此方案还是很粗简,不是很全面,希望大家有好的提议可以随时赐教。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值