前端心得---仿IOS拾取器控制項(轉輪控制項)

來源:互聯網
上載者:User

標籤:style   blog   http   java   color   strong   

    希望做一個類似IOS拾取器的控制項,在IOS上該控制項的效果是這樣的:,我也把該效果稱之為為輪子效果。

 

  要實現這個效果,能夠用到的技術點非常簡單,無非是transform的translate3d和rotate,不過要想很好的實現,還要建立一個精確的數學模型,來解決如何【擺放】的問題。特別是這個效果不是靜態,需要滿足滑鼠滑動的時,這個輪子要轉起來,這就需要仔細思索了。當然,在最開始重點還是要搞清楚自變數是什麼、因變數是什麼、它們之間的關係是什麼以及該需求的一些性質。找到了好的性質,可以減輕工作量,並且讓代碼可以更加簡潔。

 

  做這個效果,首先想到的,就是用div表示每個小條目,然後想象成這些div是貼在一個圓上面,滾動這個圓。先用html把結構展示一下:

 1 <div class="border"> 2     <div class="item">0</div> 3     <div class="item">1</div> 4     <div class="item">2</div> 5     <div class="item">3</div> 6     <div class="item">4</div> 7     <div class="item">5</div> 8     <div class="item">6</div> 9     <div class="item">7</div>10     <div class="item">8</div>11     <div class="item">9</div>12     <div class="item">10</div>13     <div class="item">11</div>14     <div class="item">12</div>15     <div class="item">13</div>16     <div class="item">14</div>17     <div class="item">15</div>18     <div class="item">16</div>19     <div class="item">17</div>20     <div class="item">18</div>21 </div>

 

 

  接著把其中的css代碼也寫出來:

 1 <style> 2 * { 3     -webkit-user-select: none; 4 } 5  6 .item { 7     height: 30px; 8     line-height: 30px; 9     font-size: 15px;10     font-weight: bolder;11     color: #222;12     width: 400px;13     background: white;14     text-align: center;15     position: absolute;16     top: 50%;17     margin-top: -15px;18 }19 20 .border {21     overflow: hidden;22     cursor: pointer;23     position: relative;24     height: 240px;25     width: 400px;26     border: 2px solid black;27 }28 29 .hide {30     display: none;31 }32 </style>

 

  注意上面的border採取的是相對(relative)定位,裡面的條目(item)採用的是絕對位置,而且是垂直置中,這樣的話,就會有如下的效果:

                

  由於給item設定了背景色,所以只會看到最後一個item。接下來我們要做的工作是,把這19個item先擺成像是貼在圓上一樣。這需要先挖掘一下這個需求的性質,因為性質會成為我們的突破口。

 

  想要擺出這個效果,需要先進行分析。我們知道,由於每個item的高度相同,所以每兩個相鄰的item之間的旋轉角度之差相同,而這個角度之差可以通過公式2 * Math.asin( height / 2 / r )計算出來。另外,轉輪的旋轉角度和item的旋轉角度相同,那麼我們需要知道已經旋轉的角度,用這個角度以及角度之差我們可以知道任何一個item的旋轉角度,然後再根據這個角度計算出item擺放的位置。

 

  有了上述的分析,想要擺放出一個很漂亮的拾取器控制項樣式就不那麼難了。不過在此之前,要做一下簡單的準備。

  

  首先,需要一個設定css樣式的javascript函數,因為在擺放的過程中,要頻繁用到javascript來設定css的transform樣式,因此極有必要將該操作提取出來寫成為一個函數,不妨將其命名為css,這部分的代碼如下:

1 function css( el, style ) {2     loopObj( style, function ( name, value ) {3         el.style.setProperty( name, value, "");4     } )5 }

  代碼非常簡單,但是非常實用。其中setProperty方法的第三個參數可以為important或者是一個Null 字元串,這裡設成Null 字元串。

 

  接下來進行布局。由於部署在球面上的item具有對稱性,所以對19個item,從第10個開始布局,然後迴圈10次,從中間到兩邊依次對item進行布局。這部分代碼如下所示:

 1 var r = 90; 2 var height = 30; 3 var dAngle = 2 * Math.asin( height / 2 / r ); 4 var first = items.length / 2 << 0; 5  6 function setPosition( curAngle ) { 7     d.loop( first + 1, function ( i ) { 8         doSet( items[first + i], curAngle - i * dAngle ); 9         doSet( items[first - i], curAngle + i * dAngle );10     } );11 }

 

 

  其中doSet的代碼如下所示:

1 function doSet( el, angle ) {2     Math.abs( angle ) > Math.PI / 2 ? el.classList.add( "hide" ) : el.classList.remove( "hide" );3     d.css( el, {4         "-webkit-transform" : "translate3d(0," + (r * Math.sin( -angle )) + "px,0) rotateX(" + 180 * angle / Math.PI + "deg)"5     } );6 }

 

 

  添加初始化的javascript代碼:setPosition( 0 ),然後在瀏覽器中開啟後就能看到這樣的效果,可以看出布局成功了,正是我們想要的效果。

   

   接下來的工作中,要讓它轉動起來,由於上面考慮的非常充分,已經不必再引入新的變數,只要記錄滑鼠滑動的距離,得出相應的curAngle,然後傳給setPosition即可。相關代碼如下所示:

 1 var end = d.Events(); 2  3 d.dragY( border, border, { 4     moving : function () { 5         var moving = d.Events(); 6         moving.regist( function ( e ) { 7             setPosition( -e.dy / 50 ); 8         } ); 9         return moving;10     },11     end : end,12     setMove : function ( e ) {13         console.log( e.dy );14     }15 } );

 

   在瀏覽器中開啟,然後就可以看到已經可以轉動了。

  

  但是這個目前仍然美中不足,就是對旋轉的角度沒有記錄,導致第二次轉動時,還是從新開始,所以還需要改動一下:

 1 var alreadyS = 0; 2  3 d.dragY( border, border, { 4     moving : function () { 5         var moving = d.Events(); 6         moving.regist( function ( e ) { 7             console.log( alreadyS - e.dy ); 8             setPosition( (alreadyS - e.dy) / 50 ); 9         } );10         return moving;11     },12     end : function () {13         var end = d.Events();14         end.regist( function ( e ) {15             alreadyS = alreadyS - e.dy;16         } );17         return end;18     },19     setMove : function ( e ) {20     }21 } );

  這裡添加了一個全域變數alreadyS,記錄滑動的距離,這樣就不用每次滑動都要重新開始了。更新alreadyS的時機在每次滾動結束結束的時候,所以新添加了end事件。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.