需求:做一个仿电商或者b站右侧 那样的楼层导航
环境:原生js
学习知识点:
- 练习scroll家族
- 练习client家族
- 练习缓动动画、定时器
- 练习函数封装
- 学习json遍历
- 学习style[]传参
- 练习简单闭包
- 熟悉回调思想
封装的工具包myFunc.js
/**
* 获取滚动的头部距离和左边距离
* scroll().top scroll().left
* @returns {*}
*/
function scroll() {
if(window.pageYOffset !== null){
return {
top: window.pageYOffset,
left: window.pageXOffset
}
}else if(document.compatMode === "CSS1Compat"){ // W3C
return {
top: document.documentElement.scrollTop,
left: document.documentElement.scrollLeft
}
}
return {
top: document.body.scrollTop,
left: document.body.scrollLeft
}
}
function $(id) {
return typeof id === "string" ? document.getElementById(id) : null;
}
/**
* 获取屏幕的宽度和高度
* @returns {*}
*/
function client() {
if(window.innerWidth){ // ie9+ 最新的浏览器
return {
width: window.innerWidth,
height: window.innerHeight
}
}else if(document.compatMode === "CSS1Compat"){ // W3C
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight
}
}
return {
width: document.body.clientWidth,
height: document.body.clientHeight
}
}
/**
* 缓动动画
* @param obj
* @param json
* @param fn
*/
function buffer(obj, json, fn) {
// 1.1 清除定时器
clearInterval(obj.timer);
// 1.2 设置定时器
var begin = 0, target = 0, speed = 0;
obj.timer = setInterval(function () {
// 1.3.0 旗帜
var flag = true;
for(var k in json){
// 1.3 获取初始值
if("opacity" === k){ // 透明度
begin = Math.round(parseFloat(getCSSAttrValue(obj, k)) * 100) || 100;
target = parseInt(json[k] * 100);
}else if("scrollTop" === k){
begin = Math.ceil(obj.scrollTop);
target = parseInt(json[k]);
}else { // 其他情况
begin = parseInt(getCSSAttrValue(obj, k)) || 0;
target = parseInt(json[k]);
}
// 1.4 求出步长
speed = (target - begin) * 0.2;
// 1.5 判断是否向上取整
speed = (target > begin) ? Math.ceil(speed) : Math.floor(speed);
// 1.6 动起来
if("opacity" === k){ // 透明度
// w3c的浏览器
obj.style.opacity = (begin + speed) / 100;
// ie 浏览器
obj.style.filter = 'alpha(opacity:' + (begin + speed) +')';
}else if("scrollTop" === k){
obj.scrollTop = begin + speed;
}else {
obj.style[k] = begin + speed + "px";
}
console.log(begin, target);
// 1.5 判断
if(begin !== target){
flag = false;
}
}
// 1.3 清除定时器
if(flag){
clearInterval(obj.timer);
console.log(fn);
// 判断有没有回调函数
if(fn){
fn();
}
}
}, 20);
}
主体实现index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
*{
margin: 0;
padding: 0;
list-style: none;
border:0;
}
html, body, ul{
width: 100%;
height: 100%;
}
#ul li{
width: 100%;
height: 100%;
text-align: center;
font-size: 30px;
/*background-color: red;*/
color: #fff;
}
#ol{
width: 80px;
background-color: #ccc;
position: fixed;
left: 50px;
top: 200px;
border: 1px solid #fff;
}
#ol li{
text-align: center;
line-height: 30px;
border-bottom: 1px solid #fff;
color: #fff;
cursor: pointer;
}
#ol li.current{
background-color: orangered;
}
</style>
</head>
<body>
<!--GPS-->
<ol id="ol">
<li class="current">第1层</li>
<li>第2层</li>
<li>第3层</li>
<li>第4层</li>
<li>第5层</li>
</ol>
<!--楼层-->
<ul id="ul">
<li>第1层内容</li>
<li>第2层内容</li>
<li>第3层内容</li>
<li>第4层内容</li>
<li>第5层内容</li>
</ul>
<script src="js/myFunc.js"></script>
<script>
window.onload = function () {
// 1. 获取需要的标签
var ol = $('ol'), ul = $('ul');
var ulLis = ul.children;
var olLis = ol.children;
//设置变量分离"自由滚动"和"点击导航滚动",使相互不影响
var isClick = false;
// 2. 上色
var colorArr = ['red', 'green', 'blue', 'purple', 'yellow'];
for(var i=0; i<colorArr.length; i++){
ulLis[i].style.backgroundColor = colorArr[i];
}
// 3. 监听GPS的点击
for(var j=0; j<olLis.length; j++){
(function (index) {
var olLi = olLis[index];
// 3.1 点击切换
olLi.onmousedown = function () {
isClick = true;
for(var i = 0; i<olLis.length; i++){
olLis[i].className = "";
}
this.className = "current";
// 3.2 让内容滚动起来
// document.documentElement.scrollTop = index * client().height;
buffer(document.documentElement, {scrollTop: index * client().height}, function () {
isClick = false;
});
}
})(j);
}
// 4.监听滚动
window.onscroll = function () {
if(!isClick){
// 4.1 获取滚动产生的高度
var roll = Math.ceil(scroll().top);
// 4.2 遍历
for(var i=0; i<olLis.length; i++){
// 4.3 判断
if(roll >= ulLis[i].offsetTop){
for(var j=0; j<olLis.length; j++){
olLis[j].className = "";
}
olLis[i].className = "current";
}
}
}
}
}
</script>
</body>
总结:
发现兼容性很差,ie不兼容
网友评论