练习 - javascript 触摸滑动程序
Posted myrocknroll
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了练习 - javascript 触摸滑动程序相关的知识,希望对你有一定的参考价值。
addTouchListWrapper
支持垂直、水平滑动、tab、轮播图等
//事件注册给哪个对象?默认document
var d = option.target == undefined ? document : option.target;
//指示线与ul滑动距离比
var scale = option.scale ? option.scale : 1;
//是单点还是多点触控,支持single、more,默认more
var isMorePointTouch = option.isMorePointTouch == undefined ? true : option.isMorePointTouch;
//滑动类型,取值:垂直tab、水平tab、垂直轮播、水平轮播
var slideType = option.slideType;
//导航小圆点的父元素
var circle = option.circle == undefined ? undefined : option.circle;
//是否自动轮播
var autoPlay = option.autoPlay == undefined ? false : option.autoPlay;
//tab指示线
var tabLine = option.tabLine;
//滑动前tab指示线上面的a元素
var slideNowElm = null;
//内容
var ul = option.ul;
//滑动前显示在屏幕以内的li
var slideNowElmLi = null;
//滑动定时器
var ms = 0;
//轮播图定时器
var timmer = null;
//手指触碰屏幕的X的起始位置
var startX = 0;
//tab指示线上一次滑动的translateX
var lastTransLateX_hr = null;
//内容上一次滑动的translateX
var lastTransLateX_ul = null;
//记录屏幕上所有滑动信息的数组
var touchInformation = [];
//自定义索引
var index = -1;
//上一个滑动的touc对象
var movingTouch = null;
//上一次滑动后的坐标
var beforeDistansX = null;
//touch对象唯一标识
var touch_identity = null;
//屏幕上的最新触摸点
var lastTouch = null;
//chrome passive
var passive = { passive: true };
function play() {
//定时滑动
timmer = setInterval( function () {
shuffling();
}, 1000 );
}
//轮播图无缝结合
function set_shuffling() {
var bool = slideType.includes( "水平" );
var t;
//第一个元素前面的最后一个元素
if ( slideNowElmLi.getAttribute( "index" ) == "last" ) {
t = bool ? ul.querySelector( "li:last-child" ).previousElementSibling.offsetLeft
: ul.querySelector( "li:last-child" ).previousElementSibling.offsetTop;
//替换为最后一个元素
ul.style.transitionDuration = "0ms";
ul.style.transform = ( bool ? "translateX" : "translateY" ) + "(-" + t + "px)";
slidebeforeTranslate_ul = t;
//更改slideNowElmLi为替换后的当前元素
slideNowElmLi = getNowElement( ul, ul.querySelectorAll( "li" ), bool ? 0 : 1 );
}
//最后一个元素后面的第一个元素
else if ( slideNowElmLi.getAttribute( "index" ) == "first" ) {
t = bool ? ul.querySelector( "li:first-child" ).nextElementSibling.offsetLeft
: ul.querySelector( "li:first-child" ).nextElementSibling.offsetTop;
//替换为第一个元素
ul.style.transitionDuration = "0ms";
ul.style.transform = bool ? "translateX(-" + t + "px)" : "translateY(-" + t + "px)";
slidebeforeTranslate_ul = t;
//更改slideNowElmLi为替换后的当前元素
slideNowElmLi = getNowElement( ul, ul.querySelectorAll( "li" ), bool ? 0 : 1 );
}
}
//自动轮播
function shuffling() {
var bool = slideType.includes( "水平" );
var distans_circle;
//当前屏幕上的li元素
slideNowElmLi = getNowElement( ul, ul.querySelectorAll( "li" ), bool ? 0 : 1 );
set_shuffling();
ul.style.transitionDuration = "300ms";
ul.style.transform = bool ? "translateX(-" + slideNowElmLi.nextElementSibling.offsetLeft + "px)" : "translateY(-" + slideNowElmLi.nextElementSibling.offsetTop + "px)";
if ( !circle ) return;
var circleIndex = slideNowElmLi.nextElementSibling.getAttribute( "circleIndex" );
bool ? distans_circle = circle.parentNode.querySelectorAll( "li" )[circleIndex].offsetLeft - parseFloat( getComputedStyle( circle ).marginLeft )
: distans_circle = circle.parentNode.querySelectorAll( "li" )[circleIndex].offsetTop - parseFloat( getComputedStyle( circle ).marginTop );
circle.style.transform = ( bool ? "translateX" : "translateY" ) + "(" + distans_circle + "px)";
}
//为第一张图和最后一张图的无缝结合动态添加节点
function addChild() {
var bool = slideType.includes( "水平" );
var first = ul.querySelector( "li:first-child" );
var last = ul.querySelector( "li:last-child" );
var newfirst = first.cloneNode( true );
newfirst.setAttribute( "index", "first" );
ul.appendChild( newfirst );
var newlast = last.cloneNode( true );
newlast.setAttribute( "index", "last" );
ul.prepend( newlast );
//将ul定位到第一张图片
ul.style.transitionDuration = "0s";
ul.style.transform = bool ? "translateX( -" + ul.parentNode.offsetWidth + "px)" : "translateY( -" + ul.parentNode.offsetHeight + "px)";
}
if ( slideType.includes( "轮播" ) ) {
addChild();
}
//启用自动轮播
if ( autoPlay ) play();
//如果当前滑动元素的translateX绝对等于参数2指定的元素与父元素的左边距,则返回真
function testRange( moving, elm, transType ) {
var movingTranslate;
if ( transType == 1 ) {
movingTranslate = moving.style.transform.replace( "translateY(", ‘‘ ).replace( "px)", ‘‘ ) == false ? 0 : parseFloat( moving.style.transform.replace( "translateY(", ‘‘ ).replace( "px)", ‘‘ ) );
if ( Math.abs( movingTranslate ) == elm.offsetTop ) return true;
}
else {
movingTranslate = moving.style.transform.replace( "translateX(", ‘‘ ).replace( "px)", ‘‘ ) == false ? 0 : parseFloat( moving.style.transform.replace( "translateX(", ‘‘ ).replace( "px)", ‘‘ ) );
if ( Math.abs( movingTranslate ) == elm.offsetLeft ) return true;
}
}
//获取当前指示线上面的a元素或屏幕以内的li元素
function getNowElement( moving, chiList, transType ) {
return Array.from( chiList ).filter( elm => {
if ( testRange( moving, elm, transType ) ) return elm;
} )[0];
}
//根据方向获取元素的translate
function getTranslaste( el, direction ) {
if ( direction == 1 ) {
return el.style.transform.replace( "translateY(", ‘‘ ).replace( "px)", ‘‘ ) == false ? 0 : parseFloat( el.style.transform.replace( "translateY(", ‘‘ ).replace( "px)", ‘‘ ) );
}
return el.style.transform.replace( "translateX(", ‘‘ ).replace( "px)", ‘‘ ) == false ? 0 : parseFloat( el.style.transform.replace( "translateX(", ‘‘ ).replace( "px)", ‘‘ ) );
}
//滑动中
function slideX( touch ) {
if ( touch.moveX - beforeDistansX == 0 ) { return; }
var ulDistans = 0;
var distans = 0;
var ulTranslate;
var bool = slideType.includes( "水平" );
if ( slideType.includes( "tab" ) ) {
var hrTranslate;
if ( slideType.includes( "水平" ) ) hrTranslate = getTranslaste( tabLine, 0 );
else hrTranslate = getTranslaste( tabLine, 1 );
}
if ( slideType.includes( "水平" ) ) ulTranslate = getTranslaste( ul, 0 );
else ulTranslate = getTranslaste( ul, 1 );
movingTouch = touch.touch_identity;
//手指左滑
if ( touch.moveX - beforeDistansX < 0 ) {
console.log( "手指左滑或上滑" );
//即时记录手指左滑的坐标,右滑(上滑)时用最后一个左滑坐标作为起始坐标计算左滑距离
touch.slideLeftEndPoint = touch.moveX;
touch.leftSlideTranslateX = hrTranslate == undefined ? null : hrTranslate;
touch.leftSlideTranslateX_ul = ulTranslate;
//最后一个元素不能左滑(上滑)
var translate = hrTranslate != undefined ? hrTranslate : ulTranslate;
var nowElm = hrTranslate != undefined ? slideNowElm : slideNowElmLi;
if ( translate != parseFloat( slideType.includes( "水平" ) ? nowElm.parentNode.offsetWidth : nowElm.parentNode.offsetHeight ) - parseFloat( slideType.includes( "水平" ) ? nowElm.offsetWidth : nowElm.offsetHeight ) ) {
var startPoint = touch.slideRightEndPoint == null ? touch.startX : touch.slideRightEndPoint;
if ( slideType.includes( "tab" ) ) {
distans = ( touch.rightSlideTranslateX == null ? touch.translateX_tabline : touch.rightSlideTranslateX ) + Math.abs( touch.moveX - startPoint ) * scale;
var slideAfterSibling = slideNowElm.nextElementSibling.nodeName.toLowerCase() == "a" ? slideNowElm.nextElementSibling : slideNowElm;
var leftOrTop = slideType.includes( "水平" ) ? slideAfterSibling.offsetLeft : slideAfterSibling.offsetTop;
if ( distans >= leftOrTop ) distans = leftOrTop;
console.log( distans );
slideType.includes( "水平" ) ? tabLine.style.transform = "translateX(" + distans + "px)" : tabLine.style.transform = "translateY(" + distans + "px)";
}
ulDistans = -( touch.rightSlideTranslateX_ul == null ? Math.abs( touch.translateX_ul ) : Math.abs( touch.rightSlideTranslateX_ul ) ) + ( touch.moveX - startPoint );
console.log( touch.translateX_ul );
var slideAfterSiblingLi = slideNowElmLi.nextElementSibling == null ? slideNowElmLi : slideNowElmLi.nextElementSibling;
var leftOrTop = slideType.includes( "水平" ) ? slideAfterSiblingLi.offsetLeft : slideAfterSiblingLi.offsetTop;
if ( Math.abs( ulDistans ) >= leftOrTop ) ulDistans = -leftOrTop;
ul.style.transform = ( bool ? "translateX" : "translateY" ) + "(" + ulDistans + "px)";
}
}
//手指右滑
else if ( touch.moveX - beforeDistansX > 0 ) {
console.log( "手指右滑或下滑" );
//即时记录手指右滑的坐标,左滑时用最后一个右滑坐标作为起始坐标计算右滑距离
touch.slideRightEndPoint = touch.moveX;
touch.rightSlideTranslateX = hrTranslate == undefined ? null : hrTranslate;
touch.rightSlideTranslateX_ul = ulTranslate;
//第一个元素不能右滑
var translate = hrTranslate != undefined ? hrTranslate : ulTranslate;
if ( translate != 0 ) {
var startPoint = touch.slideLeftEndPoint == null ? touch.startX : touch.slideLeftEndPoint;
if ( slideType.includes( "tab" ) ) {
distans = ( touch.leftSlideTranslateX == null ? touch.translateX_tabline : touch.leftSlideTranslateX ) - ( touch.moveX - startPoint ) * scale;
var slideBeforeSibling = slideNowElm.previousElementSibling == null ? slideNowElm : slideNowElm.previousElementSibling;
var leftOrTop = slideType.includes( "水平" ) ? slideBeforeSibling.offsetLeft : slideBeforeSibling.offsetTop;
if ( distans <= leftOrTop ) distans = leftOrTop;
slideType.includes( "水平" ) ? tabLine.style.transform = "translateX(" + distans + "px)" : tabLine.style.transform = "translateY(" + distans + "px)";
}
ulDistans = ( touch.leftSlideTranslateX_ul == null ? Math.abs( touch.translateX_ul ) : Math.abs( touch.leftSlideTranslateX_ul ) ) - ( touch.moveX - startPoint );
ulDistans = -ulDistans;
var slideBeforeSiblingLi = slideNowElmLi.previousElementSibling == null ? slideNowElmLi : slideNowElmLi.previousElementSibling;
var leftOrTop = slideType.includes( "水平" ) ? slideBeforeSiblingLi.offsetLeft : slideBeforeSiblingLi.offsetTop;
if ( ulDistans >= -( leftOrTop ) ) ulDistans = -( leftOrTop );
ul.style.transform = ( bool ? "translateX" : "translateY" ) + "(" + ulDistans + "px)";
}
}
beforeDistansX = touch.moveX;
lastTransLateX_hr = hrTranslate == undefined ? null : hrTranslate;
lastTransLateX_ul = ulTranslate;
}
//滑动未至,则原路退回,滑动过半,则自动吸附
function setRange( msflag ) {
var distans = 0;
var ulDistans = 0;
var circleIndex = null;
var bool = slideType.includes( "水平" );
if ( slideType.includes( "tab" ) ) {
var hrTranslate = bool ? getTranslaste( tabLine, 0 ) : getTranslaste( tabLine, 1 );
var slideBeforeSibling = slideNowElm.previousElementSibling;
var slideAfterSibling = slideNowElm.nextElementSibling;
var afterLeft = slideAfterSibling.nodeName.toLowerCase() != "a" ? null : bool ? parseFloat( slideAfterSibling.offsetLeft ) : parseFloat( slideAfterSibling.offsetTop );
var nowLeft = bool ? parseFloat( slideNowElm.offsetLeft ) : parseFloat( slideNowElm.offsetTop );
var beforeLeft = slideBeforeSibling == null ? null : bool ? parseFloat( slideBeforeSibling.offsetLeft ) : parseFloat( slideBeforeSibling.offsetTop );
}
var ulTranslate = bool ? Math.abs( getTranslaste( ul, 0 ) ) : Math.abs( getTranslaste( ul, 1 ) );
var slideBeforeSiblingLi = slideNowElmLi.previousElementSibling == null ? slideNowElmLi : slideNowElmLi.previousElementSibling;
var slideAfterSiblingLi = slideNowElmLi.nextElementSibling == null ? slideNowElmLi : slideNowElmLi.nextElementSibling;
var fatherWidth = bool ? parseFloat( ul.parentNode.offsetWidth ) : parseFloat( ul.parentNode.offsetHeight );
var nowLeft_ul;
var afterLeft_ul;
var beforeLeft_ul;
if ( bool ) {
nowLeft_ul = slideNowElmLi.offsetLeft;
afterLeft_ul = slideAfterSiblingLi.offsetLeft;
beforeLeft_ul = slideBeforeSiblingLi.offsetLeft;
}
else {
nowLeft_ul = slideNowElmLi.offsetTop;
afterLeft_ul = slideAfterSiblingLi.offsetTop;
beforeLeft_ul = slideBeforeSiblingLi.offsetTop;
}
if ( msflag && ulTranslate > nowLeft_ul ) { distans = afterLeft; ulDistans = afterLeft_ul; circleIndex = slideAfterSiblingLi.getAttribute( "circleIndex" ); }
else if ( msflag && ulTranslate < nowLeft_ul ) { distans = beforeLeft; ulDistans = beforeLeft_ul; circleIndex = slideBeforeSiblingLi.getAttribute( "circleIndex" ); }
else if ( ulTranslate - nowLeft_ul > fatherWidth / 2 ) { hrTranslate != undefined ? distans = afterLeft : ""; ulDistans = afterLeft_ul; circleIndex = slideAfterSiblingLi.getAttribute( "circleIndex" ); }
else if ( ulTranslate - nowLeft_ul < -fatherWidth / 2 ) { distans = beforeLeft; ulDistans = beforeLeft_ul; circleIndex = slideBeforeSiblingLi.getAttribute( "circleIndex" ); }
else { distans = nowLeft; ulDistans = nowLeft_ul; circleIndex = slideNowElmLi.getAttribute( "circleIndex" ); }
ul.style.transitionDuration = "300ms";
if ( bool ) {
if ( slideType.includes( "tab" ) ) {
tabLine.style.transitionDuration = "300ms";
tabLine.style.transform = "translateX(" + distans + "px)";
}
ul.style.transform = "translateX(" + -ulDistans + "px)";
}
else {
if ( slideType.includes( "tab" ) ) {
tabLine.style.transitionDuration = "300ms";
tabLine.style.transform = "translateY(" + distans + "px)";
}
ul.style.transform = "translateY(" + -ulDistans + "px)";
}
if ( circle ) {
var distans_circle;
distans_circle = bool ? circle.parentNode.querySelectorAll( "li" )[circleIndex].offsetLeft - parseFloat( getComputedStyle( circle ).marginLeft )
: circle.parentNode.querySelectorAll( "li" )[circleIndex].offsetTop - parseFloat( getComputedStyle( circle ).marginTop );
circle.style.transform = ( bool ? "translateX" : "translateY" ) + "(" + distans_circle + "px)";
}
//清空屏幕触控点信息
touchInformation = [];
index = -1;
beforeDistansX = null;
lastTransLateX_hr = null;
lastTransLateX_ul = null;
}
d.addEventListener( "touchstart", function ( e ) {
var slidebeforeTranslate_ul = 0;
var bool = slideType.includes( "水平" );
if ( getNowElement( ul, ul.querySelectorAll( "li" ), bool ? 0 : 1 ) != null ) {
//当前屏幕上的li元素
slideNowElmLi = getNowElement( ul, ul.querySelectorAll( "li" ), bool ? 0 : 1 );
}
if ( bool ) {
beforeDistansX = startX = e.touches[e.touches.length - 1].clientX;
if ( slideType.includes( "tab" ) ) {
if ( getNowElement( tabLine, tabLine.parentNode.querySelectorAll( "a" ), 0 ) != null ) {
//当前tab指示线上面的a元素
slideNowElm = getNowElement( tabLine, tabLine.parentNode.querySelectorAll( "a" ), 0 );
}
var slidebeforeTranslate_hr = Math.abs( getTranslaste( tabLine, 0 ) );
}
if ( slideType.includes( "轮播" ) ) {
if ( autoPlay ) clearInterval( timmer );//触摸时关掉定时滑动
set_shuffling();
}
}
else {
beforeDistansX = startX = e.touches[e.touches.length - 1].clientY;
if ( slideType.includes( "tab" ) ) {
if ( getNowElement( tabLine, tabLine.parentNode.querySelectorAll( "a" ), 1 ) != null ) {
//当前tab指示线上面的a元素
slideNowElm = getNowElement( tabLine, tabLine.parentNode.querySelectorAll( "a" ), 1 );
}
var slidebeforeTranslate_hr = Math.abs( getTranslaste( tabLine, 1 ) );
}
if ( slideType.includes( "轮播" ) ) {
if ( autoPlay ) clearInterval( timmer );//触摸时关掉定时滑动
set_shuffling();
}
}
slidebeforeTranslate_ul = Math.abs( getTranslaste( ul, bool ? 0 : 1 ) );
touch_identity = e.touches[e.touches.length - 1].identifier;
touchInformation.push( {
//触摸唯一标识
touch_identity: touch_identity,
//自定义索引
index: ++index,
//起始坐标
startX: startX,
//移动坐标
moveX: startX,
//tab指示线的偏移距离
translateX_tabline: slidebeforeTranslate_hr,
//ul的偏移距离
translateX_ul: slidebeforeTranslate_ul,
//tab指示线左滑实时translateX
leftSlideTranslateX: null,
//tab指示线右滑实时translateX
rightSlideTranslateX: null,
//ul左滑实时translateX
leftSlideTranslateX_ul: null,
//ul右滑时实时偏移距离
rightSlideTranslateX_ul: null,
//右滑实时移动点
slideRightEndPoint: null,
//左滑实时移动点
slideLeftEndPoint: null,
//上一个移动点
beforeDistansX: startX
} );
if ( slideType.includes( "tab" ) ) tabLine.style.transitionDuration = "0ms";
ul.style.transitionDuration = "0ms";
ms = new Date().getTime();
}, passive );
d.addEventListener( "touchmove", function ( e ) {
if ( touchInformation == null ) return;
lastTouch = e.touches[e.touches.length - 1];
length = touchInformation.length;
var touch;
for ( var i = length - 1; i >= 0; i-- ) {
//只有接触屏幕的最后一根手指才可以滑动
if ( touchInformation[i].touch_identity == lastTouch.identifier ) {
touch = touchInformation[i];
break;
}
}
//多点触控
if ( isMorePointTouch ) {
if ( lastTouch.identifier != movingTouch ) {
if ( slideType.includes( "tab" ) ) touch.translateX_tabline = lastTransLateX_hr == null ? touch.translateX_tabline : lastTransLateX_hr;
touch.translateX_ul = lastTransLateX_ul == null ? touch.translateX_ul : lastTransLateX_ul;
touch.rightSlideTranslateX = touch.rightSlideTranslateX_ul = touch.leftSlideTranslateX = touch.leftSlideTranslateX_ul = touch.slideLeftEndPoint = touch.slideRightEndPoint = null;
if ( slideType.includes( "水平" ) ) touch.startX = lastTouch.clientX;
else touch.startX = lastTouch.clientY;
}
}
//单点触控
else {
if ( lastTouch.identifier != movingTouch && movingTouch != null ) {
setRange();
return;
}
}
if ( slideType.includes( "水平" ) ) touch.moveX = lastTouch.clientX;
else touch.moveX = lastTouch.clientY;
lastTouch = touch;
slideX( lastTouch );
}, passive );
d.addEventListener( "touchend", function ( e ) {
//删除touchInformation中抬起的touch对象
index -= 1;
//不设置吸附
if ( slideType.includes( "tab" ) ) {
if ( getNowElement( tabLine, tabLine.parentNode.querySelectorAll( "a" ), slideType.includes( "水平" ), slideType.includes( "水平" ) ? 0 : 1 ) != null ) {
return;
}
}
if ( e.touches.length == 0 ) {
var flag = new Date().getTime() - ms <= 200;
setRange( flag );
if ( slideType.includes( "tab" ) ) tabLine.style.transition = "none 0 ease";
ul.style.transition = "none 0 ease";
if ( autoPlay ) {
play();
}
}
}, passive );
d.addEventListener( "touchcancel", function ( e ) {
setRange();
if ( slideType.includes( "tab" ) ) tabLine.style.transition = "none 0 ease";
ul.style.transition = "none 0 ease";
if ( autoPlay ) {
play();
}
}, passive );
}
多个触摸点
已实现多点触控,你可以建立第1、第2、第3、第n个触控点,只有最新加入的触控点才可以滑动,除非它离开了屏幕,一旦它离开屏幕,那么最后一个触控点就是紧靠它前面的那个触控点。滑动顺序为n……、3、2、1。另外,按照e.touches对触控点的存储规则,比如前两根手指触控屏幕,接着第一根手指离开屏幕,此时再重新触控屏幕,那么新的手指的触控点会替换掉第一根手指原来的触控点,原来的触控点的索引为0,那么新的触控点的索引就是0(索引覆盖),而不是最后一个索引。这导致新加入的触控点不能滑动,因为它的索引是0,而最后一个触控点的索引是1(第二根手指)。参考:触摸事件 - e.touches。
非全屏滑动
支持非全屏的滑动,但本程序依赖于offsetLeft,该属性需要正确找到元素离父元素的offsetLeft,参照以下各种例子中的position定位设置才行。
六种模式
水平简约
不实现无缝结合。第一张不能右滑,最后一张不能左滑。
padding: 0;
margin: 0;
font-size: 3.3vw;
color: #fff;
text-decoration: none;
list-style: none;
font-family: 微软雅黑;
}
.content-wrapper {
position: relative;
width: 100%;
overflow: hidden;
}
.content-wrapper .content-ul {
overflow: hidden;
width: 600%;
}
.content-wrapper .content-ul li {
float: left;
width: 16.66%;
height: 135.74vw;
}
.content-wrapper .content-ul li img {
width: 100%;
height: 100%;
}
<div class="content-wrapper">
<ul class="content-ul">
<li circleIndex="0"><img src="./Img/x1.jpg" /> </li>
<li circleIndex="1"><img src="./Img/x2.jpg" /></li>
<li circleIndex="2"><img src="./Img/x3.jpg" /></li>
<li circleIndex="3"><img src="./Img/x4.jpg" /></li>
</ul>
</div>
window.onload = function () {
var $ = document.querySelector.bind( document );
var ul = $( ".content-ul" );
addTouchListWrapper( {
//滑动类型:水平简约、水平tab、水平轮播、垂直简约、垂直tab、垂直轮播
slideType: "水平简约",
ul: ul
} );
}
水平轮播图
实现第一张和最后一张图切换时的无缝结合,不需要在第一张和最后一张前加图片,但你需要在css中把多出的两张图的宽度计算进每个li的宽度百分比。
padding: 0;
margin: 0;
font-size: 3.3vw;
color: #fff;
text-decoration: none;
list-style: none;
font-family: 微软雅黑;
}
.content-wrapper {
position: relative;
width: 100%;
overflow: hidden;
}
.content-wrapper .content-ul {
overflow: hidden;
width: 600%; /*一共四张图,但js动态添加了两张,所以是600%*/
}
.content-wrapper .content-ul li {
float: left;
width: 16.66%; /*一共四张图,但js动态添加了两张,每张占比16.66%*/
height: 150vw;
}
.content-wrapper .content-ul li img {
width: 100%;
}
.content-wrapper .little-circle-ul {
overflow: hidden;
position: absolute;
top: 30vw;
left: 50%;
transform: translateX(-50%);
}
.content-wrapper .little-circle-ul li {
float: left;
width: 3.33vw;
height: 3.33vw;
margin: 0 2.06vw;
border: 0.13vw solid #fff;
border-radius: 50%;
}
.little-circle-ul .active {
position: absolute;
width: 3.33vw;
height: 3.33vw;
background: #b6ff00;
}
<div class="content-wrapper">
<ul class="content-ul">
<li circleIndex="0"><img src="./Img/x1.jpg" /> </li>
<li circleIndex="1"><img src="./Img/x2.jpg" /></li>
<li circleIndex="2"><img src="./Img/x3.jpg" /></li>
<li circleIndex="3"><img src="./Img/x4.jpg" /></li>
</ul>
<ul class="little-circle-ul">
<li></li>
<li></li>
<li></li>
<li></li>
<li class="active"></li>
</ul>
</div>
window.onload = function () {
var $ = document.querySelector.bind( document );
var ul = $( ".content-ul" );
addTouchListWrapper( {
//滑动类型:水平简约、水平tab、水平轮播、垂直简约、垂直tab、垂直轮播
slideType: "水平轮播",
//是否自动轮播,默认false
autoPlay: true,
//圆点,如果不提供circle,则轮播时不调用圆点。
//在此例中,圆点列表是4个,多出的这个circle是额外的,需要把这个circle绝对定位到第一个圆点处,以便滑动程序控制它移动,其它四个圆点起始是保持不动的
circle: $( ".active" ),
ul: ul
} );
}
水平tab
不实现无缝结合。第一张不能右滑,最后一张不能左滑。
padding: 0;
margin: 0;
font-size: 3.3vw;
color: #fff;
text-decoration: none;
list-style: none;
font-family: 微软雅黑;
}
.tab-box {
position: relative;
width: 100%;
height: 12vw;
margin: auto;
overflow: hidden;
line-height: 12vw;
text-align: center;
background: #000;
}
.tab-box a {
float: left;
width: 25%;
height: inherit;
}
.tabLine {
position: absolute;
left: 9.067vw;
bottom: 0;
width: 7vw;
height: 0.5vw;
background: #fff;
}
/*.tabLine {
position: absolute;
left:0;
bottom: 0;
width: 25vw;
height: 0.5vw;
background: #cfff56;
}*/
/*.tabLine {
position: absolute;
left: 0;
bottom: 0;
width: 25vw;
height: 12.5vw;
background: #fff;
opacity: 0.3;
z-index: 1;
}*/
.content-wrapper {
position: relative;
width: 100%;
overflow: hidden;
}
.content-wrapper .content-ul {
overflow: hidden;
width: 600%;
}
.content-wrapper .content-ul li {
float: left;
width: 16.66%;
height: 150vw;
}
.content-wrapper .content-ul li img {
width: 100%;
}
<div class="tab-box">
<a href="#" style="background:#2a2b2f;">山魈</a>
<a href="#" style="background:#9f0105;">寒食</a>
<a href="#" style="background:#118eb8;">训诂</a>
<a href="#" style="background:#c4282b;">觞逝</a>
<div class="tabLine"></div>
</div>
<div class="content-wrapper">
<ul class="content-ul">
<li circleIndex="0"><img src="./Img/x1.jpg" /> </li>
<li circleIndex="1"><img src="./Img/x2.jpg" /></li>
<li circleIndex="2"><img src="./Img/x3.jpg" /></li>
<li circleIndex="3"><img src="./Img/x4.jpg" /></li>
</ul>
</div>
window.onload = function () {
var $ = document.querySelector.bind( document );
var tabLine = $( ".tabLine" );
var ul = $( ".content-ul" );
var scale = tabLine.parentNode.querySelector( "a" ).offsetWidth / ( window.screen.width ); //tab指示线与ul的滑动距离比
addTouchListWrapper( {
slideType: "水平tab",
tabLine: tabLine,
ul: ul,
scale: scale
} );
}
tab有三种css风格
三种风格可以参照以上注释掉的tabLine的css
========短线========
========长线========
========框========
tab注意
1.tab指示线通过position定位到起始位置,css中不要用translateX定位,也不要设置其transition(js里已经做了处理)
2.盒子内所有元素都不要设置padding和margin,只需要设置a元素的宽度,a元素内可以加其他内容
3.指示线定位时可以在chrome浏览器里逐步设置其偏移,直到其位置正确为止。短线风格:tab指示线必须定位到a元素的下面,与a元素离父元素的距离相等才行,例子中的tab指示线定位在第一个a元素的下面,此时它的translateX是0,而a元素离父元素的距离恰好也是0。如果一开始就需要将tab指示线的起始位置定位在非第一个a元素下,不要在css中这样做,你可以在js里在调用滑动函数之前通过编程将tab指示线定位,这样可以保证指示线的起始translateX是在第一个a元素下,否则会出问题。你可以载js中如下处理将tab指示线定位在其它a元素下:
ul.style.transform = "translateX(-" + ul.querySelector( "li" ).offsetWidth + "px)";
垂直简约
padding: 0;
margin: 0;
font-size: 3.3vw;
color: #fff;
text-decoration: none;
list-style: none;
font-family: 微软雅黑;
}
.content-wrapper {
position: relative;
width: 100%;
height: 135.74vw;
overflow: hidden;
}
.content-wrapper .content-ul {
overflow: hidden;
width: 100%;
height: 400%;
}
.content-wrapper .content-ul li {
width: 100%;
height: 135.74vw;
}
.content-wrapper .content-ul li img {
width: 100%;
height: 100%;
}
<div class="content-wrapper">
<ul class="content-ul">
<li circleIndex="0"><img src="./Img/x1.jpg" /> </li>
<li circleIndex="1"><img src="./Img/x2.jpg" /></li>
<li circleIndex="2"><img src="./Img/x3.jpg" /></li>
<li circleIndex="3"><img src="./Img/x4.jpg" /></li>
</ul>
</div>
window.onload = function () {
var $ = document.querySelector.bind( document );
var ul = $( ".content-ul" );
addTouchListWrapper( {
//滑动类型:水平简约、水平tab、水平轮播、垂直简约、垂直tab、垂直轮播
slideType: "垂直简约",
ul: ul
} );
}
垂直轮播图
padding: 0;
margin: 0;
font-size: 3.3vw;
color: #fff;
text-decoration: none;
list-style: none;
font-family: 微软雅黑;
}
.content-wrapper {
position: relative;
width: 100%;
height: 135.74vw;
overflow: hidden;
}
.content-wrapper .content-ul {
overflow: hidden;
width: 100%;
height: 600%;
}
.content-wrapper .content-ul li {
width: 100%;
height: 16.66%;
}
.content-wrapper .content-ul li img {
width: 100%;
height: 100%;
}
.content-wrapper .little-circle-ul {
overflow: hidden;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
.content-wrapper .little-circle-ul li {
position: relative;
width: 2.49vw;
height: 2.49vw;
margin: 3vw 0;
border-radius: 50%;
border: 0.5vw solid #fff;
}
.content-wrapper .little-circle-ul .active {
position: absolute;
top: 0;
background: #8f00ff;
}
<div class="content-wrapper">
<ul class="content-ul">
<li circleIndex="0"><img src="./Img/x1.jpg" /> </li>
<li circleIndex="1"><img src="./Img/x2.jpg" /></li>
<li circleIndex="2"><img src="./Img/x3.jpg" /></li>
<li circleIndex="3"><img src="./Img/x4.jpg" /></li>
</ul>
<ul class="little-circle-ul">
<li></li>
<li></li>
<li></li>
<li></li>
<li class="active"></li>
</ul>
</div>
window.onload = function () {
var $ = document.querySelector.bind( document );
var ul = $( ".content-ul" );
addTouchListWrapper( {
//滑动类型:水平简约、水平tab、水平轮播、垂直简约、垂直tab、垂直轮播
slideType: "垂直轮播",
//是否自动轮播,默认false
autoPlay: true,
//圆点,如果不设置circle,则轮播时不调用圆点。
//在此例中,圆点列表是4个,多出的这个circle是额外的,需要把circle绝对定位到第一个圆点处,以便滑动程序控制它移动,其它四个圆点保持不动
circle: $( ".active" ),
ul: ul
} );
}
垂直tab
padding: 0;
margin: 0;
font-size: 3.3vw;
color: #fff;
text-decoration: none;
list-style: none;
font-family: 微软雅黑;
}
.tab-box {
position: fixed;
right: 0;
width: 12.07vw;
z-index: 1;
}
.tab-box a {
display: block;
border-radius:12.62vw;
width: 12.07vw;
height: 12.07vw;
}
.tab-box a div {
width: 3.3vw;
height: inherit;
margin: auto;
padding-top: 7px;
box-sizing: border-box;
}
/*.tabLine {
position: absolute;
top: 11px;
bottom: 0;
width: 0.5vw;
height: 7vw;
background: #fff;
}*/
/*.tabLine {
position: absolute;
top:0;
width: 0.5vw;
height: 12.07vw;
background: #fff;
}*/
.tabLine {
position: absolute;
top:0;
width: 12.07vw;
height: 12.07vw;
background: #ff3700;
opacity: 0.25;
z-index: 1;
border-radius:12.62vw;
}
.content-wrapper {
position: relative;
width: 100%;
height: 135.74vw;
overflow: hidden;
}
.content-wrapper .content-ul {
overflow: hidden;
width: 100%;
height: 400%;
}
.content-wrapper .content-ul li {
width: 100%;
height: 135.74vw;
}
.content-wrapper .content-ul li img {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div class="tab-box">
<a href="#"><div>山魈</div></a>
<a href="#"><div>寒食</div></a>
<a href="#"><div>训诂</div></a>
<a href="#"><div>觞逝</div></a>
<div class="tabLine"></div>
</div>
<div class="content-wrapper">
<ul class="content-ul">
<li circleIndex="0"><img src="./Img/x1.jpg" /> </li>
<li circleIndex="1"><img src="./Img/x2.jpg" /></li>
<li circleIndex="2"><img src="./Img/x3.jpg" /></li>
<li circleIndex="3"><img src="./Img/x4.jpg" /></li>
</ul>
</div>
var $ = document.querySelector.bind( document );
var tabLine = $( ".tabLine" );
var ul = $( ".content-ul" );
var scale = tabLine.parentNode.querySelector( "a" ).offsetHeight / ( ul.parentNode.offsetHeight ); //tab指示线与ul的滑动距离比
addTouchListWrapper( {
slideType:"垂直tab",
tabLine: tabLine,
ul: ul,
scale: scale
} );
}
源代码下载:列表滑动
以上是关于练习 - javascript 触摸滑动程序的主要内容,如果未能解决你的问题,请参考以下文章