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

来源:互联网 发布:淘宝上迷彩服是正品吗 编辑:程序博客网 时间:2024/05/20 00:11

我最近写了一个类似于京东详情的一个滑屏切换,这是应客户需求写的,切换效果做出来了,如果要达到京东那种效果还需要动画切换,目前我对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);//滑动navInnerif(targetY>minTranslateY){targetY = 0;}else if(targetY < maxTranslateY){targetY = maxTranslateY;}css(this,'translateY',targetY);//设置手指抬起,垂直滑动的距离return false;});};

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


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

原创粉丝点击