前端心得---仿IOS拾取器控件(转轮控件)

希望做一个类似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或者是一个空字符串,这里设成空字符串。

  接下来进行布局。由于部署在球面上的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事件。

前端心得---仿IOS拾取器控件(转轮控件)

时间: 2024-08-06 11:38:11

前端心得---仿IOS拾取器控件(转轮控件)的相关文章

IOS 拾取器控件

拾取器是个常用控件. 在使用拾取器之前需要引用两个协议   <UIPickerViewDataSource,UIPickerViewDelegate>       还需要连接  datesource & delegate   调用协议后,需要重写三个方法 -(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView     这个方法返回拾取器的 个数. -(NSString *)pickerView:(UIP

仿IOS 带字母索引的滑轮控件

效果大概就是这样,右边是字母索引效果 做开发的时候,经常碰到产品经理设计出来的界面是参考IOS控件设计出来的 ,比如上图效果  ios有个控件是UIPickerView  就是可以上下滑动 并有些3d效果,非常炫. 但是android并没有提供这样的原生控件支持,所以需要通过其他方式实现类似效果.上图就是我开发中用到的一个效果. 话不多说 ,直接上代码: Activity package com.example.picscrollview; import java.util.ArrayList;

Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框

转载请注明出处http://blog.csdn.net/xiaanming/article/details/11066685 今天给大家带来一个很实用的小控件ClearEditText,就是在Android系统的输入框右边加入一个小图标,点击小图标可以清除输入框里面的内容,IOS上面直接设置某个属性就可以实现这一功能,但是Android原生EditText不具备此功能,所以要想实现这一功能我们需要重写EditText,接下来就带大家来实现这一小小的功能 我们知道,我们可以为我们的输入框在上下左右

(转载) Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框

Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框 标签: Android清除功能EditText仿IOS的输入框 2013-09-04 17:33 70865人阅读 评论(57) 收藏 举报  分类: Android UI设计(7)  版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处http://blog.csdn.net/xiaanming/article/details/11066685 今天给大家带来一个很实用的小控件ClearEdit

IOS开发-UIDatePicker和UIPickerView(拾取器)

外观及作用                     UIDatePicker和事件相关,用来设置时间,选择时间等.UIPickerView则是自定义的,可以用作下拉列表等 运行结果 本示例主要简示了这些拾取器的用法,效果图如下所示(改成Iphone4大小了):          构建概要 1.新建基本视图或者基于TabView的工程,如果是基本的工程,需要额外操作转换为TabView,方法为:打开Main.storyboard,选中视图,然后在Xcode的菜单中Edit->Ebeded in->

iOS开发基础篇-手写控件

一.手写控件的步骤 1)使用相应的控件类创建控件对象: 2)设置该控件的各种属性: 3)添加空间到视图中: 4)如果是 UIButton 等控件,还需考虑控件的单击事件等: 二.添加 UIButton 单击事件  [topbtn addTarget:self action:@selector(move:) forControlEvents:UIControlEventTouchUpInside]; 1) addTarget:forControlEvents: 方法定义在 UIControl 类中

iOS开发UI篇—手写控件,frame,center和bounds属性

iOS开发UI基础—手写控件,frame,center和bounds属性 一.手写控件 1.手写控件的步骤 (1)使用相应的控件类创建控件对象 (2)设置该控件的各种属性 (3)添加控件到视图中 (4)如果是button等控件,还需考虑控件的单击事件等 (5)注意:View Contollor和view的关系 2.注意点 在OC开发中,Storyboard中的所有操作都可以通过代码实现,程序员一定要熟练掌握代码布局界面的能力! 设置控件监听方法的示例代码如下: [btn addTarget:se

一步一步学ios UITextView(多行文本框)控件的用法详解(五5.8)

本文转载至 http://wuchaorang.2008.blog.163.com/blog/static/48891852201232014813990/ 1.创建并初始化 创建UITextView的文件,并在.h文件中写入如下代码: [csharp] view plaincopy #import <UIKit/UIKit.h> @interface TextViewController : UIViewController <UITextViewDelegate> { UITe

IOS开发基础篇--手写控件,frame,center和bounds属性

iOS开发UI基础—手写控件,frame,center和bounds属性 一.手写控件 1.手写控件的步骤 (1)使用相应的控件类创建控件对象 (2)设置该控件的各种属性 (3)添加控件到视图中 (4)如果是button等控件,还需考虑控件的单击事件等 (5)注意:View Contollor和view的关系 2.注意点 在OC开发中,Storyboard中的所有操作都可以通过代码实现,程序员一定要熟练掌握代码布局界面的能力! 设置控件监听方法的示例代码如下: [btn addTarget:se