自定义滚动条
*{margin: 0;padding: 0;}
body, html{height: 100%;overflow: hidden;}
#wrap{height: 100%;overflow: hidden;position: relative;}
#scrollBar{position: absolute;right: 0;top: 0;width: 4px;height: 100%;background: rgba(0,0,0,.5);opacity: 0;transition: .3s opacity;}
<div id="wrap">
<div id="scroll"></div>
<div id="scrollBar"></div>
</div>
window.onload = function(){
setInner();
var wrap = document.querySelector('#wrap');
var scroll = document.querySelector('#scroll');
var bar = document.querySelector('#scrollBar');
var scale = wrap.clientHeight/scroll.offsetHeight;
bar.style.height = wrap.clientHeight*scale + 'px';
var callBack = {
start: function(){
bar.style.opacity = 1;
},
in: function(){
var top = -cssTransform(scroll, 'translateY')*scale;
cssTransform(bar, 'translateY', top);
},
over: function(){
bar.style.opacity = 0;
}
};
moveScroll(wrap, callBack);
}
function setInner(){
var scroll = document.querySelector('#scroll');
var inner = '';
for(var i=0; i<300; i++){
inner += '移动端事件交互' + i + '<br/>';
}
scroll.innerHTML = inner;
}
js封装
transform.js
function cssTransform(el, attr, val){
if(!el.transform){
el.transform = {};
}
if(arguments.length>2){
el.transform[attr] = val;
var sVal = '';
for(var s in el.transform){
switch(s){
case 'rotate':
case 'rotateX':
case 'rotateY':
case 'rotateZ':
case 'skewX':
case 'skewY':
sVal += s+'('+el.transform[s]+'deg) ';
break;
case 'translateX':
case 'translateY':
case 'translateZ':
sVal += s+'('+el.transform[s]+'px) ';
break;
case 'scaleX':
case 'scaleY':
case 'scale':
sVal += s+'('+el.transform[s]+') ';
break;
}
el.style.WebkitTransform = el.style.transform = sVal;
}
}else{
var val = el.transform[attr];
if(typeof val == 'undefined'){
if(['scale', 'scaleX', 'scaleY'].indexOf(attr)>-1){
val = 1;
}else{
val = 0;
}
}
return val;
}
}
tween.js
var Tween = (function(){
return {
easeOut: function(t, b, c, d){
return -c*((t=t/d-1)*t*t*t-1) + b;
},
backOut: function(t, b, c, d, s){
if(typeof s == 'undefined'){
s = 2.70158;
}
return c*((t=t/d-1)*t*((s+1)*t+s)+1)+b;
}
}
})();
scrollBar.js
function moveScroll(wrap, callBack){
var child = wrap.children[0];
var startPoint = 0;
var startY= 0;
var minY = wrap.clientHeight - child.offsetHeight;
var step = 1;
var lastY = 0;
var lastTime = 0;
var lastDis = 0;
var lastTimeDis = 1;
var isMove = true;
var isFirst = true;
cssTransform(child, 'translateZ', 0.01);
wrap.addEventListener('touchstart', function (e) {
clearInterval(child.scroll);
if(callBack && callBack.start){
callBack.start();
}
startPoint = {pageX: e.changedTouches[0].pageX, pageY: e.changedTouches[0].pageY};
startY = cssTransform(child, 'translateY');
step = 1;
lastY = startPoint.pageY;
lastTime = new Date().getTime();
lastDis = 0;
lastTimeDis = 1;
isMove = true;
isFirst = true;
});
wrap.addEventListener('touchmove', function (e) {
if(!isMove){
return;
}
var nowPoint = {pageX: e.changedTouches[0].pageX, pageY: e.changedTouches[0].pageY};
var disX = nowPoint.pageX - startPoint.pageX;
var disY = nowPoint.pageY - startPoint.pageY;
var top = startY + disY;
if(isFirst){
isFirst = false;
if(Math.abs(disY) < Math.abs(disX)){
isMove = false;
return;
}
}
var nowTime = new Date().getTime();
if (top > 0) {
step = 1-top / wrap.clientHeight;
top = parseInt(top*step);
}
if (top < minY) {
var over = minY - top;
step = 1 - over / wrap.clientHeight;
over = parseInt(over * step);
top = minY - over;
}
lastDis = nowPoint.pageY - lastY;
lastTimeDis = nowTime - lastTime;
lastY = nowPoint.pageY;
lastTime = nowTime;
cssTransform(child, 'translateY', top);
if(callBack && callBack.in){
callBack.in();
}
});
wrap.addEventListener('touchend', function (e) {
var speed = (lastDis / lastTimeDis) * 200;
speed = isNaN(speed) ? 0 : speed
var top = cssTransform(child, 'translateY');
var target = top + speed;
var type = 'easeOut';
var time = Math.abs(speed * 1.2);
time = time < 300 ? 300 : time;
if (target > 0) {
target = 0;
type = 'backOut';
}
if (target < minY) {
target = minY;
type = 'backOut';
}
move(target, time, type);
cssTransform(child, 'translateY', target);
});
function move(target, time, type){
var t = 0;
var b = cssTransform(child, 'translateY');
var c = target - b;
var d = Math.ceil(time/20);
clearInterval(child.scroll);
child.scroll = setInterval(function(){
t++;
if(t>d){
clearInterval(child.scroll);
if(callBack && callBack.over){
callBack.over();
}
}else{
var top = Tween[type](t, b, c, d);
cssTransform(child, 'translateY', top);
if(callBack && callBack.in){
callBack.in();
}
}
}, 20);
}
}
音悦台
适配
<meta name="viewport" content="width=device-width, user-scalable=no"/>
<script type="text/javascript">
setRem();
window.addEventListener('orientationchange', setRem);
window.addEventListener("resize", setRem);
function setRem() {
var html = document.querySelector('html');
var width = html.getBoundingClientRect().width;
console.log(width)
html.style.fontSize = width / 16 + 'px';
}
</script>
样式
body,h1,h2,h3,h4,h5,h6,p,dl,dd{margin:0;-webkit-text-size-adjust:100%;font-family:Helvetica;}
ul,ol{margin:0;padding:0;list-style:none;}
img{display:block;}
a{text-decoration:none;}
a,input,button{-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-appearance:none;outline:none;}
html,body{height:100%;position:relative;overflow:hidden;background:#eee;}
.wrap{height:100%;position:relative;overflow:hidden;}
#header{position:absolute;background:rgba(0,0,0,0.8);left:0;top:0;width:100%;z-index:2;}
.headerC{height:2rem;}
#logo{float:left;padding:0.38518519rem 0.25185185rem 0.31111111rem;}
#logo img{width:3.55555556rem;}
#menu-btn{float:left;width:1.91111111rem;height:2rem;background:url(../img/menuBtn.png) no-repeat;background-size:1.21481481rem 3.45185185rem;}
.menu-btn-show{background-position:center 0.23703704rem !important;}
.menu-btn-close{background-position:center -1.77777778rem !important;}
#btns{float:right;padding-top:0.31111111rem;}
#btns a{float:left;margin-right:0.22222222rem;width:1.64444444rem;height:1.15555556rem;background:#690;color:#ccc;font-size:0.59259259rem;line-height:1.15555556rem;text-align:center;border-radius:0.11851852rem;}
#btns .search-btn{font-weight:bold;color:#ffffff;margin-right:0.44444444rem;width:1.92592593rem;line-height:1.3037037rem;border-radius:0.14814815rem;}
.search{height:1.52592593rem;padding:0.23703704rem;}
.search input[type='search']{float:left;width:12.28148148rem;height:1.52592593rem;background:#999;padding:5px 10px;box-sizing:border-box;border:1px solid #5a5a5a;font-size:0.6rem;color:#333;border-radius:0.22222222rem 0 0 0.22222222rem;}
.search input[type='search']:focus{background:#fff;}
.search input[type='search']::-webkit-input-placeholder{color:#666;}
.search input[type='submit']{float:right;width:3.00740741rem;height:1.52592593rem;border:none;background:#414040;color:#fff;border-radius:0 0.22222222rem 0.22222222rem 0;font-size:0.77037037rem;}
#nav{position:absolute;width:100%;left:0;top:2rem;border-top:1px solid #414040;background:rgba(0,0,0,0.8);padding:0.14814815rem 0;display:none;}
#nav li{float:left;width:22.5%;line-height:2rem;font-size:0.8rem;text-align:center;}
#nav a{color:#fff;}
.content{padding-top:4rem;z-index:1;}
#navScroll{height:2.62222222rem;border-bottom:1px solid #ccc;box-sizing:border-box;padding:0.45925926rem 0 0.20740741rem;overflow:hidden;}
#navs{height:1.91111111rem;white-space:nowrap;font-size:0;float:left;}
#navs li{display:inline-block;padding:0 0.56296296rem;line-height:1.91111111rem;font-size:1.03703704rem;}
#navs a{color:#020202;}
#navs .active{background:#690;}
#navs .active a{color:#fff;}
#picTab{overflow:hidden;position:relative;}
#picList{width:400%;}
#picList li{float:left;width:25%;}
#picList img{width:100%;display:block;}
#picNav{position:absolute;left:0;bottom:3px;width:100%;line-height:10px;text-align:center;}
#picNav span{display:inline-block;width:10px;height:10px;background:#C00;border-radius:5px;}
#picNav .active{background:#0F0;}
.tab{width:15.5rem;margin:0 auto;background:#fff;overflow:hidden;}
.tabHeader{height:2rem;}
.tabHeader h2{float:left;}
.tabHeader a{float:right;}
.tabNav{height:1.56rem;position:relative;}
.tabNav a{width:1.79rem;text-align:center;float:left;font-size:0.65rem;color:#6b6b6b;line-height:1.56rem;}
.tabNav span{position:absolute;left:0;bottom:0.1rem;width:1.79rem;height:3px;background:#6f900d;transition:0.3s cubic-bezier(0.68,1.31,0.92,1.2);}
.tabList{width:300%;overflow:hidden;}
.tabList ul{width:33.3333%;float:left;}
.tabList li{width:7.5rem;float:left;margin:0.12rem;padding:5px;box-sizing:border-box;background:#efefef;font-size:0.6rem;}
.tabList a{display:block;color:#000;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.tabList img{width:100%;}
.tabNext{font-size:100px;text-align:center;opacity:0;}
#scrollBar{position:absolute;right:0;top:0;width:4px;height:100%;background:rgba(0,0,0,.5);opacity:0;transition:.3s opacity;z-index:3;}
html
<header id="header">
<div class="headerC">
<h1 id="logo"><a href="#"><img src="img/logo.png"></a></h1>
<a href="javascript:void(0);" id="menu-btn" class="menu-btn-show"></a>
<nav id="btns"><a href="#" class="search-btn">搜索</a><a href="#">登陆</a><a href="#">注册</a></nav>
</div>
<form class="search">
<input type="search" placeholder="请输入搜索内容"><input type="submit" value="搜索">
</form>
<ul id="nav">
<li><a href="javascript:void(0);" class="" data-tab="index">首页</a></li>
<li><a href="javascript:void(0);" data-tab="mv" class="">MV</a></li>
<li><a href="javascript:void(0);" data-tab="pl" class="">悦单</a></li>
<li><a href="javascript:void(0);" data-tab="vchart" class="">V榜</a></li>
<li><a href="http://zhongchou.yinyuetai.com/wap" class="">众筹</a></li>
<li><a href="http://www.yinyuetai.com/fanMass" data-tab="wapfan" class="">饭团</a></li>
<li><a href="javascript:void(0);" data-tab="program" class="">节目</a></li>
<li><a href="javascript:void(0);" data-tab="stage" class="">音悦stage</a></li>
<li><a href="javascript:void(0);" data-tab="apps/mobile" class="">APP下载</a></li>
<li><a href="http://news.yinyuetai.com/" target="_blank" class="">资讯</a></li>
<li><a href="http://i.yinyuetai.com" target="_blank" class="selected">我的家</a></li>
<li><a href="javascript:void(0);" data-tab="apps" class="">热门应用</a></li>
</ul>
</header>
<section class="wrap">
<div class="content">
<nav id="navScroll">
<ul id="navs">
<li class="active"><a href="javascript:void(0);" class="" data-tab="index">首页</a></li>
<li><a href="javascript:void(0);" data-tab="mv" class="">MV</a></li>
<li><a href="javascript:void(0);" data-tab="pl" class="">悦单</a></li>
<li><a href="javascript:void(0);" data-tab="vchart" class="">V榜</a></li>
<li><a href="http://zhongchou.yinyuetai.com/wap" class="">众筹</a></li>
<li><a href="http://www.yinyuetai.com/fanMass" data-tab="wapfan" class="">饭团</a></li>
<li><a href="javascript:void(0);" data-tab="program" class="">节目</a></li>
<li><a href="javascript:void(0);" data-tab="program" class="">节目</a></li>
<li><a href="javascript:void(0);" data-tab="stage" class="">音悦stage</a></li>
<li><a href="javascript:void(0);" data-tab="apps/mobile" class="">APP下载</a></li>
<li><a href="http://news.yinyuetai.com/" target="_blank" class="">资讯</a></li>
<li><a href="http://i.yinyuetai.com" target="_blank" class="selected">我的家</a></li>
<li><a href="javascript:void(0);" data-tab="apps" class="">热门应用</a></li>
</ul>
</nav>
<div id="picTab">
<ul id="picList">
<li><a href="#"><img src="img/img1.jpg"/></a></li>
<li><a href="#"><img src="img/img2.jpg"/></a></li>
<li><a href="#"><img src="img/img3.jpg"/></a></li>
<li><a href="#"><img src="img/img4.jpg"/></a></li>
</ul>
<nav id="picNav">
<span class="active"></span><span></span><span></span><span></span>
</nav>
</div>
<section class="tab">
<header class="tabHeader">
<h2>MV首播</h2><a href="#">更多</a>
</header>
<nav class="tabNav">
<a href="javascript:;" class="J_area cur" data-area="all">全部</a>
<a href="javascript:;" class="J_area" data-area="ml">内地</a>
<a href="javascript:;" class="J_area" data-area="ht">港台</a>
<a href="javascript:;" class="J_area" data-area="us">欧美</a>
<a href="javascript:;" class="J_area" data-area="kr">韩国</a>
<a href="javascript:;" class="J_area" data-area="jp">日本</a>
<span></span>
</nav>
<section class="tabList">
<ul class="tabNext">loading</ul>
<ul class="tabShow">
<li><a href="#"><img src="img/img.jpg"/><span>当我们混在一起 夏日泳池版</span></a></li>
<li><a href="#"><img src="img/img.jpg"/><span>当我们混在一起 夏日泳池版</span></a></li>
<li><a href="#"><img src="img/img.jpg"/><span>当我们混在一起 夏日泳池版</span></a></li>
<li><a href="#"><img src="img/img.jpg"/><span>当我们混在一起 夏日泳池版</span></a></li>
<li><a href="#"><img src="img/img.jpg"/><span>当我们混在一起 夏日泳池版</span></a></li>
<li><a href="#"><img src="img/img.jpg"/><span>当我们混在一起 夏日泳池版</span></a></li>
</ul>
<ul class="tabNext">loading</ul>
</section>
</section>
</div>
</section>
js
window.onload = function () {
navShow();
navSwipe();
scrollPic();
tabSwipe();
scroll();
}
function scroll(){
var wrap = document.querySelectorAll('.wrap')[0];
var search = document.querySelector('.search');
var scroll = wrap.children[0];
var searchBtn = document.querySelector('.search-btn');
searchBtn.addEventListener('touchend', function(e){
var top = -cssTransform(scroll, 'translateY');
if(search.style.display=='block'){
if(top){
search.style.display = 'none';
}
}else{
search.style.display = 'block';
}
});
var bar = document.querySelector('#scrollBar');
var scale = wrap.clientHeight/scroll.offsetHeight;
bar.style.height = wrap.clientHeight*scale + 'px';
var callBack = {
start: function(){
},
in: function(){
bar.style.opacity = 1;
var top = -cssTransform(scroll, 'translateY')*scale;
cssTransform(bar, 'translateY', top);
if(top){
search.style.display = 'none';
}
},
over: function(){
bar.style.opacity = 0;
var top = -cssTransform(scroll, 'translateY');
if(top == 0){
search.style.display = 'block';
}
}
};
moveScroll(wrap, callBack);
}
function navShow() {
var btn = document.querySelector("#menu-btn");
var nav = document.querySelector("#nav");
btn.addEventListener('touchstart', function (e) {
if (btn.className === 'menu-btn-show') {
btn.className = 'menu-btn-close';
nav.style.display = 'block';
} else {
btn.className = 'menu-btn-show';
nav.style.display = 'none';
}
e.stopPropagation();
}
);
nav.addEventListener('touchstart', function (e) {
e.stopPropagation();
});
document.addEventListener('touchstart', function () {
if (btn.className === 'menu-btn-close') {
btn.className = 'menu-btn-show';
nav.style.display = 'none';
}
}
);
}
function navSwipe() {
var navScroll = document.querySelector('#navScroll');
var navs = document.querySelector('#navs');
var startPoint = 0;
var startX = 0;
var minX = navScroll.clientWidth - navs.offsetWidth;
var step = 1;
var lastX = 0;
var lastTime = 0;
var lastDis = 0;
var lastTimeDis = 0;
cssTransform(navs, 'translateZ', 0.01);
navScroll.addEventListener('touchstart', function (e) {
navs.style.transition = 'none';
startPoint = e.changedTouches[0].pageX;
startX = cssTransform(navs, "translateX");
step = 1;
lastX = startPoint;
lastTime = new Date().getTime();
lastDis = 0;
lastTimeDis = 0;
});
navScroll.addEventListener('touchmove', function (e) {
var nowPoint = e.changedTouches[0].pageX;
var dis = nowPoint - startPoint;
var left = startX + dis;
var nowTime = new Date().getTime();
if (left > 0) {
step = 1 - left / navScroll.clientWidth;
left = parseInt(left * step);
}
if (left < minX) {
var over = minX - left;
step = 1 - over / navScroll.clientWidth;
over = parseInt(over * step);
left = minX - over;
}
lastDis = left - lastX;
lastTimeDis = nowTime - lastTime;
lastX = left;
lastTime = nowTime;
cssTransform(navs, "translateX", left);
});
navScroll.addEventListener('touchend', function (e) {
var speed = (lastDis / lastTimeDis) * 200;
var left = cssTransform(navs, "translateX");
var target = left + speed;
var type = 'cubic-bezier(.34, 0.92, .58, .9)';
var time = Math.abs(speed * 1.2);
time = time < 300 ? 300 : time;
if (target > 0) {
target = 0;
type = 'cubic-bezier(.68, 1.31, .92, 1.2)';
}
if (target < minX) {
target = minX;
type = 'cubic-bezier(.68, 1.31, .92, 1.2)';
}
navs.style.transition = time + 'ms ' + type;
cssTransform(navs, "translateX", target);
});
}
function scrollPic() {
var wrap = document.querySelector('#picTab');
var list = document.querySelector('#picList');
list.innerHTML += list.innerHTML;
var lis = document.querySelectorAll('#picList li');
var css = document.querySelector('style');
var navSpan = document.querySelectorAll('#picNav span')
wrap.style.height = lis[0].offsetHeight + 'px';
list.style.width = lis.length + '00%';
var style = '#picTab{height: ' + lis[0].offsetHeight + 'px}';
var timer = 0;
style += '#picList{width: ' + lis.length + '00%}';
style += '#picList li{width:' + (1 / lis.length * 100) + '%}';
css.innerHTML += style;
var startPoint = {};
var startX = 0;
var now = 0;
var isMove = true;
var isFirst = true;
cssTransform(list, 'translateZ', 0.01);
cssTransform(list, 'translateX', 0);
auto();
wrap.addEventListener('touchstart', function (e) {
clearInterval(timer);
list.style.transition = 'none';
var translateX = cssTransform(list, 'translateX');
now = Math.round(-translateX / wrap.offsetWidth);
if (now == 0) {
now = navSpan.length;
}
if (now == lis.length - 1) {
now = navSpan.length - 1;
}
cssTransform(list, 'translateX', -now * wrap.offsetWidth);
startPoint = {pageX: e.changedTouches[0].pageX, pageY: e.changedTouches[0].pageY};
startX = cssTransform(list, 'translateX');
isMove = true;
isFirst = true;
});
wrap.addEventListener('touchmove', function (e) {
if (!isMove) {
return;
}
var nowPoint = e.changedTouches[0];
var disX = nowPoint.pageX - startPoint.pageX;
var disY = nowPoint.pageY - startPoint.pageY;
if (isFirst) {
isFirst = false;
if (Math.abs(disY) > Math.abs(disX)) {
isMove = false;
}
}
if (isMove) {
cssTransform(list, 'translateX', startX + disX);
}
});
wrap.addEventListener('touchend', function (e) {
var translateX = cssTransform(list, 'translateX');
now = Math.round(-translateX / wrap.offsetWidth);
tab();
auto();
});
function auto() {
clearInterval(timer);
timer = setInterval(function () {
if (now == lis.length - 1) {
now = navSpan.length - 1;
}
list.style.transition = 'none';
cssTransform(list, 'translateX', -now * wrap.offsetWidth);
setTimeout(function () {
now++;
tab();
}, 30);
}, 2000);
}
function tab() {
list.style.transition = '.5s';
cssTransform(list, 'translateX', -now * wrap.offsetWidth);
for (var i = 0; i < navSpan.length; i++) {
navSpan[i].className = '';
}
navSpan[now % navSpan.length].className = 'active';
}
}
function tabSwipe() {
var tabList = document.querySelectorAll(".tabList");
var tabNav = document.querySelectorAll(".tabNav");
var width = tabNav[0].offsetWidth;
for (var i = 0; i < tabNav.length; i++) {
swipe(tabNav[i], tabList[i]);
}
function swipe(nav, list) {
cssTransform(navs, 'translateZ', 0.01);
cssTransform(list, "translateX", -width);
var startPoint = 0;
var startX = 0;
var now = 0;
var isMove = true;
var isFirst = true;
var next = document.querySelectorAll(".tabNext");
var isLoad = false;
var navA = nav.getElementsByTagName('a');
var navActive = nav.getElementsByTagName('span')[0];
list.addEventListener('touchstart', function (e) {
if (isLoad) {
return;
}
list.style.transition = "none";
startPoint = {pageX: e.changedTouches[0].pageX, pageY: e.changedTouches[0].pageY};
startX = cssTransform(list, "translateX");
isMove = true;
isFirst = true;
}
);
list.addEventListener('touchmove', function (e) {
if (isLoad) {
return;
}
if (!isMove) {
return;
}
var nowPoint = e.changedTouches[0];
var disX = nowPoint.pageX - startPoint.pageX;
var disY = nowPoint.pageY - startPoint.pageY;
if (isFirst) {
isFirst = false;
if (Math.abs(disY) > Math.abs(disX)) {
isMove = false;
}
}
if (isMove) {
cssTransform(list, "translateX", startX + disX);
}
if (Math.abs(disX) > width / 2) {
end(disX);
}
}
);
function end(disX) {
isLoad = true;
var dir = disX / Math.abs(disX);
now -= dir;
if(now<0){
now = navA.length - 1;
}
if(now >= navA.length){
now = 0;
}
console.log(now);
var target = dir > 0 ? 0 : -2 * width;
list.style.transition = "300ms";
cssTransform(list, "translateX", target);
list.addEventListener('webkitTransitionEnd', tranEnd);
list.addEventListener('transitionend', tranEnd);
}
function tranEnd() {
var left = navA[now].offsetLeft;
cssTransform(navActive, 'translateX', left);
list.removeEventListener('webkitTransitionEnd', tranEnd);
list.removeEventListener('transitionend', tranEnd);
for (var i = 0; i < next.length; i++) {
next[i].style.opacity = 1;
}
setTimeout(function () {
list.style.transition = "none";
cssTransform(list, "translateX", -width);
isLoad = false;
}, 1000);
}
}
}