手机端上下滑动选择项小组件

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

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

 

重点请看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 class="item" 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         //四舍五入取 idx

144         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 })();

 

你可能感兴趣的:(手机)