这是一个手机端的滑动选择小组件。
详细的需求介绍:话费充值,滑动选择充值面额,显示对应的应付金额即可。
重点请看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='/images/loading.gif' data-original="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 +'">¥ '+ 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 })();
原标题:手机端上下滑动选择项小组件
关键词: