效果图: {F1209}
功能描述:
- 点击右侧字母,自动滚动到字母对应的联系人列表
- 按住右侧字母列表并滑动,滑动过程中,左侧联系人列表跟随滑动。
相关技术: CSS、JavaScript、JQuery
实现方法:
- html中对目标块设置id="slider" 和class="slider-content",并对联系人目录title设置id="{{aleph}}"
- 在页面加载完成后,调用function,动态生成音序列,关键代码:data-ng-init="sliderNavi()"
- 动态生成音序列时,根据页面高度,动态设置字母单元格高度
- 为每个字母绑定触摸事件,关键代码:$scope.bindEvent();
- 监听touchstart事件,获取当前触发事件的“字母”,并获取对应联系人目录title的偏移量,滑动到对应title处。
- 监听touchmove事件,获取当前触摸点的偏移量(相对于第一次按下去的位置),计算出当前触摸点对应的字母检索处的字母(根据之前设定的字母单元格高度来计算),之后同上,获取对应联系人目录title的偏移量并滑动。
注意点: touchmove事件是指,手指按住对象A之后,在屏幕滑动过程中不断触发的一个事件,需要注意的是,在滑动过程中,该事件的target element永远是触发改事件的对象A,即使滑动过程中经过了对象B,并且B上也有监听事件,也不会触发B的事件。
核心代码: html:
<div id="slider" ng-show="showAllMan" data-ng-init="sliderNavi()" style="margin-top: 35px">
<div class="slider-content">
<ons-list ng-repeat="aleph in charTab" ng-init="indexAleph = $index"
ng-show="havaData[indexAleph]">
<ons-list-header id="{{aleph}}" style="color: #1284ff">{{aleph}}</ons-list-header>
<ons-list-item ng-repeat="nameList in saveChar[indexAleph] track by $index"
ng-click="goLinkManDetail(nameList)" ">
</ons-list-item>
</ons-list>
</div>
</div>
JS:
// 字母滑动检索功能
$scope.letters = new Array();
letters = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#"];
$scope.startY = 0;
$scope.moveY = 0;
$scope.startLetterIndex = 0;
$scope.currentLetterIndex = 0;
$scope.currentLetter = "";
$scope.letterHeight = 0;// 字母检索的高度
function touchStartFunc(event) {
var startletter = event.target.text;
$scope.startLetterIndex = letters.indexOf(startletter);
var touch = event.touches[0]; //获取第一个触点
var y = Number(touch.pageY); //页面触点Y坐标
startY = y; //记录触点初始位置
//moveY = 0; // 初始偏移量为 0
// 移动到当前对应字母序列
var cOffset = $('.slider-content').offset().top;// 获取偏移量
var tOffset = $('.slider-content #' + startletter).offset().top;// 获取当前标签偏移量
var height = $('.slider-nav').height();
var pScroll = (tOffset - cOffset) - height / 24;
// console.log("cOffset: " + cOffset + " tOffset:" + tOffset + " height:" + height + " pScroll:" + pScroll);
if (tOffset !== 0) $('.slider-content').stop().animate({scrollTop: '+=' + pScroll + 'px'});
};
function touchMoveFunc(event) {
event.preventDefault();//移动端touchmove只能触发一次的问题,加此代码即可连续触发了
var touch = event.touches[0]; //获取第一个触点
var y = Number(touch.pageY); //页面触点Y坐标
console.log("y = " + y + " | startY = " + startY);
//判断滑动方向 上下
if ((y - startY) % $scope.letterHeight === 0) {
currentLetterIndex = $scope.startLetterIndex + parseInt((y - startY) / $scope.letterHeight);
$scope.currentLetter = letters[currentLetterIndex];
console.log("currentLetter = " + $scope.currentLetter);
var cOffset = $('.slider-content').offset().top;// 获取偏移量
var tOffset = $('.slider-content #' + $scope.currentLetter).offset().top;// 获取当前标签偏移量
var height = $('.slider-nav').height();
var pScroll = (tOffset - cOffset) - height / 24;
// console.log("cOffset: " + cOffset + " tOffset:" + tOffset + " height:" + height + " pScroll:" + pScroll);
if (tOffset !== 0) $('.slider-content').stop().animate({scrollTop: '+=' + pScroll + 'px'});
}
};
// 加监听
$scope.bindEvent = function () {
for (i = 0; i < letters.length; i++) {
document.getElementById("#" + letters[i]).addEventListener('touchstart', touchStartFunc);
document.getElementById("#" + letters[i]).addEventListener('touchmove', touchMoveFunc);
}
}
$scope.isTouchDevice = function () {
console.log("支持TouchEvent事件");
$scope.bindEvent(); //绑定事件
};
$scope.sliderNavi = function (options) {
var o = {
items: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#"]
};
$(slider).append('<div class="slider-nav"><ul></ul></div>');// 加滚动条
for (var i in o.items) $('.slider-nav ul', slider).append("<li ><a id='#" + o.items[i] + "' alt= '#" + o.items[i] + "'>" + o.items[i] + "</a></li>");
var height = window.innerHeight;
$scope.letterHeight = parseInt((height - 77) / 30);// 取整,以防后续通过偏移量获取坐标时出现四舍五入不精确的情况。
$('.slider-content, .slider-nav', slider).css('height', height - 77);
$('.slider-nav ul li a', slider).css('height', $scope.letterHeight);
$('.slider-nav ul li a', slider).css('width', 30); //
/*$('.slider-nav a', slider).mouseover(function(event) {//mouseover(function (event) { on("scrollstart",function(){
var target = $(this).attr('alt');
var cOffset = $('.slider-content', slider).offset().top;// 获取偏移量
var tOffset = $('.slider-content ' + target, slider).offset().top;// 获取当前标签偏移量
var height = $('.slider-nav', slider).height();
if (o.height) height = o.height;
var pScroll = (tOffset - cOffset) - height / 30;
console.log("cOffset: " + cOffset + " tOffset:" + tOffset + " height:" + height + " pScroll:" + pScroll);
//$('.slider-content li', slider).removeClass('selected');
//$(target).addClass('selected');
if (tOffset !== 0) $('.slider-content', slider).stop().animate({scrollTop: '+=' + pScroll + 'px'});
console.log($(this).attr('alt'));
});*/ // 需要注释掉
// 绑定触摸事件
$scope.isTouchDevice();
};
CSS:
.slider { width: 300px; min-height: 250px; display: block; position: relative; background: #fff; overflow: hidden; }
.slider ul { list-style: none; }
.slider-content { float: left; width: 100%; display: block; overflow: auto; min-height: 250px; }
.slider-content ul { list-style: none; float: left; width: 100%; display: block; position: fixed; }
.slider-content ul li {list-style-type: none; float: left; width: 100%; }
.slider-content ul ul li a { list-style-type: none; padding: 5px 10px; display: block; border-bottom: 1px solid #f3f3f3; text-transform: capitalize; }
.slider-content ul ul li a:hover { background: #f3faff; border-color: #d5ebf9; }
.slider-content .title { padding: 5px 0; text-indent: 10px; background: #bbb; color: #fff; width: 100%; float: left; font-weight: bold; text-transform: uppercase; }
.slider-content .selected .title { background: #666; }
.slider-nav { position: fixed; right: 0; margin-top: 0px; background: #FFFFFF; min-height: 250px;z-index:3 }
.slider-nav ul { padding: 0px 0; }
.slider-nav ul li { list-style-type: none; text-align: center; }
.slider-nav li a { display: block; list-style-type: none; font-size: 60% ; text-align: center; color: #1284ff; font-weight: bold; text-transform: uppercase; cursor: po