您所在的位置:小祥子 » 编程 » JavaScript » 正文

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

时间:2015-04-30 编辑:小菜38 来源:本站整理

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

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

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

贴代码~

CSS 部分:

 html, body, h1, h2, h3, p, dl, dd, ol, ul, th, td, form, fieldset, input, button, textarea, a {
   margin: 0;
   padding: 0; }
 
 html {
   -webkit-text-size-adjust: none;
   word-wrap: break-word;
   -webkit-touch-callout: none; }
 
 h1, h2, h3 {
   font-size: 100%; }
 
 ol, ul {
   list-style: none; }
 
 table {
   border-collapse: collapse;
   border-spacing: 0;
   empty-cells: show;
   font-size: inherit; }
 
 fieldset, img {
   border: 0; }
 
 cite, em, s, i, b {
   font-style: normal; }
 
 input, button, textarea, select {
   font-size: 100%; }
 
 body, input, button, textarea, select, option, optgroup {
   font-size: 14px; }
 
 a, input, textarea {
   text-decoration: none;
   outline: 0 none;
   resize: none;
   -webkit-tap-highlight-color: transparent; }
 
 li, img, label, input {
   vertical-align: middle; }
 
 img {
   display: block; }
 
 a {
   text-decoration: none; }
 
 body {
   font: 14px/1.2 "Microsoft Yahei","Hiragino Sans GB",arial,sans-serif; }
 
 .clearfix:after {
   display: block;
   content: "\20";
   height: 0;
   clear: both;
   overflow: hidden;
   visibility: hidden; }
 
 html, body {
   height: 100%;
   background-color: #f1f1f1; }
 
 /* sprite icon */
 .icon-lottery,
 .icon-phone,
 .icon-game,
 .icon-qq,
 .icon-hotel,
 .icon-plane,
 .icon-gas {
   display: inline-block;
   background: url(../img/base/sprite-icon.png) 0 0 no-repeat;
   height: 112px; }
 
 /* header */
 .header {
   position: fixed;
   top: 0;
   left: 0;
   width: 100%;
   height: 42px;
   line-height: 42px;
   background-color: #f16b50; }
 
 .header .title {
   font-size: 16px;
   color: #fff;
   text-align: center; }
 
 .header .icon-code-left {
   position: absolute;
   left: 0;
   top: 0;
   width: 34px;
   height: 42px;
   line-height: 42px;
   font-size: 16px;
   color: #fff;
   font-weight: bold;
   text-align: center; }
 
 .wrapper {
   padding-top: 42px; }
 
 /* btn */
 .btn {
   display: inline-block;
   background-color: #f16b50;
   text-align: center;
   color: #fff; }
 
 .btn-large {
   width: 100%;
   height: 40px;
   line-height: 40px; }
 
 /* home index */
 .icon-lottery {
   background-position: 0 0;
   width: 108px; }
 
 .icon-phone {
   background-position: -108px 0;
   width: 94px; }
 
 .icon-game {
   background-position: -204px 0;
   width: 108px; }
 
 .icon-qq {
   background-position: -314px 0;
   width: 99px; }
 
 .icon-hotel {
   background-position: -415px 0;
   width: 90px; }
 
 .icon-plane {
   background-position: -507px 0;
   width: 108px; }
 
 .icon-gas {
   background-position: -618px 0;
   width: 81px; }
 
 .recharge-list .r-l-item {
   float: left;
   width: 50%;
   line-height: 1;
   text-align: center; }
 
 .recharge-list a {
   display: block;
   padding: 58px 0; }
 
 .recharge-list .r-l-item.grey {
   background-color: #eee; }
 
 .recharge-list .r-l-describe {
   height: 22px;
   line-height: 22px;
   text-align: center;
   color: #333; }
 
 /* list.html */
 .w-list {
   xxpadding: 0 22px 0 12px; }
 
 .w-list .w-l-index {
   position: fixed;
   top: 50%;
   right: 0;
   margin-top: -196px;
   width: 22px;
   text-align: center; }
 
 .w-list .w-l-index a {
   color: #666; }
 
 .w-list .w-l-content dt {
   border-bottom: 1px solid #ccc;
   padding: 10px;
   line-height: 1.2;
   background-color: #f4f4f4;
   font-size: 16px;
   color: #f16b50; }
 
 .w-list .w-l-content dd {
   border-bottom: 1px solid #ccc;
   padding: 16px;
   line-height: 1.4; }
 
 .w-list .w-l-content dd a {
   font-size: 12px;
   color: #333; }
 
 /* recharge.html */
 .box-radius {
   margin: 14px 20px 0;
   border: 1px solid #ccc;
   border-radius: 8px;
   background-color: #FFF;
   overflow: hidden; }
 
 .input-group .label,
 .input-group .input-control {
   display: block;
   padding: 12px 8px; }
 
 .input-group .label {
   line-height: 22px; }
 
 .input-group .input-control {
   border: 0;
   line-height: 22px;
   width: 100%;
   box-sizing: border-box;
   background-color: transparent; }
 
 .input-group input.input-control {
   border: 1px solid #fff;
   border-top: 1px solid #ccc; }
 
 .input-group input.input-control:first-child {
   margin-top: -1px; }
 
 .input-group input.input-control.error {
   border-color: #f16b50;
   border-radius: 7px; }
 
 .recharge .btn-area {
   margin: 14px 20px 20px; }
 
 .recharge-list {
   border-top: 1px solid #ccc;
   height: 128px;
   overflow: hidden; }
 
 .recharge-list .r-l-left {
   position: relative;
   float: left;
   border-right: 1px solid #ccc;
   width: 50%;
   height: 100%;
   xxoverflow: auto; }
 
 .recharge-list .r-l-right {
   float: right;
   padding: 46px 14px 0;
   line-height: 1.5;
   font-weight: bold;
   width: 49%;
   box-sizing: border-box; }
 
 .recharge-list .r-l-left ul {
   margin: 0 12px;
   -webkit-transition: -webkit-transform 0s ease-out;
   -webkit-transform: translate3d(0, 0, 0); }
 
 .recharge-list .item {
   border-top: 1px solid #ccc;
   padding: 0 6px;
   height: 42px;
   line-height: 42px; }
 
 .recharge-list .item.current {
   font-weight: bold;
   font-size: 15px; }
 
 .recharge-list .item:first-child {
   border: 0; }
 
 .top-cover,
 .bottom-cover {
   position: absolute;
   left: 0;
   width: 100%;
   height: 22px;
   text-indent: -999em;
   background: #fff;
   opacity: 0.5; }
 
 .top-cover {
   top: 0; }
 
 .bottom-cover {
   bottom: 0; }
 
 .skin-color {
   font-weight: bold;
   color: #f16b50; }
 
 @media screen and (max-width: 320px) {
   .icon-lottery,
   .icon-phone,
   .icon-game,
   .icon-qq,
   .icon-hotel,
   .icon-plane,
   .icon-gas {
     height: 80px;
     background-size: 460px; }
 
   .icon-lottery {
     background-position: 0 0;
     width: 71px; }
 
   .icon-phone {
     background-position: -71px 0;
     width: 62px; }
 
   .icon-game {
     background-position: -133px 0;
     width: 73px; }
 
   .icon-qq {
     background-position: -206px 0;
     width: 66px; }
 
   .icon-hotel {
     background-position: -271px 0;
     width: 62px; }
 
   .icon-plane {
     background-position: -333px 0;
     width: 71px; }
 
   .icon-gas {
     background-position: -406px 0;
     width: 53px; } }
css 代码

HTML 结构部分:

 <!doctype html>
 <html>
     <head>
         <meta charset="utf-8"/>
         <meta name="viewport" content="width=device-width, initial-scale=1,target-densitydpi=medium-dpi, user-scalable=no">
         <meta name="format-detection" content="telephone=no" />
         <title>充值首页 -- 手机充值</title>
         <link rel="stylesheet" href="css/index.css" />
     </head>
     <body>
         
         <header class="header">
             <h2 class="title">手机充值</h2><span class="icon-code-left">〈</span>
         </header>
         
         <div class="wrapper recharge">
             <div class="box-radius input-group">
                 <label class="label">充值类型</label>
                 <input class="input-control" placeholder="请输入手机号码"/>
             </div>
             <div class="box-radius input-group">
                 <label class="label">充值面额</label>
                 <div class="recharge-list clearfix">
                     <div class="r-l-left">
                         <s class="top-cover">top cover</s>
                         <s class="bottom-cover">bottom cover</s>
                         <div id="sliderEl" style="-webkit-transform: translate3d(0, 0, 0);"></div>
                     </div>
                     <div class="r-l-right">
                         <span class="title">售价</span>
                         <p class="price">¥ <i id="showPriceEl"></i></p>
                     </div>
                 </div>
             </div>
             <div class="box-radius input-group">
                 <label class="label">应付金额:<span class="skin-color">¥<i id="priceEl"></i></span></label>
             </div>
             <div class="btn-area"><em class="btn btn-large">立刻充值</em></div>
         </div>
         <script type="text/javascript" src="JS/scroll-list.js"></script>
         <script>
         (function(){
 
             //调用
             var data = [{id:"bm_50",showPrice:50,price:49.750},
                         {id:"bm_30",showPrice:30,price:29.850},
                         {id:"bm_100",showPrice:100,price:99.500},
                         {id:"om_300",showPrice:300,price:298.500},
                         {id:"om_500",showPrice:500,price:497.500}],
                 el = document.getElementById('sliderEl');
             
             var slider = new Slider({
                 dataModule     : data,
                 sliderEl     : el,
                 current     : 1,
                 callBack     : function(data){
                     if (!data) { return; }
                     data.showPrice && (document.getElementById('showPriceEl').innerHTML = data.showPrice);
                     data.price && (document.getElementById('priceEl').innerHTML = data.price);
                 }
             });
             
         })();
         </script>
     </body>
 </html>
HTML 部分

Javascript 部分:

 var Slider;
 (function(){
 
     Slider = function(opt){
         this.el = opt.sliderEl;                //模板容器
         this.idx = opt.current;                //设定初始索引
         this.callBack = opt.callBack;
         
         this.dataIdx = [];                    //缓存索引数据
         this.dataModule = {};                //缓存数据对象
         this.setDataModule(opt.dataModule);
 
         //初始化
         this.init();
     };
     
     //数据处理
     Slider.prototype.setDataModule = function(data){
         if (!data) return;
         for (var i = 0, len = data.length; i < len; i++) {
             var d = data[i];
             if (!d) { continue; }
             this.dataIdx.push( d.id );
             this.dataModule[ d.id ] = d;
         }
     };
 
     Slider.prototype.init = function(){
         //渲染模板
         this.renderTpl();
 
         //设定滚动高度
         this.scaleH = this.el.getElementsByTagName('li')[0].clientHeight + 1; //1px border
         
         //初始总偏移量
         this.scrollY = 0;
         
         //绑定事件
         this.bindEvent();
 
     };
     
     //渲染模板
     Slider.prototype.renderTpl = function(){
         var data = this.dataIdx,
             el = this.el,
             dataArr = ['<ul>'];
         for (var i = 0, len = data.length; i < len; i++) {
             var id = data[i],
                 d = this.dataModule[id];
             if (!d) continue;
             dataArr.push( this.setTpl(d) );
         }
         dataArr.push('</ul>')
         el.innerHTML = dataArr.join('');
         
         //模板渲染完成后,设定初始选定项
         el.getElementsByTagName('li')[ this.idx ].className = 'item current';
         var cid = data[this.idx],
             cdata = this.dataModule[cid];
         this.callBack(cdata);
     };
     
     //普通list模板
     Slider.prototype.setTpl = function(data){
         return '<li class="item" data-val="'+ data.id +'">¥ '+ data.showPrice +'</li>';
     };
     
 
     //绑定事件
     Slider.prototype.bindEvent = function(){
         
         var self = this,
             el = this.el,
 
             //手指按下
             startHandler = function(event){
                 //记录手指按下的坐标
                 self.startY = event.touches[0].pageY;
                 //清除偏移量
                 self.offsetY = 0;
                 //事件对象
                 self.target = event.target;
 
             },
             //手指移动
             moveHandler = function(event){
                 event.preventDefault();
 
                 //计算手指的偏移量
                 self.offsetY = event.targetTouches[0].pageY - self.startY;
 
                 //当前偏移量 + 总偏移量
                 var scrollHeight = self.offsetY + self.scrollY;
                 
                 el.style.webkitTransform = 'translate3d(0, '+ scrollHeight +'px, 0)';
                 
             },
             //手指抬起
             endHandler = function(event){
                 event.preventDefault();
 
                 //记录滑动边界,用于判定滑动的类型
                 var boundary = self.scaleH / 2;
 
                 if (self.offsetY > boundary) {
                     self.setIndex('-1');
                 } else if (self.offsetY < 0 && self.offsetY < -boundary) {
                     self.setIndex('+1');
                 } else {
                     self.setIndex('0');
                 }
 
             };
 
             //绑定事件
             el.addEventListener('touchstart', startHandler);
             el.addEventListener('touchmove', moveHandler);
             el.addEventListener('touchend', endHandler);
     };
 
     //滑动
     Slider.prototype.setIndex = function(n){
         var el = this.el;
 
         //情景一:偏移量太小,偏移回原始位置即可
         if (n == '0'){
             el.style.webkitTransform = 'translate3d(0, '+ this.scrollY +'px, 0)';
             return;
         }
 
         //情景二:依照滚动的间距计算
         var liEl = el.getElementsByTagName('li'),
             liLen = liEl.length;
         //在改变 this.idx 之前要去掉 当前 idx 的 current 状态
         liEl[this.idx].className = 'item';
 
         var maxY = this.scaleH * -(liLen - 2),
             minY = this.scaleH,
             boundary = this.scaleH / 2,
             d = Math.abs( this.offsetY % this.scaleH ), //取模 -- 偏移量
             offIdx = Math.abs( this.offsetY / this.scaleH );        //取值 -- 偏移量
         //四舍五入取 idx
         if (d > boundary) {
             offIdx = Math.ceil(offIdx);
         } else {
             offIdx = Math.floor(offIdx);
         }
         this.idx = this.idx + (n * offIdx); //重置 idx 索引
         
         if (n == '+1'){
             scrollHeight = (-n * this.idx) * this.scaleH + (n * this.scaleH);
         } else {
             scrollHeight = (n * this.idx) * this.scaleH - (n * this.scaleH);
         }
         
         if (this.idx < 0) { 
             scrollHeight = minY;
             this.idx = 0;
         } else if (this.idx >= liLen) {
             scrollHeight = maxY;
             this.idx = liLen - 1;
         }
         
         this.scrollY = scrollHeight;
         
         var li = liEl[this.idx],
             cId = li.getAttribute('data-val'),
             currentItemData = this.dataModule[cId];
         li.className = 'item current';
         
         el.style.webkitTransform = 'translate3d(0, '+ scrollHeight +'px, 0)';
         
         this.callBack(currentItemData);
     };
     
 })();
关键词:选择 组件