多屏幕尺寸测试

多屏幕尺寸测试

Chrome 有一个非常诱人的功能就是能够模拟不同设备的尺寸,在 Chrome 的 Inspector 中点击toggle device mode按钮,然后就可以在不同的设备屏幕尺寸下进行调试:

无线模拟

无线模拟方案主要有三点

  • http 协议修改 - userAgent

  • 视图渲染 - 无线模拟

  • 事件模拟 - touch

HTTP 协议修改

js 本身无法修改 http 协议,我们需要借助于 chrome extension,开发一个 chrome 扩展插件用于修改 http 协议,通过插件我们可以通过浏览器获取设备、通信的底层信息。开发插件是一件很简单的事件,这里涉及的重点在于修改 httt.userAgent

/**
 * 更新ua
 */
function replaceHeader(requestHeaders) {
  var newHeaders = [];
  for (var i = 0; i < requestHeaders.length; i++)
    if (requestHeaders[i].name != "User-Agent")
      newHeaders.push(requestHeaders[i]);
    else {
      var new_value = requestHeaders[i].value;
      //这里将user-agent声明为iphone
      newHeaders.push({
        name: "User-Agent",
        value:
          "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25"
      });
    }
  return newHeaders;
}

/**
 * 监听通信
 */
function updateListeners() {
  let listener = function(details) {
    var header_map = {
      requestHeaders: details.requestHeaders
    };
    if (!uaIsPhone) {
      return header_map;
    }
    if (
      details &&
      details.url &&
      details.requestHeaders &&
      details.requestHeaders.length > 0
    )
      header_map = {
        requestHeaders: replaceHeader(details.requestHeaders)
      };
    return header_map;
  };
  chrome.webRequest.onBeforeSendHeaders.addListener(
    listener,
    {
      urls: ["http://*/*", "https://*/*"]
    },
    ["requestHeaders", "blocking"]
  );
}

监听 chrome.webRequest.onBeforeSendHeaders,在发送前修改 ua 为无线。

服务端收到的 ua 为无线的 http 请求,判断为无线终端返回无线页面。

此时浏览器的 navigator.userAgent 还显示为 pc,为了保持与 http 请求一致,我们需要注入页面 js,来修改 navigator.user

function toMobile() {
  var head = document.querySelector("head");
  if (!head) {
    setTimeout(turnPhone, 100);
    return;
  }
  var _turnP = document.createElement("script");
  _turnP.type = "text/javascript";
  _turnP.innerText = [
    "Object.defineProperty(window.navigator, 'userAgent', { get: function(){ return 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1'; } });",
    "Object.defineProperty(window.navigator, 'vendor', { get: function(){ return 'Apple, Inc.'; } });",
    "Object.defineProperty(window.navigator, 'platform', { get: function(){ return 'iPhone'; } });"
  ].join("");
  head.appendChild(_turnP);
}

视图渲染

通常我们可以使用 iframe,不过这个涉及到跨域,对 dom 入侵大等一系列问题,针对这里的场景特点废弃了 iframe。使用在 dom 里渲染,首先需要修改 html 大小,这里也要通过插件,插件可以设置 content-script,并且指定其在 document_start 时执行,这样就保证了在页面返回前,就设置了 css,否则等 html 已经渲染一部分了再设置就无效了。

"content_scripts": [ {
      "all_frames": true,
      "js": [ "js/main.js" ],
      "css": ["css/main.css"],
      "matches": [ "http://*/*", "https://*/*" ],
      "run_at": "document_start"
   } ]

main.css 里设置

html.terminal-mobile {
  width: 400px !important;
}

main.js 里设置

document.querySelector("html").setAttribute("class", "udata-mobile");

现在从显示宽度上,似乎像手机的宽度了,但是有些元素却超出 html 的宽度,这类是样式主要是因为 dom 设置了 position: fixed 的元素,其定位是参照 window,非 html,所以其宽度是 window.innerWidth,所以我们需要修改参照项,可以通过修改 html 的 transform

html.terminal-mobile {
  width: 400px !important;
  transform: translate3d(0px, 0px, 0px);
}

现在再看,html 的内容完全参照 html 定位了

我们加上手机外框,通常会考虑会上下 padding 一定大小后使用 background-image,而这里样式我们需要在页面渲染前就设置,此时无法计算出 html.height 高度,所以只能用百分比,又不准确,所以使用 border-box

html.udata-mobile {
  transform: translate3d(0px, 0px, 0px);
  height: 100%;
  border-left-width: 10px;
  border-right-width: 10px;
  border-top-width: 80px;
  border-bottom-width: 80px;
  box-sizing: border-box; //将border设置进html height
  margin-left: 200px;
  width: 400px;
  border-color: transparent;
  border-style: solid;
  border-image: url(https://s.tbcdn.cn/g/udata/udata-pi/iphoneBg.png) 146 20
    stretch;
  background-color: rgb(255, 255, 255) !important;
}

box-sizing: border-box; 将 html:100%算进了 border,再通过 border-image 来添加手机框,下图是 demo 的操作

事件模拟

上一页
下一页