百度高考题库WAP版

电脑用户请使用Chrome移动调试模式打开,该路由做了平台判断,PC打开将会自动跳转PC题库

才入职几天,就接到对我而言来说是一个『大项目』的事情,那就是百度高考题库WAP版。这个项目主要为了熟悉高考这边的一个开发环境及流程,因此并没有采用新的架构方式,依然采用基于yog2 + express的开发方式,只是中途涉及到前端路由转发及nginx的相关配置,幸好这些都在老大 @岳凯璐 的帮助下完成了 :)。

在开发过程中遇到很多问题,以下是相关问题及解决办法的整理

文理科切换

这部分涉及到两个知识点

  • 通过CSS3 animation实现双面翻转
  • 文理科切换的动画要求动画结束后再跳转,因此这里要用到动画相关的事件监听,即transitionend,animationstart,animationiteration,animationend

实现双面翻转的原理是将两个块重叠在一起,然后将下面的块设置为rotate(180deg),同时两个块都设置背面不可见
backface-visibility: hidden,最后通过js手动控制外层容器rotate(180deg)。

1
2
3
4
<div class="wl">
<div class="front">文科</div>
<div class="back">理科</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.wl.hover {
transform: rotateY(180deg);
}

.wl {
transition: 0.6s;
transform-style: preserve-3d;
position: relative;
width: 64px/@scale;
height: 76px/@scale;
line-height: 76px/@scale;
text-align: center;
}

.front, .back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
width: 64px/@scale;
height: 76px/@scale;
}

.front {
z-index: 2;
}

.back {
transform: rotateY(180deg);
}
1
2
3
4
5
6
7
8
$(".wl").on("click", function () {
$(".wl").addClass("hover");
});

//transition动画结束时触发事件
$(".wl").on("webkitTransitionEnd", function(){
// do something
});

定位组件

定位采取后端通过IP自动定位的方式,于是需要前端缓存这次定位的结果,避免每次都需要定位,我这里采用Express cookieParser中间件在后端读取cookie,再以模板形式写入前端页面的方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 设置cookie
function setCookie(pid, wl) {
var currentList = getRecentProvinceIdList();
currentList.unshift(pid);
currentList = unique(currentList);
res.cookie('rpids', currentList.slice(0, 3).join('|'), {
expires: new Date((+new Date()) + 365 * 24 * 3600 * 1000)
});
res.cookie('wl', wl, {
expires: new Date((+new Date()) + 365 * 24 * 3600 * 1000)
});
res.cookie('pid', pid, {
expires: new Date((+new Date()) + 365 * 24 * 3600 * 1000)
});
}

// 从Cookies中取最近浏览省份
function getRecentProvinceIdList() {
var rpid = req.cookies.rpids, ret = [];
if(rpid){
ret = rpid.split('|');
}
return ret;
}

// 去重
function unique(arr) {
var result = [], hash = {};
for (var i = 0, elem; (elem = arr[i]) != null; i++) {
if (!hash[elem]) {
result.push(elem);
hash[elem] = true;
}
}
return result;
}

下拉遮罩层

这部分有两个小问题

  • flex-wrap 兼容性
  • opacity 容器子元素透明问题

flex-wrap 兼容性不佳,我想实现的效果是每行占据固定宽度的块,最初想通过flex-wrap换行及flex:1实现,结果效果不理想,最后通过百分比布局及display:inline-block实现,缺点是无法精准控制两边边距。

设置opacity的容器子元素透明的问题是老生常谈(但我老是忘 - -),解决办法也很简单,把元素放到和容器平行就行。

UC浏览器在线上环境下fixed定位bug

在此期间遇到的一个最坑的问题就是,安卓版UC在线上环境下js无法触发fixed定位容器子元素的高度变化,至今不知道为什么 - -

上滑隐藏地址栏

主要是利用window.scrollTo(0, 0)方法,控制网页往上滚动地址栏的高度,以达到隐藏地址栏的效果

需要注意的是,浏览器内容的高度要超过浏览器窗口高度(出现’滚动条’)才有效,所以不足一屏高时需要手动设置页面高度

1
2
3
4
5
6
7
8
var scrollHeight = document.documentElement.scrollHeight;
var bodyTag = document.getElementsByTagName('body')[0];
if(scrollHeight <= document.documentElement.clientHeight) {
bodyTag.style.height = document.documentElement.clientWidth / screen.width * screen.height + 'px';
}
setTimeout(function() {
window.scrollTo(0, 1);
}, 0);

通过特定meta标签实现(但是无法手动控制,只是一进入页面就全屏,而且只有特定浏览器支持)

1
2
3
4
5
6
7
8
9
10
<!-- UC强制全屏 -->
<meta name="full-screen" content="yes">
<!-- QQ强制全屏 -->
<meta name="x5-fullscreen" content="true">
<!-- UC应用模式 -->
<meta name="browsermode" content="application">
<!-- QQ应用模式 -->
<meta name="x5-page-mode" content="app">
<!-- 是否启用 WebApp 全屏模式,删除苹果默认的工具栏和菜单栏 -->
<meta name="apple-mobile-web-app-capable" content="yes"/>

锚点定位

之前的方案是通过a标签锚点实现,但是由于有fixed定位会遮住一部分,所以通过scrollTop实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 定位到锚点
function GetQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)","i");
var r = window.location.search.substr(1).match(reg);
if (r!=null) return (r[2]);
return null;
}
$(function(){
if(GetQueryString("hash_anchor")){
var target = $("#" + GetQueryString("hash_anchor"));
if(target.length == 1){
// 偏移的高度
var top = target.offset().top - 38;
if(top > 0){
$("body").scrollTop(top);
}
}
}
});