上图:
1.derective代码
.directive('monthPicker', function ($ionicScrollDelegate) {
return {
restrict: 'E',
templateUrl: 'component/tab_bill/month-picker.html',
scope: {
localDate: '='
},
link: function ($scope) {
var yearIndex = 0, year = new Date().getFullYear() + 2, localYear = new Date().getFullYear(),
localMonth = month = new Date().getMonth() + 1, localDay = new Date().getDate();
var monthIndex = 0, month = new Date().getMonth() + 1;
if (month < 10) {
month = '0' + month
}
if (localMonth < 10) {
localMonth = '0' + localMonth;
}
if (localMonth < 10) {
localDay = '0' + localDay;
}
var dayIndex = 0;
$scope.years = []; // 年数组
$scope.months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
$scope.days = [];
var spar = {
28: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28'],
29: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29'],
30: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30'],
31: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31']
};
// $scope.hasDate = false; // 是否选择需要选择日期
$scope.changeFlag = 1; // 1是开始时间,2是结束时间
for (var i = 2000; i <= year; i++) {
$scope.years.push(i)
}
var loop1, loop2, loop3;
var checkTag = 0, checkTag2 = 0, checkTag3 = 0;
var _endDay, _endYear, _endMonth; $scope.goChoose = function () {
$scope.blockFlag = true;
setTimeout(function () {
_initScroll()
},300)
}; $scope.$on('initPicker', function (scope, unReset) {
if (!unReset) {
$scope.localDate = angular.extend($scope.localDate, {
startYear: localYear,
startMonth: localMonth,
startDay: localDay,
endYear: localYear,
endMonth: localMonth,
endDay: localDay
});
_initScroll();
return;
} _endDay = $scope.localDate.endDay;
_endYear = $scope.localDate.endYear;
_endMonth = $scope.localDate.endMonth;
_initScroll();
}); $scope.check1 = function () {
clearInterval(loop1);
if (checkTag < 0) {
return false;
}
checkTag = 0;
loop1 = setInterval(function () {
checkTag++;
if (checkTag > 2) {
chooseYear();
checkTag = -1;
}
}, 100)
};
$scope.check2 = function () {
clearInterval(loop2);
if (checkTag2 < 0) {
return false;
}
checkTag2 = 0;
loop2 = setInterval(function () {
checkTag2++;
if (checkTag2 > 2) {
chooseMonth();
checkTag2 = -1;
}
}, 100)
};
$scope.check3 = function () {
clearInterval(loop3);
if (checkTag3 < 0) {
return false;
}
checkTag3 = 0;
loop3 = setInterval(function () {
checkTag3++;
if (checkTag3 > 2) {
chooseDay();
checkTag3 = -1;
}
}, 100)
};
$scope.changeType = function () {
if ($scope.hasDate) {
$scope.hasDate = !$scope.hasDate;
$scope.blockFlag = false;
$scope.localDate = angular.extend($scope.localDate, {
startYear: '',
startMonth: '',
startDay: '',
endYear: '',
endMonth: '',
endDay: ''
});
return;
}
$scope.hasDate = !$scope.hasDate;
if ($scope.hasDate) {
$scope.localDate = angular.extend($scope.localDate, {
startYear: localYear,
startMonth: localMonth,
startDay: localDay,
endYear: localYear,
endMonth: localMonth,
endDay: localDay
});
$scope.days = spar[getDaysInOneMonth(localYear, localMonth)];
setTimeout(function () {
_initScroll()
},100)
} else {
$scope.localDate.startYear = $scope.localDate.endYear;
$scope.localDate.startMonth = $scope.localDate.endMonth;
$scope.localDate.startDay = $scope.localDate.endDay;
_initScroll()
}
};
$scope.setDate = function () {
if ($scope.changeFlag === 1) {
$scope.localDate.startYear = $scope.years[yearIndex];
$scope.localDate.startMonth = $scope.months[monthIndex];
if (!$scope.hasDate) {
$scope.localDate.endYear = $scope.years[yearIndex];
$scope.localDate.endMonth = $scope.months[monthIndex];
$scope.localDate.startDay = '01';
$scope.localDate.endDay = getDaysInOneMonth($scope.years[yearIndex], $scope.months[monthIndex]);
} else {
$scope.localDate.startDay = $scope.days[dayIndex];
}
} else {
$scope.localDate.endYear = $scope.years[yearIndex];
$scope.localDate.endMonth = $scope.months[monthIndex];
$scope.localDate.endDay = $scope.days[dayIndex];
}
console.log($scope.localDate)
}; $scope.setTime = function (num, _year, _month, _day) {
$scope.changeFlag = num;
if (!_year) {
_year = $scope.localDate.startYear;
_month = $scope.localDate.startMonth;
_day = $scope.localDate.startDay;
}
$ionicScrollDelegate.$getByHandle('scroll1').scrollTop();
$ionicScrollDelegate.$getByHandle('scroll2').scrollTop();
$ionicScrollDelegate.$getByHandle('scroll3').scrollTop();
_animation(_year, _month, _day)
};
function chooseYear() {
var top = $ionicScrollDelegate.$getByHandle('scroll1').getScrollPosition().top;
yearIndex = (top / 44).toFixed(0);
$ionicScrollDelegate.$getByHandle('scroll1').scrollTo(0, yearIndex * 44);
_initDate();
$scope.setDate();
setTimeout(function () {
checkTag = 0;
clearInterval(loop1);
$scope.$apply();
}, 100)
} function chooseMonth() {
var top = $ionicScrollDelegate.$getByHandle('scroll2').getScrollPosition().top;
monthIndex = (top / 44).toFixed(0);
$ionicScrollDelegate.$getByHandle('scroll2').scrollTo(0, monthIndex * 44);
_initDate();
$scope.setDate();
setTimeout(function () {
checkTag2 = 0;
clearInterval(loop2);
$scope.$apply();
}, 100)
} function chooseDay() {
var top = $ionicScrollDelegate.$getByHandle('scroll3').getScrollPosition().top;
dayIndex = Number((top / 44).toFixed(0));
$ionicScrollDelegate.$getByHandle('scroll3').scrollTo(0, dayIndex * 44);
$scope.setDate();
setTimeout(function () {
checkTag3 = 0;
clearInterval(loop3);
$scope.$apply();
}, 100)
} function _animation(year, month, day) {
$ionicScrollDelegate.$getByHandle('scroll1').scrollTop();
$ionicScrollDelegate.$getByHandle('scroll2').scrollTop();
for (var i = 0; i < $scope.years.length; i++) {
if ($scope.years[i] == year) {
yearIndex = i;
$ionicScrollDelegate.$getByHandle('scroll1').scrollTo(0, yearIndex * 44);
}
}
for (var j = 0; j < 12; j++) {
if ($scope.months[j] == month) {
monthIndex = j;
$ionicScrollDelegate.$getByHandle('scroll2').scrollTo(0, monthIndex * 44);
}
}
if (day) {
for (var k = 0; k < 32; k++) {
if ($scope.days[k] == day) {
dayIndex = k;
$ionicScrollDelegate.$getByHandle('scroll3').scrollTo(0, dayIndex * 44);
}
}
}
} function _initDate() {
var sparNum = getDaysInOneMonth($scope.years[yearIndex], $scope.months[monthIndex]);
$scope.days = spar[sparNum];
if (dayIndex + 1 > sparNum) {
for (var k = 0; k < 32; k++) {
if ($scope.days[k] == sparNum) {
dayIndex = k;
$ionicScrollDelegate.$getByHandle('scroll3').scrollTo(0, dayIndex * 44);
}
}
}
} function getDaysInOneMonth(year, month) {
month = parseInt(month, 10);
var d = new Date(year, month, 0);
return d.getDate();
} function _initScroll() {
if (!$scope.blockFlag) {
return;
}
$scope.changeFlag = 1; if ($scope.hasDate) {
_animation($scope.localDate.startYear, $scope.localDate.startMonth, $scope.localDate.startDay)
return
} if (_endDay) {
$scope.localDate = angular.extend($scope.localDate, {
startYear: '',
startMonth: '',
startDay: '',
endYear: '',
endMonth: '',
endDay: ''
});
_animation(_endYear,_endMonth);
return;
}
_animation(localYear,month) }
}
};
}
);
2.html代码
<div class="switch-btn-zx" ng-click="changeType()" ng-if="blockFlag">
{{hasDate?'按日选择':'按月选择'}}
</div>
<div class="switch-btn-zx" ng-click="goChoose()" ng-if="!blockFlag">
未筛选
</div>
<div id="month-picker" ng-if="blockFlag">
<div class="title" ng-if="!hasDate">{{localDate.endYear?localDate.endYear + '-' + localDate.endMonth:localDate.endDay + '-' + localDate.startMonth}}</div>
<div class="title1" ng-if="hasDate">
<span ng-click="setTime(1,localDate.startYear,localDate.startMonth,localDate.startDay)" ng-class="{'active': changeFlag == 1}">
{{localDate.startYear + '-' + localDate.startMonth + '-' + localDate.startDay}}
</span>
<span>至</span>
<span ng-click="setTime(2,localDate.endYear,localDate.endMonth,localDate.endDay)" ng-class="{'active': changeFlag == 2}">
<span ng-if="localDate.endYear" style="border-bottom:0" >{{localDate.endYear + '-' + localDate.endMonth + '-' + localDate.endDay}}</span>
<span ng-if="!localDate.endYear" style="color:#666;border-bottom:0">结束日期</span>
</span>
</div>
<div class="select-container">
<div class="hook">
<ion-scroll scrollbar-y="false" delegate-handle="scroll1" on-scroll="check1()">
<ul>
<li ng-repeat="year in years">{{year}}年</li>
</ul>
</ion-scroll>
<div class="picker-center-highlight"></div>
</div>
<div class="hook">
<ion-scroll scrollbar-y="false" delegate-handle="scroll2" on-scroll="check2()">
<ul>
<li ng-repeat="month in months">{{month}}月</li>
</ul>
</ion-scroll>
<div class="picker-center-highlight"></div>
</div>
<div class="hook" ng-if="hasDate">
<ion-scroll scrollbar-y="false" delegate-handle="scroll3" on-scroll="check3()">
<ul>
<li ng-repeat="day in days">{{day}}日</li>
</ul>
</ion-scroll>
<div class="picker-center-highlight"></div>
</div>
</div>
</div>
3.scss代码
#month-picker {
width: 5.4rem;
height: (378px/2);
border-radius: 0.1rem;
padding: 6px 6px 0px 6px;
background: rgba(72, 128, 237, 0.06);
position: relative;
.title {
height: 50px;
line-height: 50px;
border-bottom: 1px solid #4880ED;
color: #4880ED !important;
text-align: center;
font-size: 0.4rem !important;
}
.title1 {
height: 50px;
line-height: 50px;
color: #aaa !important;
text-align: center;
font-size: 0.4rem !important;
display: -webkit-flex;
display: flex;
span:first-child, span:last-child {
-webkit-flex: 1;
flex: 1;
}
span:nth-child(2) {
width: 0.5rem;
font-size: 0.28rem;
}
.active {
color:#4880ED !important;
font-weight: 500;
border-bottom: 1px solid #4880ED;
}
}
.select-container {
display: -webkit-flex;
display: flex;
position: relative;
.hook {
-webkit-flex: 1;
flex: 1;
height: (44*3px);
position: relative;
z-index: 33!important;
}
ion-scroll {
width: 100%;
height: 100%;
z-index: 1!important;
.scroll {
z-index: 1!important;
}
ul {
padding: 44px 0;
background: rgba(72, 128, 237, 0.12);
}
li {
height: 44px;
text-align: center;
line-height: 44px;
font-size: 0.4rem;
color: #000;
}
}
}
.picker-center-highlight {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 132px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin-top: 0;
pointer-events: none;
z-index: 3333;
&:after {
content: '';
width: 100%;
height: 44px;
position: absolute;
left: 0;
top: 50%;
margin-top: -22px;
z-index: 33333;
background-image: -webkit-linear-gradient(top, #d0d0d0, #d0d0d0, transparent, transparent), -webkit-linear-gradient(bottom, #d0d0d0, #d0d0d0, transparent, transparent);
background-image: linear-gradient(180deg, #d0d0d0, #d0d0d0, transparent, transparent), linear-gradient(0deg, #d0d0d0, #d0d0d0, transparent, transparent);
background-position: top, bottom;
background-size: 100% 1px;
background-repeat: no-repeat;
}
&:before {
height: 100%;
margin: 0 auto;
z-index: 333333;
background-image: -webkit-linear-gradient(top, hsla(0, 0%, 100%, .8), hsla(0, 0%, 100%, .4)), -webkit-linear-gradient(bottom, hsla(0, 0%, 100%, .8), hsla(0, 0%, 100%, .4));
background-image: linear-gradient(180deg, hsla(0, 0%, 100%, .8), hsla(0, 0%, 100%, 0.4)), linear-gradient(0deg, hsla(0, 0%, 100%, .8), hsla(0, 0%, 100%, .4));
background-position: top , bottom;
background-size: 100% 44px;
background-repeat: no-repeat;
position: absolute;
left: 0;
top: 0;
content: '';
width: 100%;
}
}
} .switch-btn-zx {
width: 1.74rem;
height: 0.48rem;
border-radius: 1rem;
background: rgba(72, 128, 237, 0.06);
border: 1px solid #4880ED;
font-size: 0.24rem;
color: #4880ED;
padding: 0.08rem 0 0.13rem 0.2rem;
background: url('../img/switch.png') no-repeat 1.23rem center;
background-size: 0.32rem 0.32rem;
margin-bottom: 0.2rem;
}
4.controller用法
$scope.localDate = {}; // 初始化时间选择插件对象
$scope.$broadcast('initPicker', true); // 需要手动初始化的时候调用一下广播。 在ios上scroll的层级会有问题,我在里面初始化了两次后显示正常。现在还找不到原因。
ionic的scroll指令在移动很短距离的时候不会触发scroll-complete事件。所以用了一个定时器在on-scroll事件上去计算值,然后再计算移动距离。
有想法的童鞋可以指导改进一下。