你的位置:首页 > Java教程

[Java教程]手机端上下滑动选择项小组件


这是一个手机端的滑动选择小组件。

详细的需求介绍:话费充值,滑动选择充值面额,显示对应的应付金额即可。

 

重点请看Javascript部分的代码,请大神指点。跪谢! 

 

贴代码~

CSS 部分:

 1 html, body, h1, h2, h3, p, dl, dd, ol, ul, th, td, form, fieldset, input, button, textarea, a { 2  margin: 0; 3  padding: 0; } 4  5 html { 6  -webkit-text-size-adjust: none; 7  word-wrap: break-word; 8  -webkit-touch-callout: none; } 9  10 h1, h2, h3 { 11  font-size: 100%; } 12  13 ol, ul { 14  list-style: none; } 15  16 table { 17  border-collapse: collapse; 18  border-spacing: 0; 19  empty-cells: show; 20  font-size: inherit; } 21  22 fieldset, img { 23  border: 0; } 24  25 cite, em, s, i, b { 26  font-style: normal; } 27  28 input, button, textarea, select { 29  font-size: 100%; } 30  31 body, input, button, textarea, select, option, optgroup { 32  font-size: 14px; } 33  34 a, input, textarea { 35  text-decoration: none; 36  outline: 0 none; 37  resize: none; 38  -webkit-tap-highlight-color: transparent; } 39  40 li, img, label, input { 41  vertical-align: middle; } 42  43 img { 44  display: block; } 45  46 a { 47  text-decoration: none; } 48  49 body { 50  font: 14px/1.2 "Microsoft Yahei","Hiragino Sans GB",arial,sans-serif; } 51  52 .clearfix:after { 53  display: block; 54  content: "\20"; 55  height: 0; 56  clear: both; 57  overflow: hidden; 58  visibility: hidden; } 59  60 html, body { 61  height: 100%; 62  background-color: #f1f1f1; } 63  64 /* sprite icon */ 65 .icon-lottery, 66 .icon-phone, 67 .icon-game, 68 .icon-qq, 69 .icon-hotel, 70 .icon-plane, 71 .icon-gas { 72  display: inline-block; 73  background: url(../img/base/sprite-icon.png) 0 0 no-repeat; 74  height: 112px; } 75  76 /* header */ 77 .header { 78  position: fixed; 79  top: 0; 80  left: 0; 81  width: 100%; 82  height: 42px; 83  line-height: 42px; 84  background-color: #f16b50; } 85  86 .header .title { 87  font-size: 16px; 88  color: #fff; 89  text-align: center; } 90  91 .header .icon-code-left { 92  position: absolute; 93  left: 0; 94  top: 0; 95  width: 34px; 96  height: 42px; 97  line-height: 42px; 98  font-size: 16px; 99  color: #fff;100  font-weight: bold;101  text-align: center; }102 103 .wrapper {104  padding-top: 42px; }105 106 /* btn */107 .btn {108  display: inline-block;109  background-color: #f16b50;110  text-align: center;111  color: #fff; }112 113 .btn-large {114  width: 100%;115  height: 40px;116  line-height: 40px; }117 118 /* home index */119 .icon-lottery {120  background-position: 0 0;121  width: 108px; }122 123 .icon-phone {124  background-position: -108px 0;125  width: 94px; }126 127 .icon-game {128  background-position: -204px 0;129  width: 108px; }130 131 .icon-qq {132  background-position: -314px 0;133  width: 99px; }134 135 .icon-hotel {136  background-position: -415px 0;137  width: 90px; }138 139 .icon-plane {140  background-position: -507px 0;141  width: 108px; }142 143 .icon-gas {144  background-position: -618px 0;145  width: 81px; }146 147 .recharge-list .r-l-item {148  float: left;149  width: 50%;150  line-height: 1;151  text-align: center; }152 153 .recharge-list a {154  display: block;155  padding: 58px 0; }156 157 .recharge-list .r-l-item.grey {158  background-color: #eee; }159 160 .recharge-list .r-l-describe {161  height: 22px;162  line-height: 22px;163  text-align: center;164  color: #333; }165 166 /* list.html */167 .w-list {168  xxpadding: 0 22px 0 12px; }169 170 .w-list .w-l-index {171  position: fixed;172  top: 50%;173  right: 0;174  margin-top: -196px;175  width: 22px;176  text-align: center; }177 178 .w-list .w-l-index a {179  color: #666; }180 181 .w-list .w-l-content dt {182  border-bottom: 1px solid #ccc;183  padding: 10px;184  line-height: 1.2;185  background-color: #f4f4f4;186  font-size: 16px;187  color: #f16b50; }188 189 .w-list .w-l-content dd {190  border-bottom: 1px solid #ccc;191  padding: 16px;192  line-height: 1.4; }193 194 .w-list .w-l-content dd a {195  font-size: 12px;196  color: #333; }197 198 /* recharge.html */199 .box-radius {200  margin: 14px 20px 0;201  border: 1px solid #ccc;202  border-radius: 8px;203  background-color: #FFF;204  overflow: hidden; }205 206 .input-group .label,207 .input-group .input-control {208  display: block;209  padding: 12px 8px; }210 211 .input-group .label {212  line-height: 22px; }213 214 .input-group .input-control {215  border: 0;216  line-height: 22px;217  width: 100%;218  box-sizing: border-box;219  background-color: transparent; }220 221 .input-group input.input-control {222  border: 1px solid #fff;223  border-top: 1px solid #ccc; }224 225 .input-group input.input-control:first-child {226  margin-top: -1px; }227 228 .input-group input.input-control.error {229  border-color: #f16b50;230  border-radius: 7px; }231 232 .recharge .btn-area {233  margin: 14px 20px 20px; }234 235 .recharge-list {236  border-top: 1px solid #ccc;237  height: 128px;238  overflow: hidden; }239 240 .recharge-list .r-l-left {241  position: relative;242  float: left;243  border-right: 1px solid #ccc;244  width: 50%;245  height: 100%;246  xxoverflow: auto; }247 248 .recharge-list .r-l-right {249  float: right;250  padding: 46px 14px 0;251  line-height: 1.5;252  font-weight: bold;253  width: 49%;254  box-sizing: border-box; }255 256 .recharge-list .r-l-left ul {257  margin: 0 12px;258  -webkit-transition: -webkit-transform 0s ease-out;259  -webkit-transform: translate3d(0, 0, 0); }260 261 .recharge-list .item {262  border-top: 1px solid #ccc;263  padding: 0 6px;264  height: 42px;265  line-height: 42px; }266 267 .recharge-list .item.current {268  font-weight: bold;269  font-size: 15px; }270 271 .recharge-list .item:first-child {272  border: 0; }273 274 .top-cover,275 .bottom-cover {276  position: absolute;277  left: 0;278  width: 100%;279  height: 22px;280  text-indent: -999em;281  background: #fff;282  opacity: 0.5; }283 284 .top-cover {285  top: 0; }286 287 .bottom-cover {288  bottom: 0; }289 290 .skin-color {291  font-weight: bold;292  color: #f16b50; }293 294 @media screen and (max-width: 320px) {295  .icon-lottery,296  .icon-phone,297  .icon-game,298  .icon-qq,299  .icon-hotel,300  .icon-plane,301  .icon-gas {302   height: 80px;303   background-size: 460px; }304 305  .icon-lottery {306   background-position: 0 0;307   width: 71px; }308 309  .icon-phone {310   background-position: -71px 0;311   width: 62px; }312 313  .icon-game {314   background-position: -133px 0;315   width: 73px; }316 317  .icon-qq {318   background-position: -206px 0;319   width: 66px; }320 321  .icon-hotel {322   background-position: -271px 0;323   width: 62px; }324 325  .icon-plane {326   background-position: -333px 0;327   width: 71px; }328 329  .icon-gas {330   background-position: -406px 0;331   width: 53px; } }

css 代码

 

HTML 结构部分:

 1 <!doctype html> 2 <html> 3   <head> 4     <meta charset="utf-8"/> 5     <meta name="viewport" content="width=device-width, initial-scale=1,target-densitydpi=medium-dpi, user-scalable=no"> 6     <meta name="format-detection" content="telephone=no" /> 7     <title>充值首页 -- 手机充值</title> 8     <link rel="stylesheet" href="css/index.css" /> 9   </head>10   <body>11     12     <header class="header">13       <h2 class="title">手机充值</h2><span class="icon-code-left">〈</span>14     </header>15     16     <div class="wrapper recharge">17       <div class="box-radius input-group">18         <label class="label">充值类型</label>19         <input class="input-control" placeholder="请输入手机号码"/>20       </div>21       <div class="box-radius input-group">22         <label class="label">充值面额</label>23         <div class="recharge-list clearfix">24           <div class="r-l-left">25             <s class="top-cover">top cover</s>26             <s class="bottom-cover">bottom cover</s>27             <div id="sliderEl" style="-webkit-transform: translate3d(0, 0, 0);"></div>28           </div>29           <div class="r-l-right">30             <span class="title">售价</span>31             <p class="price">¥ <i id="showPriceEl"></i></p>32           </div>33         </div>34       </div>35       <div class="box-radius input-group">36         <label class="label">应付金额:<span class="skin-color">¥<i id="priceEl"></i></span></label>37       </div>38       <div class="btn-area"><em class="btn btn-large">立刻充值</em></div>39     </div>40     <script type="text/javascript" src="js/scroll-list.js"></script>41     <script>42     (function(){43 44       //调用45       var data = [{id:"bm_50",showPrice:50,price:49.750},46             {id:"bm_30",showPrice:30,price:29.850},47             {id:"bm_100",showPrice:100,price:99.500},48             {id:"om_300",showPrice:300,price:298.500},49             {id:"om_500",showPrice:500,price:497.500}],50         el = document.getElementById('sliderEl');51       52       var slider = new Slider({53         dataModule   : data,54         sliderEl   : el,55         current   : 1,56         callBack   : function(data){57           if (!data) { return; }58           data.showPrice && (document.getElementById('showPriceEl').innerHTML = data.showPrice);59           data.price && (document.getElementById('priceEl').innerHTML = data.price);60         }61       });62       63     })();64     </script>65   </body>66 </html>

HTML 部分

 

Javascript 部分:

 1 var Slider; 2 (function(){ 3  4   Slider = function(opt){ 5     this.el = opt.sliderEl;        //模板容器 6     this.idx = opt.current;        //设定初始索引 7     this.callBack = opt.callBack; 8      9     this.dataIdx = [];          //缓存索引数据 10     this.dataModule = {};        //缓存数据对象 11     this.setDataModule(opt.dataModule); 12  13     //初始化 14     this.init(); 15   }; 16    17   //数据处理 18   Slider.prototype.setDataModule = function(data){ 19     if (!data) return; 20     for (var i = 0, len = data.length; i < len; i++) { 21       var d = data[i]; 22       if (!d) { continue; } 23       this.dataIdx.push( d.id ); 24       this.dataModule[ d.id ] = d; 25     } 26   }; 27  28   Slider.prototype.init = function(){ 29     //渲染模板 30     this.renderTpl(); 31  32     //设定滚动高度 33     this.scaleH = this.el.getElementsByTagName('li')[0].clientHeight + 1; //1px border 34      35     //初始总偏移量 36     this.scrollY = 0; 37      38     //绑定事件 39     this.bindEvent(); 40  41   }; 42    43   //渲染模板 44   Slider.prototype.renderTpl = function(){ 45     var data = this.dataIdx, 46       el = this.el, 47       dataArr = ['<ul>']; 48     for (var i = 0, len = data.length; i < len; i++) { 49       var id = data[i], 50         d = this.dataModule[id]; 51       if (!d) continue; 52       dataArr.push( this.setTpl(d) ); 53     } 54     dataArr.push('</ul>') 55     el.innerHTML = dataArr.join(''); 56      57     //模板渲染完成后,设定初始选定项 58     el.getElementsByTagName('li')[ this.idx ].className = 'item current'; 59     var cid = data[this.idx], 60       cdata = this.dataModule[cid]; 61     this.callBack(cdata); 62   }; 63    64   //普通list模板 65   Slider.prototype.setTpl = function(data){ 66     return '<li data-val="'+ data.id +'">¥&nbsp;'+ data.showPrice +'</li>'; 67   }; 68    69  70   //绑定事件 71   Slider.prototype.bindEvent = function(){ 72      73     var self = this, 74       el = this.el, 75  76       //手指按下 77       startHandler = function(event){ 78         //记录手指按下的坐标 79         self.startY = event.touches[0].pageY; 80         //清除偏移量 81         self.offsetY = 0; 82         //事件对象 83         self.target = event.target; 84  85       }, 86       //手指移动 87       moveHandler = function(event){ 88         event.preventDefault(); 89  90         //计算手指的偏移量 91         self.offsetY = event.targetTouches[0].pageY - self.startY; 92  93         //当前偏移量 + 总偏移量 94         var scrollHeight = self.offsetY + self.scrollY; 95          96         el.style.webkitTransform = 'translate3d(0, '+ scrollHeight +'px, 0)'; 97          98       }, 99       //手指抬起100       endHandler = function(event){101         event.preventDefault();102 103         //记录滑动边界,用于判定滑动的类型104         var boundary = self.scaleH / 2;105 106         if (self.offsetY > boundary) {107           self.setIndex('-1');108         } else if (self.offsetY < 0 && self.offsetY < -boundary) {109           self.setIndex('+1');110         } else {111           self.setIndex('0');112         }113 114       };115 116       //绑定事件117       el.addEventListener('touchstart', startHandler);118       el.addEventListener('touchmove', moveHandler);119       el.addEventListener('touchend', endHandler);120   };121 122   //滑动123   Slider.prototype.setIndex = function(n){124     var el = this.el;125 126     //情景一:偏移量太小,偏移回原始位置即可127     if (n == '0'){128       el.style.webkitTransform = 'translate3d(0, '+ this.scrollY +'px, 0)';129       return;130     }131 132     //情景二:依照滚动的间距计算133     var liEl = el.getElementsByTagName('li'),134       liLen = liEl.length;135     //在改变 this.idx 之前要去掉 当前 idx 的 current 状态136     liEl[this.idx].className = 'item';137 138     var maxY = this.scaleH * -(liLen - 2),139       minY = this.scaleH,140       boundary = this.scaleH / 2,141       d = Math.abs( this.offsetY % this.scaleH ), //取模 -- 偏移量142       offIdx = Math.abs( this.offsetY / this.scaleH );    //取值 -- 偏移量143     //四舍五入取 idx144     if (d > boundary) {145       offIdx = Math.ceil(offIdx);146     } else {147       offIdx = Math.floor(offIdx);148     }149     this.idx = this.idx + (n * offIdx); //重置 idx 索引150     151     if (n == '+1'){152       scrollHeight = (-n * this.idx) * this.scaleH + (n * this.scaleH);153     } else {154       scrollHeight = (n * this.idx) * this.scaleH - (n * this.scaleH);155     }156     157     if (this.idx < 0) { 158       scrollHeight = minY;159       this.idx = 0;160     } else if (this.idx >= liLen) {161       scrollHeight = maxY;162       this.idx = liLen - 1;163     }164     165     this.scrollY = scrollHeight;166     167     var li = liEl[this.idx],168       cId = li.getAttribute('data-val'),169       currentItemData = this.dataModule[cId];170     li.className = 'item current';171     172     el.style.webkitTransform = 'translate3d(0, '+ scrollHeight +'px, 0)';173     174     this.callBack(currentItemData);175   };176   177 })();