仿京东的一个详情滑屏切换

1 篇文章 0 订阅

我最近写了一个类似于京东详情的一个滑屏切换,这是应客户需求写的,切换效果做出来了,如果要达到京东那种效果还需要动画切换,目前我对js运动有点迷茫,所以就没有运动效果,如果你很擅长运动,可以添加上去,我就不写了,以后还会封装一个库,到时候会添加运动,知识总是越学越会的,相信不久的将来,自己会把js运动写的游刃有余,现如今就从最简单的做起吧。这个滑屏切换效果说小不小,内在还是挺丰富的,我不能保证自己写的代码多优美,因为我还没有到达写出优美的境界,我现在最多意义上算是个实现者,可以把程序功能给实现,我也很崇拜那些写出优美代码的牛人,他们是自己的目标。慢慢来,“路漫漫其修远兮,吾将上下而求索”

jindong

 

这个就是我从京东上截取的效果图,不过我要做的是这个

hexi

 

效果:当我们用手指滑动下面内容的时候,可以切换到下一屏幕内容,同时上面的标签也会滑动到相应的列表项上

原理:给每一个版块添加touch事件,让它每一次滑动一个屏幕,同时,获取每个屏幕的序号,给对应的标签加样式,同时让标签滚动,如何设置这些标签的滚动距离,由于标签文字大小不一,不可能固定滚动多少长度,所以我取标签最大滑动距离除以标签个数,就得到每个标签平均滑动距离,从而让标签页滑动

 

html代码结构部分

<!--标签项-->
<nav class="nav bg1 pdl20 pdr20">
<div class="navInner">
<a href="" class="current">关于我们</a>
<a href="">企业景愿</a>
<a href="">招聘信息</a>
<a href="">新闻中心</a>
<a href="">招聘信息</a>
</div>
</nav>

内容项

<!--标签项-->
<section class="seParent pdt66">
<ul class="seParentInner">
<li class="sectionWrap">

<section class="section bg1 pdl20 pdr20 mgb14 mgl20 mgr20 pdt20">

<ul class="news">
<li>
<a href="" class="block"><img src="images/pic1.jpg" class="imgResponsive"/></a>
<div class="newTxt">
<h4>标题标题标题标题标题标题</h4>

<p>这里是内容这里是内容这里是内容这里是内容这里是内容
这里是内容这里是内容这里是内容这里是内容这里是内...</p>
</div>

</li>

</ul>
</section>
<section class="section bg1 pdl20 pdr20 mgb14 mgl20 mgr20 pdt20">

<ul class="news">
<li>
<a href="" class="block"><img src="images/pic1.jpg" class="imgResponsive"/></a>
<div class="newTxt">
<h4>标题标题标题标题标题标题</h4>

<p>这里是内容这里是内容这里是内容这里是内容这里是内容
这里是内容这里是内容这里是内容这里是内容这里是内...</p>
</div>

</li>

</ul>
</section>
<section class="section bg1 pdl20 pdr20 mgb14 mgl20 mgr20 pdt20">

<ul class="news">
<li>
<a href="" class="block"><img src="images/pic1.jpg" class="imgResponsive"/></a>
<div class="newTxt">
<h4>标题标题标题标题标题标题</h4>

<p>这里是内容这里是内容这里是内容这里是内容这里是内容
这里是内容这里是内容这里是内容这里是内容这里是内...</p>
</div>

</li>

</ul>
</section>
</li><!--sectionWrap-->
<li class="sectionWrap">
<article class="article bg1 pdl20 pdr20 mgb14 mgl20 mgr20 pdt20 pdb10">
<p>fdsfsdfsdf文字</p>
<p>fdsfsdfsdf文字</p>
<p>fdsfsdfsdf文字</p>
</article>
</li><!--sectionWrap-->
<li class="sectionWrap">
<article class="article bg1 pdl20 pdr20 mgb14 mgl20 mgr20 pdt20 pdb10">
<p>fdsfsdfsdf文字</p>
<p>fdsfsdfsdf文字</p>
<p>fdsfsdfsdf文字</p>
</article>
</li>
<li class="sectionWrap">
<article class="article bg1 pdl20 pdr20 mgb14 mgl20 mgr20 pdt20 pdb10">
<p>fdsfsdfsdf文字</p>
<p>fdsfsdfsdf文字</p>
<p>fdsfsdfsdf文字</p>
</article>
</li>
<li class="sectionWrap">
<article class="article bg1 pdl20 pdr20 mgb14 mgl20 mgr20 pdt20 pdb10">
<p>fdsfsdfsdf文字</p>
<p>fdsfsdfsdf文字</p>
<p>fdsfsdfsdf文字</p>
</article>
</li>
</ul><!--seParentInner-->
</section><!--seParent-->

内容项的结构为什么如此设计:首先我需要知道这个最外层的父标签需要包裹ul列表的标签,ul中每个li就是一个屏幕,多个li就会是多个屏幕,最外层的标签overflow,就会让内层li只显示一屏幕且没有滚动条。

写完了结构,我们看样式,具体内容样式,我就不写了,太长了,且没有必要,我写整体框架的样式:

.seParent{overflow: hidden;}//这一句就是一次只显示一屏幕,不会有滚动条
.seParent .seParentInner{overflow: hidden;}//这一句至关重要,我写这个的时候,栽的坑就在这,写了这个,touchmove的时候就会正常touchmove
.seParent .sectionWrap{float: left;}

接着我们看js部分

 

window.addEventListener('load',function(){
scroll({
parent:'.nav',
child :'.navInner',
li:'a',
ancestor:'.seParent',
content:'.seParentInner',
con_child:'.sectionWrap',
mr:0.6
});
});//这句页面装载结束,调用我们接下来写的滑屏切换函数

滑屏切换封装到一个函数中了,scroll,接下来我就一句一句分析,我也好重温一下当初的思路

function scroll(elem)
{
if(!elem){
return;//传进来的对象不存在突出
}
if(!elem.mr){
elem.mr=0;//设置默认的mr值
}
var oSection = document.querySelector(elem.parent);//获取nav的Dom对象
var oList = document.querySelector(elem.child);//获取navInner的Dom对象,这个对象将来要滑动作用
var oLi = oList.querySelectorAll(elem.li);//获取所有的a的Dom对象,这个用来计算整个navInner的宽度
var oAncestor = document.querySelector(elem.ancestor);//获取seParent的Dom对象
var oContent = document.querySelector(elem.content);//获取seParentInner的Dom对象,将来用来触发滑动事件
var oCon_child = oContent.querySelectorAll(elem.con_child);//获取每一个li的Dom对象
var html = parseFloat(document.documentElement.style.fontSize);//获取网页根元素大小,因为通篇是个手机站,运用flexible适配,所以要计算宽度
就要先获取整个html的fontSize大小,才会计算的精确。
var size = oLi.length;//获取每个a的个数
var count = oCon_child.length;//获取每个li的个数
var startEl = 0;//当前坐标水平位置移动的距离
var startElY =0;//当前坐标垂直位置移动距离
var startPoint;//当前横坐标位置
var startPointY;//当前纵坐标位置
var disX = 0;//水平移动的距离
var disY = 0;//垂直移动的距离
var target = 0;//水平目标位置距离
var targetY = 0;//纵向目标位置距离
var iWidth = 0;//.navInner标签的长度
var oConWidth = 100*count;
var oConChildWidth = 100/count;
var index = 0;
var aWidth = oAncestor.offsetWidth;
for(var i = 0;i<oLi.length;i++){
iWidth +=(oLi[i].offsetWidth+elem.mr*html);
}
oList.style.width=iWidth-20+'px';//设置整个navInner的宽度
for(var i = 0;i<oCon_child.length;i++){
oCon_child[i].style.width = oConChildWidth+'%';//设置每个li的宽度
}

oContent.style.width = oConWidth+'%';//设置色parentInner的宽度
var maxTranslateX = Math.round(oSection.clientWidth-0.4*html) - Math.round(oList.offsetWidth);//获取navInner滑动的最大距离
var maxTranslateY = (document.documentElement.clientHeight-2.8*html)-oAncestor.offsetHeight;separent中得li内容向上滑动最大距离
var minTranslateY = 1.25*html;//设置最小向上滑动距离
maxTranslateX = maxTranslateX>0?0:maxTranslateX;
oContent.style.height = oCon_child[index].offsetHeight+'px';//实时更新seParentInner的高度,这样做为了在不同大小内容的li向上滑动的时候,可
以实时获取最大的向上滑动距离。

oContent.addEventListener('touchstart',function(e){
startPoint = e.changedTouches[0].pageX;//获取按下坐标位置
startPointY = e.changedTouches[0].pageY;
startEl = css(this,'translateX');//获取当前对象translatex值,这里调用了另一个js文件,获取translate的值的函数
startElY = css(this,'translateY');
index = Math.round(-startEl/aWidth);//这里获取手指按下时当前li是第几个li,因为startEl是赋值,所以要用负号
return false;
});
oContent.addEventListener('touchmove',function(e){

e.preventDefault();//阻止浏览器默认事件,必须要有
var nowDis = e.changedTouches[0].pageX;//获取滑动坐标位置
var pageY = e.changedTouches[0].pageY;

disX = nowDis-startPoint;//滑动坐标减去按下坐标获取滑动距离
disY = pageY - startPointY;
if(Math.abs(disX)>Math.abs(disY)){//这里有个判断,如果水平滑动距离大于垂直滑动距离,就认为它是水平滑动,反之,是垂直滑动。
disX = disX+startEl;//用滑动距离加上起始位置距离就等于要设置的translate的距离
css(this,'translateX',disX);//设置移动的距离
css(this,'translateY',0);//水平滑动的时候设置垂直滑动距离为0,不会因为上一次垂直滑动的距离导致下一个li也滑动同样的距离
}else{
disY = disY+startElY;
css(this,'translateY',disY);//设置移动的距离
}
return false;

});
oContent.addEventListener('touchend',function(e){

var oListTarget = maxTranslateX/size;//获取每个a平均滚动距离
targetY = css(this,'translateY');//获取当前垂直滑动位置
target = css(this,'translateX');
maxTranslateY = (document.documentElement.clientHeight-2.8*html)-this.offsetHeight;//不断更新最大垂直滑动距离
maxTranslateY = maxTranslateY >0?0:maxTranslateY;//如果li的高度小于可视区域的高度,就让它最大滑动距离为0,反之为maxtranslateY;

index = Math.round(-target/aWidth);//更新li索引号
index = (index <=0?0:index>=size-1?size-1:index++);//如果当前li的索引号小于等于0,表示是第一个版面,让index为0,否则如果index>0t同时小于
最大索引号,让它索引号加1,以使得页面切换。

for(var i=0;i<oLi.length;i++){
oLi[i].className = '';
}
oLi[index].className = 'current';//给a标签加选中样式
css(this,'translateX',-aWidth*index);//移动li到制定版面
this.style.height = oCon_child[index].offsetHeight+'px';//实时更新li的高度,为了获得每个li最大滑动距离
css(oList,'translateX',oListTarget*index);//滑动navInner
if(targetY>minTranslateY){
targetY = 0;
}else if(targetY < maxTranslateY){
targetY = maxTranslateY;
}
css(this,'translateY',targetY);//设置手指抬起,垂直滑动的距离
return false;
});

};

 
通过对上面代码的分析,我对当初的思路是给肯定态度,但就是代码写的不美,朴实,就好比写文章,不精美,就是大白话,没关系,写代码的人都是不断努力进步的,未来两年我一定可以写出漂亮的代码,到时候不要把你看哭了。
关于整篇代码,你可以点击这里下载,测试哦。


转载:京东详情的一个滑屏切换

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值