上圖:
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事件上去計算值,然后再計算移動距離。
有想法的童鞋可以指導改進一下。