多屏幕尺寸测试
多屏幕尺寸测试
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 的操作