【iScroll源码学习04】分离IScroll宗旨彩民之家论坛

2019-10-12 20:10 来源:未知

二、原理

  为何把那做为单独的一环来谈谈吗?因为前边的代码已经能够一气呵成基本的行事了,何况出现的主题素材涉及也并非老大大。但是总会不爽,因为它就不那么完美,所以,Fix It!

momentum

那几个指标中最难的叁个BUG,也很入眼,他会基于我们的拖动重返运动的长度与耗费时间,那几个是依赖物理公式计算而出的,拾分可相信,哥是没看懂用怎么样公式的

 

  最后,正是编写滚动委托调用的函数了,分别有两个函数,在函数内以100ms为一循环,不停地拓宽滚动,当滚动到竣事只怕滚动量已经为0时跳出循环,退出函数奉行。

体制包容

于是我们开端吧,首先,因为各样浏览器难题,大家须要做CSS3动画片的相称

 1 var _elementStyle = document.createElement('div').style;
 2 //获得CSS3前缀
 3 var _vendor = (function () {
 4   var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'];
 5   var transform;
 6   var i = 0;
 7   var l = vendors.length;
 8 
 9   for (; i < l; i  ) {
10     transform = vendors[i]   'ransform';
11     if (transform in _elementStyle) return vendors[i].substr(0, vendors[i].length - 1);
12   }
13   return false;
14 })();

这句代码会回到须要做协作的CSS属性的前缀,然后提供二个艺术非常的干这一个事情:

1 //获取样式(CSS3兼容)
2 function _prefixStyle(style) {
3   if (_vendor === false) return false;
4   if (_vendor === '') return style;
5   return _vendor   style.charAt(0).toUpperCase   style.substr(1);
6 }

三、源码

彩民之家论坛9066777 1彩民之家论坛9066777 2滚动委托

_elementStyle

用于末端检查实验CSS3 宽容属性

  尽管功能非常粗大略,然则互连网的有的素材涉及的代码量特别可观,并且功用亦非极美貌,滚动的时候未有三个顺滑感。笔者那边提供的源码一共120多行,就能够兑现上航海用教室的效率。

  照旧把这一次写的音讯框做成客商控件的款型,首先,前台轻松的XAML:

hasTouch

是不是协理touch事件

彩民之家论坛9066777 3

  三、改良一些主题材料

resetPosition

 1 resetPosition: function (time) {
 2   var x = this.x,
 3 y = this.y;
 4 
 5   time = time || 0;
 6 
 7   if (this.y > 0) {
 8     y = 0;
 9   } else if (this.y < this.maxScrollY) {
10     y = this.maxScrollY;
11   }
12 
13   if (y == this.y) {
14     return false;
15   }
16 
17   this.scrollTo(x, y, time, this.options.bounceEasing);
18 
19   return true;
20 },

在refresh时候会接触(因为可能引致scroller超过边界),在touchend时候超过边界也会选用该方法,那一年重新载入参数边界会有动画(600ms)

动画甘休假设检验到超越边界也会进行

一、先看看效果

  当然绝不遗忘,把“_ScrollYAction = ScrollYMethod;”,“_ScrollXAction

ScrollXMethod;”这两条委托最早化语句放到PART_ContentHost_Initialized事件管理函数中去,不然就白写了。

  至此,难点2也修改达成。

  主题素材3:自动滚动到底层

  实际上那不成问题,而是二个改良,因为日常的滚动条都未有这么些效果。在实用中,假使新闻是不停地填写到消息框中,理想中应该是当拖动滚动条时,不会活动把滚动条更新到近来的一条信息,而是锁定到拖动的岗位(因为作者想看的是拖动到的新闻)。其他,假若想实时看新音信,就要求活动滚动到最终面部分。

  解决方法:

  当滚动条拖动到最底部时,就开启自动滚动,每来一条新新闻都滚动三回到最底部。假如滚动条不在最头部就毫无自动滚动。完成方式便是为TextBox增加TextChanged="TextBox_TextChanged"事件,以咬定是不是须要滚动:

1         private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
2         {
3             if (this.Text != "" && ScrollViewer != null)
4             {
5                 // 如果已经拖到最底端,则固定住
6                 if (ScrollViewer.ScrollableHeight == ScrollViewer.VerticalOffset)
7                     ScrollViewer.ScrollToBottom();
8             }
9         }

  终于码完字了,多想只贴代码啊。放个图,大家看看吧:

彩民之家论坛9066777 4

  请无视上边的丰盛深褐横条,那是自己别的一个前后相继中的GridSplitter。那一个自定义控件除了支持Text博克斯的持有属性外,还足以转移配色(使用公开的质量),别的还应该有一点点击清空、关闭按键的操作达成都轻松,不贴了,感兴趣的下载源代码看看吧。

  源代码:ScrollTest.rar

  转发请证明原址:http://www.cnblogs.com/lekko/archive/2013/02/27/2935022.html 

关系图

彩民之家论坛9066777 5

彩民之家论坛9066777 6

  首先,为ScrollViewer添加Initialized="PART_ContentHost_Initialized"事件,后台扩张新的属性ScrollViewer以便使用:

scrollTo

该方法相比首要,其实是由她调用_translate改动scroller具体地点,在那之中可以流传一些年华以致动画曲线的参数实行动画
本条时候如若touchstart触屏了话便会甘休动画,实现格局是_transitionTime()

 

  然后,本身完毕中轮滚动方法,为ScrollViewer增加MouseWheel="PART_ContentHost_MouseWheel"事件,加多后台响应代码:

destroy

销毁注册的DOM事件

  因为周边的惯性滚动以垂直方向居多,所以笔者未曾写水平方向的逻辑,但也很轻便扩张,有意思味的博友能够下载源代码自个儿切磋。

  寒假过完,在家真心什么都做不了,或然岁数已经十分大了,再想之前那样能一心坐下来已经不行了。回来第一件事就是改了类别的二个bug,方今又新扩充了一个新的机能,为顺序增加了一个音信栏。消息栏有相当多花样,供给是几个不要求历史记录,能够用鼠标选中音讯内容的新闻栏。小编第一想到的便是TextBox,笔者个人比较欣赏美貌的,有一点情感障碍,所以必需把TextBox中的ScrollViewer给改写了,好呢,起头。

骨干天性

  调控ScrollViewer的垂直滚动可以行使 ScrollViewer.ScrollToVerticalOffset ,横向也一律。为啥不能够用 VerticalOffset ?因为 VerticalOffset 在注册的时候就印证了是只读的:

 1         /// <summary>
 2         /// 滚动框背景
 3         /// </summary>
 4         public Brush ScrollViewerBackground
 5         {
 6             get { return (Brush)GetValue(ScrollViewerBackgroundProperty); }
 7             set { SetValue(ScrollViewerBackgroundProperty, value); }
 8         }
 9         public static readonly DependencyProperty ScrollViewerBackgroundProperty =
10             DependencyProperty.Register("ScrollViewerBackground", typeof(Brush), typeof(MessageTextBox), new PropertyMetadata(Brushes.LightBlue));
11 
12         /// <summary>
13         /// 滚动条前景
14         /// </summary>
15         public Brush ScrollBarForeground
16         {
17             get { return (Brush)GetValue(ScrollBarForegroundProperty); }
18             set { SetValue(ScrollBarForegroundProperty, value); }
19         }
20         public static readonly DependencyProperty ScrollBarForegroundProperty =
21             DependencyProperty.Register("ScrollBarForeground", typeof(Brush), typeof(MessageTextBox), new PropertyMetadata(Brushes.RoyalBlue));
22 
23         /// <summary>
24         /// 滚动条背景
25         /// </summary>
26         public Brush ScrollBarBackground
27         {
28             get { return (Brush)GetValue(ScrollBarBackgroundProperty); }
29             set { SetValue(ScrollBarBackgroundProperty, value); }
30         }
31         public static readonly DependencyProperty ScrollBarBackgroundProperty =
32             DependencyProperty.Register("ScrollBarBackground", typeof(Brush), typeof(MessageTextBox), new PropertyMetadata(Brushes.WhiteSmoke));

scroller

小编们实在滚动的因素,大家拖动的就是他

PS:这里供给必需传入那三个DOM结构,不然就是错

1 protected override void OnMouseWheel(MouseWheelEventArgs e)
2 {
3     if (!IsEnableInertia)
4     {
5         base.OnMouseWheel(e);
6         return;
7     }
8     e.Handled = true;
9 }    
 1     /// <summary>
 2         /// 消息体滚动框
 3         /// </summary>
 4         public ScrollViewer ScrollViewer { get; set; }
 5     
 6     // 初始化滚动条
 7         private void PART_ContentHost_Initialized(object sender, EventArgs e)
 8         {
 9             this.ScrollViewer = sender as ScrollViewer;
10         }

_resize

当我们起先化时候会图谋wrapper与scroller的尺码,resize时候也会施行,这里不予关切

 

  现在,滚动量已经能创新了,但滚动触发条件还必要考虑。首先,横向和竖向滚动相对于前台分界面确定是异步进行的;其次,已经在滚动时要实时依照滚动量来支配滚动速度;还会有,滚动终止条件应该是滚动量为0可能已经滚动到了尽头。好了,目的综上可得,须要增加四个委托来分别处理横向、竖向滚动,还供给四个异步操作景况来代表滚动是或不是终止,那么,代码扩大为:

wrapper

着力外壳,这些dom的style属性常常是 position: absolute; overflow: hidden;是我们此中滚动条的外壳

  好了,接下去就是怎么在滚轮响应措施中完毕惯性运动了,相当于一种减速运动。想到此时,熟识动画的博友非常的慢就精通要用WPF的卡通来促成了,暗中认可的动画都以二遍线性的,要有惯性效用就得用缓动函数,WPF的缓动函数有许多,而 CubicEase 特别切合用来做惯性,它的陈诉图如下:

  然后,分别自定义ScrollBar的样式。以竖向滚动条为例,自定义ControlTemplate,使用Grid作为容器,把滚动条分为三行,第一行事升高按钮、第二行事滚动条、第三表现向下按钮。笔者那边由于美观思考,把四个开关全省略了(实际上大家相当少使用开关来上下滚动,大多数时候用的鼠标中轮和拖动滑块)。

动画数据

 1 me.momentum = function (current, start, time, lowerMargin, wrapperSize) {
 2       var distance = current - start,
 3         speed = Math.abs(distance) / time,
 4         destination,
 5         duration,
 6         deceleration = 0.0006;
 7 
 8       destination = current   (speed * speed) / (2 * deceleration) * (distance < 0 ? -1 : 1);
 9       duration = speed / deceleration;
10 
11       if (destination < lowerMargin) {
12         destination = wrapperSize ? lowerMargin - (wrapperSize / 2.5 * (speed / 8)) : lowerMargin;
13         distance = Math.abs(destination - current);
14         duration = distance / speed;
15       } else if (destination > 0) {
16         destination = wrapperSize ? wrapperSize / 2.5 * (speed / 8) : 0;
17         distance = Math.abs(current)   destination;
18         duration = distance / speed;
19       }
20 
21       return {
22         destination: Math.round(destination),
23         duration: duration
24       };
25     };

以此办法越发主要,是iScroll动画平滑的第一次全国代表大会功臣,那个点子内部用到了物理一个图谋速度的公式,作者没脸的忘了是怎样了,这里一贯不予关注了,解释下参数就能够

current:当前鼠标位置
start:touchStart时候记录的Y(可能是X)的开始位置,但是在touchmove时候可能被重写
time: touchstart到手指离开时候经历的时间,同样可能被touchmove重写
lowerMargin:y可移动的最大距离,这个一般为计算得出 this.wrapperHeight - this.scrollerHeight
wrapperSize:如果有边界距离的话就是可拖动,不然碰到0的时候便停止

其一动画方法,大家后边用到还亟需加以下

  本文所切磋的控件源码已经在github开源:

  1 <ScrollViewer x:Name="PART_ContentHost">
  2     <ScrollViewer.Template>
  3         <ControlTemplate TargetType="{x:Type ScrollViewer}">
  4             <Grid Background="{Binding Path=ScrollViewerBackground,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TextBox}}}">
  5                 <Grid.ColumnDefinitions>
  6                     <ColumnDefinition />
  7                     <ColumnDefinition Width="Auto"/>
  8                 </Grid.ColumnDefinitions>
  9                 <Grid.RowDefinitions>
 10                     <RowDefinition/>
 11                     <RowDefinition Height="Auto"/>
 12                 </Grid.RowDefinitions>
 13                 <ScrollContentPresenter Margin="5,5,0,5" />
 14                 <ScrollBar Name="PART_VerticalScrollBar" Grid.Column="1" Value="{TemplateBinding VerticalOffset}" Maximum="{TemplateBinding ScrollableHeight}" ViewportSize="{TemplateBinding ViewportHeight}" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}">
 15                     <ScrollBar.Template>
 16                         <ControlTemplate TargetType="{x:Type ScrollBar}">
 17                             <!-- 竖向滚动条宽度 -->
 18                             <Grid Width="10">
 19                                 <Grid.RowDefinitions>
 20                                     <RowDefinition Height="1" />
 21                                     <RowDefinition />
 22                                     <RowDefinition Height="1" />
 23                                 </Grid.RowDefinitions>
 24                                 <Track x:Name="PART_Track" Grid.Row="1" IsDirectionReversed="True">
 25                                     <Track.DecreaseRepeatButton>
 26                                         <!--上空白-->
 27                                         <RepeatButton Command="ScrollBar.PageUpCommand" Opacity="0.5">
 28                                             <RepeatButton.Template>
 29                                                 <ControlTemplate>
 30                                                     <Border Background="{Binding Path=ScrollBarBackground,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TextBox}}}" CornerRadius="5,5,0,0" />
 31                                                 </ControlTemplate>
 32                                             </RepeatButton.Template>
 33                                         </RepeatButton>
 34                                     </Track.DecreaseRepeatButton>
 35                                     <Track.Thumb>
 36                                         <!--滑块-->
 37                                         <Thumb>
 38                                             <Thumb.Template>
 39                                                 <ControlTemplate>
 40                                                     <Border Background="{Binding Path=ScrollBarForeground,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TextBox}}}" CornerRadius="5" />
 41                                                 </ControlTemplate>
 42                                             </Thumb.Template>
 43                                         </Thumb>
 44                                     </Track.Thumb>
 45                                     <Track.IncreaseRepeatButton>
 46                                         <!--下空白-->
 47                                         <RepeatButton Command="ScrollBar.PageDownCommand" Opacity="0.5">
 48                                             <RepeatButton.Template>
 49                                                 <ControlTemplate>
 50                                                     <Border Background="{Binding Path=ScrollBarBackground,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TextBox}}}" CornerRadius="0,0,5,5" />
 51                                                 </ControlTemplate>
 52                                             </RepeatButton.Template>
 53                                         </RepeatButton>
 54                                     </Track.IncreaseRepeatButton>
 55                                 </Track>
 56                             </Grid>
 57                         </ControlTemplate>
 58                     </ScrollBar.Template>
 59                 </ScrollBar>
 60                 <ScrollBar Name="PART_HorizontalScrollBar" Orientation="Horizontal" Grid.Row="1" Value="{TemplateBinding HorizontalOffset}" Maximum="{TemplateBinding ScrollableWidth}" ViewportSize="{TemplateBinding ViewportWidth}" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}">
 61                     <ScrollBar.Template>
 62                         <ControlTemplate TargetType="{x:Type ScrollBar}">
 63                             <!-- 横向滚动条高度 -->
 64                             <Grid Height="10">
 65                                 <Grid.ColumnDefinitions>
 66                                     <ColumnDefinition Width="1" />
 67                                     <ColumnDefinition />
 68                                     <ColumnDefinition Width="1" />
 69                                 </Grid.ColumnDefinitions>
 70                                 <Track x:Name="PART_Track" Grid.Column="1" IsDirectionReversed="False">
 71                                     <Track.DecreaseRepeatButton>
 72                                         <!--左空白-->
 73                                         <RepeatButton Command="ScrollBar.PageLeftCommand" Opacity="0.5">
 74                                             <RepeatButton.Template>
 75                                                 <ControlTemplate>
 76                                                     <Border Background="{Binding Path=ScrollBarBackground,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TextBox}}}" CornerRadius="5,0,0,5" />
 77                                                 </ControlTemplate>
 78                                             </RepeatButton.Template>
 79                                         </RepeatButton>
 80                                     </Track.DecreaseRepeatButton>
 81                                     <Track.Thumb>
 82                                         <!--滑块-->
 83                                         <Thumb>
 84                                             <Thumb.Template>
 85                                                 <ControlTemplate>
 86                                                     <Border Background="{Binding Path=ScrollBarForeground,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TextBox}}}" CornerRadius="5" />
 87                                                 </ControlTemplate>
 88                                             </Thumb.Template>
 89                                         </Thumb>
 90                                     </Track.Thumb>
 91                                     <Track.IncreaseRepeatButton>
 92                                         <!--右空白-->
 93                                         <RepeatButton Command="ScrollBar.PageRightCommand" Opacity="0.5">
 94                                             <RepeatButton.Template>
 95                                                 <ControlTemplate>
 96                                                     <Border Background="{Binding Path=ScrollBarBackground,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type TextBox}}}" CornerRadius="0,5,5,0" />
 97                                                 </ControlTemplate>
 98                                             </RepeatButton.Template>
 99                                         </RepeatButton>
100                                     </Track.IncreaseRepeatButton>
101                                 </Track>
102                             </Grid>
103                         </ControlTemplate>
104                     </ScrollBar.Template>
105                 </ScrollBar>
106             </Grid>
107         </ControlTemplate>
108     </ScrollViewer.Template>
109 </ScrollViewer>

_resize

在我们窗口变化时候,恐怕竖着的显示屏横着时候便会触发该事件,他会实行大家的refresh方法,重新载入参数页面消息
PS:其实就动画一块,IScroll逻辑是很连贯的

1 _resize: function () {
2   var that = this;
3 
4   clearTimeout(this.resizeTimeout);
5 
6   this.resizeTimeout = setTimeout(function () {
7     that.refresh();
8   }, this.options.resizePolling);
9 },

 

 

IScroll

IScroll类是大家的首要,贯穿其间的是八个事件机制:

① 原生的touch(鼠标)事件

② 系统自行建造的异步事件模型

起首点是touchstart,此中的卡通片又有比非常多按键,大家下边会慢慢涉及到,这里先说下她的粗略属性

1 protected override void OnMouseWheel(MouseWheelEventArgs e)
2 {
3      e.Handled = true;
4 }
  • (e.Delta >> 2));
      }

_prefixStyle

会用到的民用方法,会再次来到CSS3包容前缀

  最终还也许有一个冲突难点,当手动拖动滑块恐怕当用上下文菜单改换滚动条地点时是无法用动画的,因为那时候未有触发 OnMouseWheel ,没提到,这正是我们想要的,不过假若再度触发 OnMouseWheel 就有标题了,因为手动触发滚动的时候我们从不给 CurrentVerticalOffset 和 _totalVerticalOffset 赋值( CurrentVerticalOffset 和 _totalVerticalOffset 只在 OnMouseWheel 中赋值),所以在用动画试行滚动操作前要先判别一下是或不是须要先更新一下它们俩,怎么着推断?大家得以用三个私人商品房字段 _isRunning 来保障状态,每当动画开首就给它赋值true,截止则赋值false。这样一来,当 _isRunning = false 时,表达在调用 OnMouseWheel 前,动画已经甘休,客商大概曾经手动改造了滚动条地方(也大概未有,但那并不影响),所以将在给前面俩哥们更新一下值了。

 1 namespace FS.PresentationManagement.Controls
 2 {
 3     /// <summary>
 4     /// 文本消息框控件
 5     /// </summary>
 6     public partial class MessageTextBox : TextBox
 7     {
 8         public MessageTextBox()
 9         {
10             InitializeComponent();        
11         }
12     }
13 }

x/y

现阶段品质的x/y坐标,用于末端touch事件

1 private static readonly DependencyPropertyKey VerticalOffsetPropertyKey = DependencyProperty.RegisterReadOnly(nameof (VerticalOffset), typeof (double), typeof (ScrollViewer), (PropertyMetadata) new FrameworkPropertyMetadata((object) 0.0));
2 
3 public static readonly DependencyProperty VerticalOffsetProperty = ScrollViewer.VerticalOffsetPropertyKey.DependencyProperty;
 1     // 竖向
 2     private void ScrollYMethod()
 3         {
 4             double endOffset = 0;
 5             if (_ScrollY < 0)       // 向上滚动
 6                 endOffset = 0;
 7             else                    // 向下滚动
 8                 ScrollViewer.Dispatcher.Invoke((Action)(() => endOffset = ScrollViewer.ScrollableHeight), null);
 9             // 初始位置
10             double offset = 0;
11             ScrollViewer.Dispatcher.Invoke((Action)(() => offset = ScrollViewer.VerticalOffset), null);
12             // 开始滚动
13             while (offset != endOffset && _ScrollY != 0)
14             {
15                 ScrollViewer.Dispatcher.Invoke((Action)(() =>
16                 {
17                     offset = ScrollViewer.VerticalOffset;
18                     ScrollViewer.ScrollToVerticalOffset(ScrollViewer.VerticalOffset   _ScrollY);
19                 }), null);
20                 Thread.Sleep(100);
21             }
22         }
23 
24     // 横向
25     private void ScrollXMethod()
26         {
27             double endOffset = 0;
28             if (_ScrollX < 0)       // 向左滚动
29                 endOffset = 0;
30             else                    // 向右滚动
31                 ScrollViewer.Dispatcher.Invoke((Action)(() => endOffset = ScrollViewer.ScrollableWidth), null);
32             // 初始位置
33             double offset = 0;
34             ScrollViewer.Dispatcher.Invoke((Action)(() => offset = ScrollViewer.HorizontalOffset), null);
35             // 开始滚动
36             while (offset != endOffset && _ScrollX != 0)
37             {
38                 ScrollViewer.Dispatcher.Invoke((Action)(() =>
39                 {
40                     offset = ScrollViewer.HorizontalOffset;
41                     ScrollViewer.ScrollToHorizontalOffset(ScrollViewer.HorizontalOffset   _ScrollX);
42                 }), null);
43                 Thread.Sleep(100);
44             }
45         }

on

其一用于注册事件,我们事先做过介绍

  那样一来,ScrollViewer就不会响应滚轮事件了,大家就在此边做作品。首先我们给这一个ScrollViewer增加叁天性质 IsEnableInertia ,用来支配是或不是使用惯性,因为萝卜不结球大白菜各有所爱,不要想着强制全体人使用惯性,所以滚轮响应措施成为:

  也正是说,在_ScrollX和_ScrollY更新的时候,程序会进展壹回推断,借使滚动量不为0,并且信托调用未有起来依然已经收尾的时候,就调用委托,开端张开滚动。

scrollerStyle

scroller 的 Style对象,通过set他的特性改造样式

  图中,横轴表示时间,纵轴代表运动间隔。很醒目,中间的 EaseOut 格局就是大家想要的。到了此处思路就一清二楚了,我们得以定义叁天品质 CurrentVerticalOffset ,大家会在它上面完结动画,在它的值回调函数中调用 ScrollViewer.ScrollToVerticalOffset 来更新ScrollViewer的轮转位置。当然我们还亟需一个民用字段 _totalVerticalOffset ,这些是用来贮存ScrollViewer滚动目的地方的,滚轮向下滚动三个单位我们就给它减去贰遍 e.Delta ,这里的e是滚轮响应措施传进来的参数,每一次给它赋值之后,就足以在 CurrentVerticalOffset 上推行动画了: BeginAnimation(CurrentVerticalOffsetProperty, animation) ,须求极其注意的是,当四个依附属性用了动画片退换后,再对其赋值则不会卓有成效,原因是在三个动画片达到活动期的终点后,时间线私下认可会保持其速度,直到其父级的活动期和保持期结束结束。倘若想在动画结束后仍是能够手动改造正视属性的值,则需求把 FillBehavior 设置为Stop。不过尔尔又会现出叁个难点,一旦动画结束,这些依赖属性又会上升初步值,所以还要给那么些动画订阅一个 Completed 事件,在事件响应措施中为 CurrentVerticalOffset 给定指标值,也便是 _totalVerticalOffset 。

  化解格局:

start

 1 _start: function (e) {
 2   if (!this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated)) {
 3     return;
 4   }
 5 
 6   var point = e.touches ? e.touches[0] : e, pos;
 7   this.initiated = utils.eventType[e.type];
 8 
 9   this.moved = false;
10 
11   this.distY = 0;
12 
13   //开启动画时间,如果之前有动画的话,便要停止动画,这里因为没有传时间,所以动画便直接停止了
14   this._transitionTime();
15 
16   this.startTime = utils.getTime();
17 
18   //如果正在进行动画,需要停止,并且触发滑动结束事件
19   if (this.isInTransition) {
20     this.isInTransition = false;
21     pos = this.getComputedPosition();
22 
23     //移动过去
24     this._translate(Math.round(pos.x), Math.round(pos.y));
25     this._execEvent('scrollEnd');
26   }
27 
28   this.startX = this.x;
29   this.startY = this.y;
30   this.absStartX = this.x;
31   this.absStartY = this.y;
32   this.pointX = point.pageX;
33   this.pointY = point.pageY;
34 
35   this._execEvent('beforeScrollStart');
36 
37   e.preventDefault();
38 
39 },

在开班阶段,首先将moved属性设置为false,然后截止动画,假诺当前isInTransition值为1,须求将她安装为false並且维持如今的情事

PS:这一步是终止动画并且维持近些日子场地包车型地铁要害,这里会触发scrollEnd事件,滚动条会有所联合浮动

在做一些开头化操作后,该措施截至,那一个里面包车型客车主干正是结束动画况且做初阶化操作

  本质上大家只要接管ScrollViewer的轮转逻辑,而且把那一个逻辑替换来带有惯性的就可以,那么怎样去接管呢?这里的要紧是先屏蔽ScrollViewer的鼠标滚轮事件:

  最终,还会有点要解释一下,我们开采好多控件有类似于“PART_***”的称谓,那一个名称请不要随意变动,那是WPF内置的独特名称,比方ScrollViewer的“PART_ContentHost”名称,正是代表这一个控件是用于装载TextBox的文书内容的,并且经过测量试验,这一个名称只好用于ScrollViewer或然Adorner、Decorator控件。若无选用那几个独特名称,可能就不只怕像你想象中那样自动达成专门的工作了。

品质总览

彩民之家论坛9066777 7彩民之家论坛9066777 8音讯框基础C#

refresh

该方法其实应当属于系统第一步,这几个措施会让缓存IScroll中的几个DOM尺寸,动画多是和尺寸打关系嘛

 1 refresh: function () {
 2   var rf = this.wrapper.offsetHeight;     // Force reflow
 3 
 4   this.wrapperHeight = this.wrapper.clientHeight;
 5   this.scrollerHeight = this.scroller.offsetHeight;
 6   this.maxScrollY = this.wrapperHeight - this.scrollerHeight;
 7 
 8   this.endTime = 0;
 9 
10   var offset = $(this.wrapper).offset();
11 
12   this.wrapperOffset = {
13     left: offset.left * (-1),
14     top: offset.top * (-1)
15   };
16 
17   this._execEvent('refresh');
18 
19   this.resetPosition();
20 
21 },

率先做了一步操作让下边包车型地铁操作不会发生重绘

var rf = this.wrapper.offsetHeight;

下一场早先化了多少个基本点DOM的冲天,何况获得maxScrollY(真正使用的时候会/3)

接下去重新初始化了endtime为0,况且安装某些基本参数后触发refresh事件(会触发滚动条的refresh)
自然,假若超越了界限的话,会resetPosition,重新恢复设置地点
refresh本人并不复杂,不过对后边的熏陶比非常大,算是初阶化第一步的干活

  要拓宽改建的ScrollViewer控件就投身第一有的XAML代码中的省略部分,小编后天只贴出那部分代码:

ease

本条是CSS3的卡通片参数,会产生动画曲线,各位自个儿去看吗

彩民之家论坛9066777 9彩民之家论坛9066777 10滚动函数体

本性检验

彩民之家论坛9066777 11彩民之家论坛9066777 12

 1 //我们暂时只判断touch 和 mouse即可
 2 me.extend(me.style = {}, {
 3   hasTouch: 'ontouchstart' in window,
 4   transform: _prefixStyle('transform'),
 5   transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
 6   transitionDuration: _prefixStyle('transitionDuration'),
 7   transitionDelay: _prefixStyle('transitionDelay'),
 8   transformOrigin: _prefixStyle('transformOrigin')
 9 });
10 
11 me.extend(me.eventType = {}, {
12   touchstart: 1,
13   touchmove: 1,
14   touchend: 1,
15 
16   mousedown: 2,
17   mousemove: 2,
18   mouseup: 2
19 });
20 
21 me.extend(me.ease = {}, {
22   quadratic: {
23     style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
24     fn: function (k) {
25       return k * (2 - k);
26     }
27   },
28   circular: {
29     style: 'cubic-bezier(0.1, 0.57, 0.1, 1)', // Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 1)
30     fn: function (k) {
31       return Math.sqrt(1 - (--k * k));
32     }
33   },
34   back: {
35     style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
36     fn: function (k) {
37       var b = 4;
38       return (k = k - 1) * k * ((b   1) * k   b)   1;
39     }
40   },
41   bounce: {
42     style: '',
43     fn: function (k) {
44       if ((k /= 1) < (1 / 2.75)) {
45         return 7.5625 * k * k;
46       } else if (k < (2 / 2.75)) {
47         return 7.5625 * (k -= (1.5 / 2.75)) * k   0.75;
48       } else if (k < (2.5 / 2.75)) {
49         return 7.5625 * (k -= (2.25 / 2.75)) * k   0.9375;
50       } else {
51         return 7.5625 * (k -= (2.625 / 2.75)) * k   0.984375;
52       }
53     }
54   },
55   elastic: {
56     style: '',
57     fn: function (k) {
58       var f = 0.22,
59         e = 0.4;
60 
61       if (k === 0) { return 0; }
62       if (k == 1) { return 1; }
63 
64       return (e * Math.pow(2, -10 * k) * Math.sin((k - f / 4) * (2 * Math.PI) / f)   1);
65     }
66   }
67 });

View Code

ease时动画平滑度相关的东西,大家权且用着,前边看看能够用zepto大概CSS3默许的性质以调减代码量,工具类到此停止

 1     // 坚向位移
 2         private double _ScrollY
 3         {
 4             get { return _scrollY; }
 5             set
 6             {
 7                 _scrollY = value;
 8                 // 开启滚动
 9                 if (_scrollY != 0 && (_ScrollYResult == null || _ScrollYResult.IsCompleted))
10                     _ScrollYResult = _ScrollYAction.BeginInvoke(null, null);
11             }
12         }
13         private double _scrollY;
14 
15         // 横向位移
16         private double _ScrollX
17         {
18             get { return _scrollX; }
19             set
20             {
21                 _scrollX = value;
22                 // 开启滚动
23                 if (_scrollX != 0 && (_ScrollXResult == null || _ScrollXResult.IsCompleted))
24                     _ScrollXResult = _ScrollXAction.BeginInvoke(null, null);
25             }
26         }
27         private double _scrollX;
28 
29     // 竖向滚动
30         private Action _ScrollYAction;
31         private IAsyncResult _ScrollYResult;
32     
33         // 横向滚动
34         private Action _ScrollXAction;
35         private IAsyncResult _ScrollXResult;

结语

大家此番抄袭了IScroll大旨代码,变成了二个回顾的拖动库,大家对IScroll的读书恐怕一时就到此处了,接下去一段时间大家的重心会放到nodeJS下边
中途或许会提到到requireJS的源码学习,不过都不会离开nodeJS的着力

介意,请看最终的代码......

彩民之家论坛9066777 13

eventType

touch事件的话值就是1,mouse事件正是2,那么些对前面有震慑的

  便得以健全消除鼠标中轮滚动难点。

_initIndicator

该办法用于初阶化滚动条(那么些措施地方其实该靠前),他会起先化三个滚动条,然后在大团结多个事件情状下各类执行滚动条的二个主意

  上边介绍本文的主干,如何自定义ScrollViewer控件,当然,我们的对象亦非把它改成怎么样奇葩,只是想把滚动条变得精粹一点而已。借使运用WPF相当多的心上人会清楚,好多控件都以由相当多层一层一层地叠合产生可视化树的,ScrollViewer也不例外,未来因此Template属性能够完全自个儿定义其布局。

getTime

取妥贴前时间戳

  首先,给前台的最上层元素TextBox加多SelectionChanged="TextBox_SelectionChanged"事件,以追踪选中时鼠标所在地方:

resetPosition

该方法用于当不止边界时候要还原scroller地点的措施

  本博文分为四个部分,第一有的将陈诉怎么样改写TextBox的布局,第4局地则描述怎样改写Text博克斯中的ScrollViewer样式,第三片段则是对自定义样式时产生的三翻四复难题张开修补。

获得当前几日子戳

获取当前岁月戳这一个格局相比较轻便,那一个会在测算动画用到:

me.getTime = Date.now || function getTime() { return new Date().getTime(); };

  说Bellamy(Bellamy)下,_ScrollX和_ScrollY是七个分子属性,它们各自用来记录横向、竖向的鼠标位移,以用于决定是不是滚动。唯有在超越ScrollViewer的限按期,它们的值才会不为0,当小于0时代表要发展/左滚动,大于0时意味着向下/右滚动,它们的断然值越大,则滚动速度越快。

move

该阶段是第二为主,这里会基于运动得到新的坐标起先运动,假使超过边界会做二个甩卖,移动的值不会超越57%个马克斯Y
二个关键点是会触发scrollStart事件,让滚动条可以预知
另三个关键点是没过300ms会复位开端意况值,所以就算使劲按着显示屏不放,遽然放手,DOM还是会移动十分远

彩民之家论坛9066777 14彩民之家论坛9066777 15音信框基础XAML

options

设置的基本参数消息

this.options = {
  //是否具有滚动条
  scrollbars: true,
  // 其实时期Y的位置
  startY: 0,
  //超出边界还原时间点
  bounceTime: 600,
  //超出边界返回的动画
  bounceEasing: utils.ease.circular,

  //超出边界时候是否还能拖动
  bounce: true,

  //当window触发resize事件60ms后还原
  resizePolling: 60,
  startX: 0,
  startY: 0
};

此地的startY值得关心,笔者那边实在是想将X相关属性去掉,不过还尚未完全去掉,那些前面点重构代码时候搞掉吧

  在组织前台界面时,首先,定义了多少个Grid做为容器,并把它分成了四份,分别是内容、竖向滚动条、横向滚动条、空白。当中,内容位于0行、0列,使用ScrollContentPresenter来表示将在突显的剧情;竖向滚动条位于0行1列,使用ScrollBar来代表;横向滚动条位于1行0列,使用横向(Orientation="Horizontal")的ScrollBar来代表。

_transitionTimingFunction

1 _transitionTimingFunction: function (easing) {
2   this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
3 
4   this.indicator && this.indicator.transitionTimingFunction(easing);
5 },

该办法用于复位CSS3的小时曲线,那几个本身没搞懂,滚动条同样是同步的

  后台代码此时也特轻松,只是简单地一而再了TextBox控件:

_transitionTime

该方法会设置运动时间,不传的话运动时间为0 ,即未有动画

 1         private void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
 2         {
 3             if (ScrollViewer != null && this.SelectedText != "")
 4             {
 5                 var point = System.Windows.Input.Mouse.GetPosition(ScrollViewer);
 6                 // 纵向位移
 7                 double y = point.Y;
 8                 if (y > 0)
 9                 {
10                     y = y - ScrollViewer.ActualHeight;
11                     if (y < 0) y = 0;
12                 }
13                 _ScrollY = y;
14                 // 横向位移
15                 double x = point.X;
16                 if (x > 0)
17                 {
18                     x = x - ScrollViewer.ActualWidth;
19                     if (x < 0) x = 0;
20                 }
21                 _ScrollX = x;
22             }
23         }

handleEvent

切切实实事件施行的地方,不过的确的逻辑又分散到了上述的相继艺术

现今,IScroll的属性就介绍完成了,大家上边收取宗旨的做牵线

  Track的DecreaseRepeatButton正是空间白、Thumb则是滑块、IncreaseRepeatButton是下空白,分别对那五个控件进行体制自定义就可以改换其外观。须求表达的是竖向滚动条供给把Track的IsDirectionReversed属性设置为True,横向则设置为False,不然会产出非常奇怪的现象(原因嘛,我们看属性名的意思就知道了)。

_events

保存体系中登记的风浪,这里大家做个总计,系统三个注册了这么些事件:

this.on('scrollEnd', function () {
  this.indicator.fade();
});

var scope = this;
this.on('scrollCancel', function () {
  scope.indicator.fade();
});

this.on('scrollStart', function () {
  scope.indicator.fade(1);
});

this.on('beforeScrollStart', function () {
  scope.indicator.fade(1, true);
});

this.on('refresh', function () {
  scope.indicator.refresh();
});

① scrollEnd

那么些事件在系统中根本用于转移滚动条的光滑度

在touchstart时候因为会甘休动画所以会触发,可是因为touchstart截至后又会触发move所以滚动条还是会来得

在touchend时候会结束动画,当然也会触发

transitionend事件触发时候,动画真正的苏息,scrollEnd也会接触

② scrollCancel

当touchend时候即使肯定是贰回点击事件便会触发该事件,将滚动条光滑度设置为透明

③ scrollStart

当我们手指起始滑动时候,就能触发该事件,将滚动条反射率设置为可以预知

④ beforeScrollStart

当手指触屏显示器便会将折射率设置为非透明

以此有贰个论断点正是连连拖动才会设置非透明,倘若第贰次触屏必得求拖动才会展现

⑤ refresh

在触发系统refresh方法时候会该事件,那些事件会触发滚动条的refresh事件,更换其地方,以致相关的尺码(因为滚动条的尺寸依照他而来)

   平常的话,大家在别的文字相关软件上,比方记事本、网页等,只要鼠标左键按下拖动选汉语本,借使鼠标超过文本框可展现范围,便会活动向鼠标所在方向滚动文本内容,以贯彻跨页选中的功能。可是与主题素材1同样,由于改造了ScrollViewer的Template,导致那个通用成效也亟需团结达成了。

三烈风云主旨

提及三大亚湾原子核能发电站心就务须将isInTransition单独建议来,他唯有0,1三个值,然则是记录DOM是不是处在活动的严重性

  其他,假使不是把ScrollViewer的Name设置为“PART_ContentHost”,而是采用<TextBlock Text="{TemplateBinding Text}" TextWrapping="{TemplateBinding TextWrapping}" />放置到ScrollViewer体中,就足以健康滚动。但是此时会招致意敏不谢选普通话本了,因为TextBlock中的文本是不接济选中的,非常注意到,那时的轮转功效非常的低,滚动时画面有水落石出的木讷现象。一样假诺不把ScrollViewer的Name设置为“PART_ContentHost”,而用<Decorator Name="PART_ContentHost" />放置到ScrollViewer体中,尽管选中也能支撑,但是照旧不可能滚动。

_execEvent

接触注册的事件

  二、改造ScrollViewer控件

_initEvents

这些为IScroll滚动区域设定了骨干的DOM事件,有偏侧改换和尺寸改造的resize事件
接下来注册了甘休动画时候接触的轩然大波,以致基础四个事件点touchstart/touchmove/touchend

  难点1:鼠标中轮无法使ScrollViewer上下滚动

_vendor

CSS3 宽容前缀

彩民之家论坛9066777 16彩民之家论坛9066777 17自定义ScrollViewer模版

_transitionTime

 1 _transitionTime: function (time) {
 2   time = time || 0;
 3   this.scrollerStyle[utils.style.transitionDuration] = time   'ms';
 4 
 5   //滚动条,我们这里只会出现一个滚动条就不搞那么复杂了
 6   this.indicator && this.indicator.transitionTime(time);
 7 
 8 },
 9 
10 getComputedPosition: function () {
11   var matrix = window.getComputedStyle(this.scroller, null), x, y;
12 
13   matrix = matrix[utils.style.transform].split(')')[0].split(', ');
14   x =  (matrix[12] || matrix[4]);
15   y =  (matrix[13] || matrix[5]);
16 
17   return { x: x, y: y };
18 },

该措施用于重新恢复设置CSS3的光阴参数属性,设置为0的话就不会具备动画,有少数必要注意的是,滚动条总是与他是一齐的

彩民之家论坛9066777 18彩民之家论坛9066777 19ScrollViewer的后台重视属性

getComputedPosition

获得贰个DOM的实时样式样式,在touchstart时候保留DOM样式状态非常使得

  这年框架大致是,右侧将是二个ScrollViewer,用来彰显消息,侧边则是关闭和清理,五个按键,至于开关的体制,也早就开展了更改,每种开关使用三张图片来表示原来、停靠、按下两种情景,要求注意,上边的XAML中按键的Source路线是像“../Pic/xxx.png”,那是自己把图纸放到了当下文件的--->上级目录的--->Pic目录下,所以实际上海大学家在采纳的时候必要把那么些天性改成图片所在路线。

_translate

该办法比较关键
她会基于传入的x,y值设置translate属性,然后就能够生出动画,完了调用滚动条的updatePosition方法立异其岗位

彩民之家论坛9066777 20彩民之家论坛9066777 21开端化滚动条

scrollTo

该格局是上述多个措施的合集,除了_transitionTime会在表面平日出现以苏息动画外,此外措施基本在该方式内部使用

 1 scrollTo: function (x, y, time, easing) {
 2   easing = easing || utils.ease.circular;
 3 
 4   this.isInTransition = time > 0;
 5 
 6   if (!time || easing.style) {
 7     this._transitionTimingFunction(easing.style);
 8     this._transitionTime(time);
 9     this._translate(x, y);
10   }
11 },

因为滚动条的联合签字在相继子类方法中了,所以那个方法比较轻便了,其逻辑步入了各种子方法

如此那般整个承袭的办法介绍截止,大家初叶对三大骨干事件进展分析

  消除格局:

运动有关

 1 <TextBox x:Class="FS.PresentationManagement.Controls.MessageTextBox"
 2          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="SkyBlue">
 4     <TextBox.Template>
 5         <ControlTemplate TargetType="{x:Type TextBox}">
 6             <Grid Background="{TemplateBinding Background}">
 7                 <Grid.ColumnDefinitions>
 8                     <ColumnDefinition />
 9                     <ColumnDefinition Width="62" />
10                 </Grid.ColumnDefinitions>
11                 <!-- 文本框 -->
12                 <ScrollViewer x:Name="PART_ContentHost">
13                     <!-- 暂时省略 -->
14                 </ScrollViewer>
15                 <!-- 按钮 -->
16                 <Button Name="BTN_Clear" Margin="5" Grid.Column="1" Click="BTN_Clear_Click">
17                     <Button.Template>
18                         <ControlTemplate>
19                             <Image Name="IMG_Clear" Source="../Pic/clear.png"/>
20                             <ControlTemplate.Triggers>
21                                 <Trigger Property="IsMouseOver" Value="True">
22                                     <Setter TargetName="IMG_Clear" Property="Source" Value="../Pic/clear2.png" />
23                                 </Trigger>
24                                 <Trigger Property="Button.IsPressed" Value="True">
25                                     <Setter TargetName="IMG_Clear" Property="Source" Value="../Pic/clear3.png" />
26                                 </Trigger>
27                             </ControlTemplate.Triggers>
28                         </ControlTemplate>
29                     </Button.Template>
30                 </Button>
31                 <Button Name="BTN_Close" Margin="0,-18,-25,0" VerticalAlignment="Top" Width="32" Height="32" Grid.Column="1" Click="BTN_Close_Click">
32                     <Button.Template>
33                         <ControlTemplate>
34                             <Image Name="IMG_Close" Source="../Pic/close.png" />
35                             <ControlTemplate.Triggers>
36                                 <Trigger Property="IsMouseOver" Value="True">
37                                     <Setter TargetName="IMG_Close" Property="Source" Value="../Pic/close2.png" />
38                                 </Trigger>
39                                 <Trigger Property="Button.IsPressed" Value="True">
40                                     <Setter TargetName="IMG_Close" Property="Source" Value="../Pic/close3.png" />
41                                 </Trigger>
42                             </ControlTemplate.Triggers>
43                         </ControlTemplate>
44                     </Button.Template>
45                 </Button>
46             </Grid>
47         </ControlTemplate>
48     </TextBox.Template>
49 </TextBox>

工具类

首先,大家将iScroll的工具类搬离出来,然则大家系统是自然帮忙CSS3动画的,所以requestAnimationFrame方法大家就不予理睬了

第二,因为大家的系统是凭仗于zepto的,以至还用到了backbone(可是backbone与underscore大有被移除的也许,所以只用zepto就好)

  private void PART_ContentHost_MouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
  {
    ScrollViewer.ScrollToVerticalOffset(ScrollViewer.VerticalOffset

disable/enable

会集的按键

  滚动条是采纳的Track控件,它又包含八个区域,分别是空间白、滑块、下空白,我们来看个示例图:

_translate

 1 _translate: function (x, y) {
 2 
 3   this.scrollerStyle[utils.style.transform] = 'translate('   x   'px,'   y   'px)'   this.translateZ;
 4 
 5   this.x = x;
 6   this.y = y;
 7 
 8   if (this.options.scrollbars) {
 9     this.indicator.updatePosition();
10   }
11 
12 },

该方法会更换DOM的样式,然而其动画由CSS3的 transitionDuration 调整,这里更换了scroller样式会同步其滚动条的

  难点2:鼠标左键按住拖动不可能使ScrollViewer滚动

style

多少个CSS3 动画属性,比如在chrome上面是那般的

Object {
transform: "webkitTransform", 
transitionTimingFunction: "webkitTransitionTimingFunction",
transitionDuration: "webkitTransitionDuration",
transitionDelay: "webkitTransitionDelay", 
transformOrigin: "webkitTransformOrigin"
}

   产生这一个题指标由来特别奇怪,借使不是修改ScrollViewer的Template来完全改造它,而是利用ScrollViewer.Resources来定义ScrollBar的Style则完全不会时有发生这种主题素材,然则那不恐怕使的改变各控件的大大小小和布局。

初阶化方法

  对应的后台注重属性:

end

彩民之家论坛9066777 22彩民之家论坛9066777 23

 1 _end: function (e) {
 2   if (!this.enabled || utils.eventType[e.type] !== this.initiated) {
 3     return;
 4   }
 5 
 6   var point = e.changedTouches ? e.changedTouches[0] : e,
 7   momentumY,
 8   duration = utils.getTime() - this.startTime,
 9   newX = Math.round(this.x),
10   newY = Math.round(this.y),
11   distanceX = Math.abs(newX - this.startX),
12   distanceY = Math.abs(newY - this.startY),
13   time = 0,
14   easing = '';
15 
16   this.isInTransition = 0;
17   this.initiated = 0;
18   this.endTime = utils.getTime();
19 
20   if (this.resetPosition(this.options.bounceTime)) {
21     return;
22   }
23 
24   this.scrollTo(newX, newY);
25   if (!this.moved) {
26     //click 的情况
27 
28     this._execEvent('scrollCancel');
29     return;
30   }
31 
32   if (duration < 300) {
33 
34     momentumY = utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0);
35     //      newX = momentumX.destination;
36     newY = momentumY.destination;
37     time = Math.max(momentumY.duration);
38     this.isInTransition = 1;
39   }
40 
41   if (newY != this.y) {
42     if (newY > 0 || newY < this.maxScrollY) {
43       easing = utils.ease.quadratic;
44     }
45     this.scrollTo(newX, newY, time, easing);
46     return;
47   }
48 
49   this._execEvent('scrollEnd');
50 },

View Code

end阶段首先会将isInTransition设置为0,假使过量边界会进展处理,进行动画又会将 isInTransition 设置为1,在动画事件甘休后装置为0

时期还可能会管理部分别样景况,大家不予理睬,注重便是利用momentum获取了当下运动参数
下一场最早活动,此处逻辑全体解释开了,这里反而显得简单了

由来,整在那之中央块IScroll便表明甘休了,大家最后看看滚动条相关

  此时的功效如图所示:彩民之家论坛9066777 24  看起来基本上能用啊,右上角的关门按键由于截图原因不是很清楚,稍后咱们能够看看完整版的要好有的。

removeEvent

为dom注销事件,注意在那之中的fn是目的,具体管理在handleEvent里面

  一、生成自定义TextBox控件

addEvent

为dom绑定事件,注意个中的fn是目的,具体管理在handle伊夫nt里面

Indicator

因为我们对滚动条的急需变动简单,大家的滚动条未来就实在很轻易了,完全与scroller是一个从属关系,随着scroller而转换
风乐趣的相恋的人自个儿去探问啊,作者那边就随意他了

源码:

彩民之家论坛9066777 25彩民之家论坛9066777 26

  1 <!DOCTYPE html>
  2 <html>
  3 <head>
  4 <meta charset="utf-8">
  5 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
  6 
  7 <title>iScroll demo: scrollbars</title>
  8 
  9 
 10 <style type="text/css">
 11 * {
 12     -webkit-box-sizing: border-box;
 13     -moz-box-sizing: border-box;
 14     box-sizing: border-box;
 15 }
 16 
 17 html {
 18     -ms-touch-action: none;
 19 }
 20 
 21 body,ul,li {
 22     padding: 0;
 23     margin: 0;
 24     border: 0;
 25 }
 26 
 27 body {
 28     font-size: 12px;
 29     font-family: ubuntu, helvetica, arial;
 30     overflow: hidden; /* this is important to prevent the whole page to bounce */
 31 }
 32 
 33 #header {
 34     position: absolute;
 35     z-index: 2;
 36     top: 0;
 37     left: 0;
 38     width: 100%;
 39     height: 45px;
 40     line-height: 45px;
 41     background: #CD235C;
 42     padding: 0;
 43     color: #eee;
 44     font-size: 20px;
 45     text-align: center;
 46     font-weight: bold;
 47 }
 48 
 49 #footer {
 50     position: absolute;
 51     z-index: 2;
 52     bottom: 0;
 53     left: 0;
 54     width: 100%;
 55     height: 48px;
 56     background: #444;
 57     padding: 0;
 58     border-top: 1px solid #444;
 59 }
 60 
 61 #wrapper {
 62     position: absolute;
 63     z-index: 1;
 64     top: 45px;
 65     bottom: 48px;
 66     left: 0;
 67     width: 100%;
 68     background: #ccc;
 69     overflow: hidden;
 70 }
 71 
 72 #scroller {
 73     position: absolute;
 74     z-index: 1;
 75     -webkit-tap-highlight-color: rgba(0,0,0,0);
 76     width: 100%;
 77     -webkit-transform: translateZ(0);
 78     -moz-transform: translateZ(0);
 79     -ms-transform: translateZ(0);
 80     -o-transform: translateZ(0);
 81     transform: translateZ(0);
 82     -webkit-touch-callout: none;
 83     -webkit-user-select: none;
 84     -moz-user-select: none;
 85     -ms-user-select: none;
 86     user-select: none;
 87     -webkit-text-size-adjust: none;
 88     -moz-text-size-adjust: none;
 89     -ms-text-size-adjust: none;
 90     -o-text-size-adjust: none;
 91     text-size-adjust: none;
 92 }
 93 
 94 #scroller ul {
 95     list-style: none;
 96     padding: 0;
 97     margin: 0;
 98     width: 100%;
 99     text-align: left;
100 }
101 
102 #scroller li {
103     padding: 0 10px;
104     height: 40px;
105     line-height: 40px;
106     border-bottom: 1px solid #ccc;
107     border-top: 1px solid #fff;
108     background-color: #fafafa;
109     font-size: 14px;
110 }
111 
112 </style>
113 </head>
114 <body  >
115 <div id="header">抄袭IScroll</div>
116 
117 <div id="wrapper">
118     <div id="scroller">
119         <ul>
120             <li>Pretty row 1</li>
121             <li>Pretty row 2</li>
122             <li>Pretty row 3</li>
123             <li>Pretty row 4</li>
124             <li>Pretty row 5</li>
125             <li>Pretty row 6</li>
126             <li>Pretty row 7</li>
127             <li>Pretty row 8</li>
128             <li>Pretty row 9</li>
129             <li>Pretty row 10</li>
130             <li>Pretty row 11</li>
131             <li>Pretty row 12</li>
132             <li>Pretty row 13</li>
133             <li>Pretty row 14</li>
134             <li>Pretty row 15</li>
135             <li>Pretty row 16</li>
136             <li>Pretty row 17</li>
137             <li>Pretty row 18</li>
138             <li>Pretty row 19</li>
139             <li>Pretty row 20</li>
140             <li>Pretty row 21</li>
141             <li>Pretty row 22</li>
142             <li>Pretty row 23</li>
143             <li>Pretty row 24</li>
144             <li>Pretty row 25</li>
145             <li>Pretty row 26</li>
146             <li>Pretty row 27</li>
147             <li>Pretty row 28</li>
148             <li>Pretty row 29</li>
149             <li>Pretty row 30</li>
150             <li>Pretty row 31</li>
151             <li>Pretty row 32</li>
152             <li>Pretty row 33</li>
153             <li>Pretty row 34</li>
154             <li>Pretty row 35</li>
155             <li>Pretty row 36</li>
156             <li>Pretty row 37</li>
157             <li>Pretty row 38</li>
158             <li>Pretty row 39</li>
159             <li>Pretty row 40</li>
160             <li>Pretty row 41</li>
161             <li>Pretty row 42</li>
162             <li>Pretty row 43</li>
163             <li>Pretty row 44</li>
164             <li>Pretty row 45</li>
165             <li>Pretty row 46</li>
166             <li>Pretty row 47</li>
167             <li>Pretty row 48</li>
168             <li>Pretty row 49</li>
169             <li>Pretty row 50</li>
170         </ul>
171     </div>
172 </div>
173 
174 <div id="footer"></div>
175 
176   <script src="zepto.js" type="text/javascript"></script>
177   <script src="MyIscroll.js" type="text/javascript"></script>
178 
179   <script type="text/javascript">
180 
181     var s = new IScroll({
182       wrapper: $('#wrapper'),
183       scroller: $('#scroller')
184     });
185 
186   </script>
187 </body>
188 </html>

View Code

彩民之家论坛9066777 27彩民之家论坛9066777 28

  1 (function (window, document, Math) {
  2 
  3   var utils = (function () {
  4     var me = {};
  5     var _elementStyle = document.createElement('div').style;
  6 
  7     //获得需要兼容CSS3前缀
  8     var _vendor = (function () {
  9       var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'];
 10       var transform;
 11       var i = 0;
 12       var l = vendors.length;
 13 
 14       for (; i < l; i  ) {
 15         transform = vendors[i]   'ransform';
 16         if (transform in _elementStyle) return vendors[i].substr(0, vendors[i].length - 1);
 17       }
 18       return false;
 19     })();
 20 
 21     //获取样式(CSS3兼容)
 22     function _prefixStyle(style) {
 23       if (_vendor === false) return false;
 24       if (_vendor === '') return style;
 25       return _vendor   style.charAt(0).toUpperCase()   style.substr(1);
 26     }
 27 
 28     me.getTime = Date.now || function getTime() { return new Date().getTime(); };
 29 
 30     me.addEvent = function (el, type, fn, capture) {
 31       if (el[0]) el = el[0];
 32       el.addEventListener(type, fn, !!capture);
 33     };
 34 
 35     me.removeEvent = function (el, type, fn, capture) {
 36       if (el[0]) el = el[0];
 37       el.removeEventListener(type, fn, !!capture);
 38     };
 39 
 40     /*
 41     current:当前鼠标位置
 42     start:touchStart时候记录的Y(可能是X)的开始位置,但是在touchmove时候可能被重写
 43     time: touchstart到手指离开时候经历的时间,同样可能被touchmove重写
 44     lowerMargin:y可移动的最大距离,这个一般为计算得出 this.wrapperHeight - this.scrollerHeight
 45     wrapperSize:如果有边界距离的话就是可拖动,不然碰到0的时候便停止
 46     */
 47     me.momentum = function (current, start, time, lowerMargin, wrapperSize) {
 48       var distance = current - start,
 49         speed = Math.abs(distance) / time,
 50         destination,
 51         duration,
 52         deceleration = 0.0006;
 53 
 54       destination = current   (speed * speed) / (2 * deceleration) * (distance < 0 ? -1 : 1);
 55       duration = speed / deceleration;
 56 
 57       if (destination < lowerMargin) {
 58         destination = wrapperSize ? lowerMargin - (wrapperSize / 2.5 * (speed / 8)) : lowerMargin;
 59         distance = Math.abs(destination - current);
 60         duration = distance / speed;
 61       } else if (destination > 0) {
 62         destination = wrapperSize ? wrapperSize / 2.5 * (speed / 8) : 0;
 63         distance = Math.abs(current)   destination;
 64         duration = distance / speed;
 65       }
 66 
 67       return {
 68         destination: Math.round(destination),
 69         duration: duration
 70       };
 71     };
 72 
 73     $.extend(me, {
 74       hasTouch: 'ontouchstart' in window
 75     });
 76 
 77 
 78     //我们暂时只判断touch 和 mouse即可
 79     $.extend(me.style = {}, {
 80       transform: _prefixStyle('transform'),
 81       transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
 82       transitionDuration: _prefixStyle('transitionDuration'),
 83       transitionDelay: _prefixStyle('transitionDelay'),
 84       transformOrigin: _prefixStyle('transformOrigin')
 85     });
 86 
 87     $.extend(me.eventType = {}, {
 88       touchstart: 1,
 89       touchmove: 1,
 90       touchend: 1,
 91 
 92       mousedown: 2,
 93       mousemove: 2,
 94       mouseup: 2
 95     });
 96 
 97     $.extend(me.ease = {}, {
 98       quadratic: {
 99         style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
100         fn: function (k) {
101           return k * (2 - k);
102         }
103       },
104       circular: {
105         style: 'cubic-bezier(0.1, 0.57, 0.1, 1)', // Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 1)
106         fn: function (k) {
107           return Math.sqrt(1 - (--k * k));
108         }
109       },
110       back: {
111         style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
112         fn: function (k) {
113           var b = 4;
114           return (k = k - 1) * k * ((b   1) * k   b)   1;
115         }
116       },
117       bounce: {
118         style: '',
119         fn: function (k) {
120           if ((k /= 1) < (1 / 2.75)) {
121             return 7.5625 * k * k;
122           } else if (k < (2 / 2.75)) {
123             return 7.5625 * (k -= (1.5 / 2.75)) * k   0.75;
124           } else if (k < (2.5 / 2.75)) {
125             return 7.5625 * (k -= (2.25 / 2.75)) * k   0.9375;
126           } else {
127             return 7.5625 * (k -= (2.625 / 2.75)) * k   0.984375;
128           }
129         }
130       },
131       elastic: {
132         style: '',
133         fn: function (k) {
134           var f = 0.22,
135         e = 0.4;
136 
137           if (k === 0) { return 0; }
138           if (k == 1) { return 1; }
139 
140           return (e * Math.pow(2, -10 * k) * Math.sin((k - f / 4) * (2 * Math.PI) / f)   1);
141         }
142       }
143     });
144     return me;
145   })();
146 
147   function IScroll(opts) {
148     this.wrapper = typeof opts.wrapper == 'string' ? $(opts.wrapper) : opts.wrapper;
149     this.scroller = typeof opts.scroller == 'string' ? $(opts.scroller) : opts.scroller;
150     if (!opts.wrapper[0] || !opts.scroller[0]) throw 'param error';
151 
152     this.wrapper = this.wrapper[0];
153     this.scroller = this.scroller[0];
154 
155     //这个属性会被动态改变的,如果这里
156     this.scrollerStyle = this.scroller.style;
157 
158     this.options = {
159       //是否具有滚动条
160       scrollbars: true,
161       // 其实时期Y的位置
162       startY: 0,
163       //超出边界还原时间点
164       bounceTime: 600,
165       //超出边界返回的动画
166       bounceEasing: utils.ease.circular,
167 
168       //超出边界时候是否还能拖动
169       bounce: true,
170 
171       //当window触发resize事件60ms后还原
172       resizePolling: 60,
173       startX: 0,
174       startY: 0
175     };
176 
177     for (var i in opts) {
178       this.options[i] = opts[i];
179     }
180 
181     this.translateZ = ' translateZ(0)';
182 
183     this.x = 0;
184     this.y = 0;
185     this._events = {};
186     this._init();
187 
188     //更新滚动条位置
189     this.refresh();
190 
191     //更新本身位置
192     this.scrollTo(this.options.startX, this.options.startY);
193 
194     this.enable();
195 
196   };
197 
198   IScroll.prototype = {
199     _init: function () {
200       this._initEvents();
201 
202       //初始化滚动条,滚动条此处需要做重要处理
203       if (this.options.scrollbars) {
204         this._initIndicator();
205       }
206     },
207     refresh: function () {
208       var rf = this.wrapper.offsetHeight;     // Force reflow
209 
210       this.wrapperHeight = this.wrapper.clientHeight;
211       this.scrollerHeight = this.scroller.offsetHeight;
212       this.maxScrollY = this.wrapperHeight - this.scrollerHeight;
213 
214       this.endTime = 0;
215 
216       this._execEvent('refresh');
217 
218       this.resetPosition();
219 
220     },
221     _initEvents: function (remove) {
222       var eventType = remove ? utils.removeEvent : utils.addEvent;
223       var target = this.options.bindToWrapper ? this.wrapper : window;
224 
225       eventType(window, 'orientationchange', this);
226       eventType(window, 'resize', this);
227 
228       if (utils.hasTouch) {
229         eventType(this.wrapper, 'touchstart', this);
230         eventType(target, 'touchmove', this);
231         eventType(target, 'touchcancel', this);
232         eventType(target, 'touchend', this);
233       } else {
234         eventType(this.wrapper, 'mousedown', this);
235         eventType(target, 'mousemove', this);
236         eventType(target, 'mousecancel', this);
237         eventType(target, 'mouseup', this);
238       }
239 
240       eventType(this.scroller, 'transitionend', this);
241       eventType(this.scroller, 'webkitTransitionEnd', this);
242       eventType(this.scroller, 'oTransitionEnd', this);
243       eventType(this.scroller, 'MSTransitionEnd', this);
244     },
245     _start: function (e) {
246       if (!this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated)) {
247         return;
248       }
249 
250       var point = e.touches ? e.touches[0] : e, pos;
251       this.initiated = utils.eventType[e.type];
252 
253       this.moved = false;
254 
255       this.distY = 0;
256 
257       //开启动画时间,如果之前有动画的话,便要停止动画,这里因为没有传时间,所以动画便直接停止了
258       this._transitionTime();
259 
260       this.startTime = utils.getTime();
261 
262       //如果正在进行动画,需要停止,并且触发滑动结束事件
263       if (this.isInTransition) {
264         this.isInTransition = false;
265         pos = this.getComputedPosition();
266 
267         //移动过去
268         this._translate(Math.round(pos.x), Math.round(pos.y));
269         this._execEvent('scrollEnd');
270       }
271 
272       this.startX = this.x;
273       this.startY = this.y;
274       this.absStartX = this.x;
275       this.absStartY = this.y;
276       this.pointX = point.pageX;
277       this.pointY = point.pageY;
278 
279       this._execEvent('beforeScrollStart');
280 
281       e.preventDefault();
282 
283     },
284 
285     _move: function (e) {
286       if (!this.enabled || utils.eventType[e.type] !== this.initiated) {
287         return;
288       }
289 
290       e.preventDefault();
291 
292       var point = e.touches ? e.touches[0] : e,
293       deltaX = point.pageX - this.pointX,
294       deltaY = point.pageY - this.pointY,
295       timestamp = utils.getTime(),
296       newX, newY,
297       absDistX, absDistY;
298 
299       this.pointX = point.pageX;
300       this.pointY = point.pageY;
301 
302       this.distX  = deltaX;
303       this.distY  = deltaY;
304       absDistX = Math.abs(this.distX);
305       absDistY = Math.abs(this.distY);
306 
307       // 如果一直按着没反应的话这里就直接返回了
308       if (timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10)) {
309         return;
310       }
311 
312       newY = this.y   deltaY;
313 
314       if (newY > 0 || newY < this.maxScrollY) {
315         newY = this.options.bounce ? this.y   deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
316       }
317 
318       if (!this.moved) {
319         this._execEvent('scrollStart');
320       }
321 
322       this.moved = true;
323 
324       this._translate(0, newY);
325 
326       if (timestamp - this.startTime > 300) {
327         this.startTime = timestamp;
328         this.startX = this.x;
329         this.startY = this.y;
330       }
331 
332 
333     },
334     _end: function (e) {
335       if (!this.enabled || utils.eventType[e.type] !== this.initiated) {
336         return;
337       }
338 
339       var point = e.changedTouches ? e.changedTouches[0] : e,
340       momentumY,
341       duration = utils.getTime() - this.startTime,
342       newX = Math.round(this.x),
343       newY = Math.round(this.y),
344       distanceX = Math.abs(newX - this.startX),
345       distanceY = Math.abs(newY - this.startY),
346       time = 0,
347       easing = '';
348 
349       this.isInTransition = 0;
350       this.initiated = 0;
351       this.endTime = utils.getTime();
352 
353       if (this.resetPosition(this.options.bounceTime)) {
354         return;
355       }
356 
357       this.scrollTo(newX, newY);
358       if (!this.moved) {
359         //click 的情况
360 
361         this._execEvent('scrollCancel');
362         return;
363       }
364 
365       if (duration < 300) {
366 
367         momentumY = utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0);
368         //      newX = momentumX.destination;
369         newY = momentumY.destination;
370         time = Math.max(momentumY.duration);
371         this.isInTransition = 1;
372       }
373 
374       if (newY != this.y) {
375         if (newY > 0 || newY < this.maxScrollY) {
376           easing = utils.ease.quadratic;
377         }
378         this.scrollTo(newX, newY, time, easing);
379         return;
380       }
381 
382       this._execEvent('scrollEnd');
383     },
384 
385     _resize: function () {
386       var that = this;
387 
388       clearTimeout(this.resizeTimeout);
389 
390       this.resizeTimeout = setTimeout(function () {
391         that.refresh();
392       }, this.options.resizePolling);
393     },
394 
395     _transitionTimingFunction: function (easing) {
396       this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
397 
398       this.indicator && this.indicator.transitionTimingFunction(easing);
399     },
400 
401     //开始或者停止动画
402     _transitionTime: function (time) {
403       time = time || 0;
404       this.scrollerStyle[utils.style.transitionDuration] = time   'ms';
405 
406       //滚动条,我们这里只会出现一个滚动条就不搞那么复杂了
407       this.indicator && this.indicator.transitionTime(time);
408 
409     },
410 
411     getComputedPosition: function () {
412       var matrix = window.getComputedStyle(this.scroller, null), x, y;
413 
414       matrix = matrix[utils.style.transform].split(')')[0].split(', ');
415       x =  (matrix[12] || matrix[4]);
416       y =  (matrix[13] || matrix[5]);
417 
418       return { x: x, y: y };
419     },
420 
421     _initIndicator: function () {
422       //滚动条
423       var el = createDefaultScrollbar();
424       this.wrapper.appendChild(el);
425       this.indicator = new Indicator(this, { el: el });
426 
427       this.on('scrollEnd', function () {
428         this.indicator.fade();
429       });
430 
431       var scope = this;
432       this.on('scrollCancel', function () {
433         scope.indicator.fade();
434       });
435 
436       this.on('scrollStart', function () {
437         scope.indicator.fade(1);
438       });
439 
440       this.on('beforeScrollStart', function () {
441         scope.indicator.fade(1, true);
442       });
443 
444       this.on('refresh', function () {
445         scope.indicator.refresh();
446       });
447 
448     },
449 
450     //移动x,y这里比较简单就不分离y了
451     _translate: function (x, y) {
452 
453       this.scrollerStyle[utils.style.transform] = 'translate('   x   'px,'   y   'px)'   this.translateZ;
454 
455       this.x = x;
456       this.y = y;
457 
458       if (this.options.scrollbars) {
459         this.indicator.updatePosition();
460       }
461 
462     },
463 
464     resetPosition: function (time) {
465       var x = this.x,
466         y = this.y;
467 
468       time = time || 0;
469 
470       if (this.y > 0) {
471         y = 0;
472       } else if (this.y < this.maxScrollY) {
473         y = this.maxScrollY;
474       }
475 
476       if (y == this.y) {
477         return false;
478       }
479 
480       this.scrollTo(x, y, time, this.options.bounceEasing);
481 
482       return true;
483     },
484 
485     //移动
486     scrollTo: function (x, y, time, easing) {
487       easing = easing || utils.ease.circular;
488 
489       this.isInTransition = time > 0;
490 
491       if (!time || easing.style) {
492         this._transitionTimingFunction(easing.style);
493         this._transitionTime(time);
494         this._translate(x, y);
495       }
496     },
497 
498     //统一的关闭接口
499     disable: function () {
500       this.enabled = false;
501     },
502     //统一的open接口
503     enable: function () {
504       this.enabled = true;
505     },
506 
507     on: function (type, fn) {
508       if (!this._events[type]) {
509         this._events[type] = [];
510       }
511 
512       this._events[type].push(fn);
513     },
514 
515     _execEvent: function (type) {
516       if (!this._events[type]) {
517         return;
518       }
519 
520       var i = 0,
521             l = this._events[type].length;
522 
523       if (!l) {
524         return;
525       }
526 
527       for (; i < l; i  ) {
528         this._events[type][i].call(this);
529       }
530     },
531     destroy: function () {
532       this._initEvents(true);
533 
534       this._execEvent('destroy');
535     },
536 
537     _transitionEnd: function (e) {
538       if (e.target != this.scroller || !this.isInTransition) {
539         return;
540       }
541 
542       this._transitionTime();
543       if (!this.resetPosition(this.options.bounceTime)) {
544         this.isInTransition = false;
545         this._execEvent('scrollEnd');
546       }
547     },
548 
549     //事件具体触发点
550     handleEvent: function (e) {
551       switch (e.type) {
552         case 'touchstart':
553         case 'mousedown':
554           this._start(e);
555           break;
556         case 'touchmove':
557         case 'mousemove':
558           this._move(e);
559           break;
560         case 'touchend':
561         case 'mouseup':
562         case 'touchcancel':
563         case 'mousecancel':
564           this._end(e);
565           break;
566         case 'orientationchange':
567         case 'resize':
568           this._resize();
569           break;
570         case 'transitionend':
571         case 'webkitTransitionEnd':
572         case 'oTransitionEnd':
573         case 'MSTransitionEnd':
574           this._transitionEnd(e);
575           break;
576       }
577     }
578 
579   };
580 
581   function createDefaultScrollbar() {
582     var scrollbar = document.createElement('div'),
583         indicator = document.createElement('div');
584 
585     scrollbar.style.cssText = 'position:absolute;z-index:9999';
586     scrollbar.style.cssText  = ';width:7px;bottom:2px;top:2px;right:1px';
587     scrollbar.style.cssText  = ';overflow:hidden';
588 
589     indicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px';
590     indicator.style.width = '100%';
591 
592     scrollbar.appendChild(indicator);
593 
594     return scrollbar;
595   }
596 
597   function Indicator(scroller, opts) {
598     this.wrapper = typeof opts.el == 'string' ? document.querySelector(opts.el) : opts.el;
599     this.indicator = this.wrapper.children[0];
600 
601     this.wrapperStyle = this.wrapper.style;
602     this.indicatorStyle = this.indicator.style;
603     this.scroller = scroller;
604 
605     this.sizeRatioY = 1;
606     this.maxPosY = 0;
607 
608     this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
609     this.wrapperStyle[utils.style.transitionDuration] = '0ms';
610     this.wrapperStyle.opacity = '0';
611 
612   }
613 
614   Indicator.prototype = {
615     transitionTime: function (time) {
616       time = time || 0;
617       this.indicatorStyle[utils.style.transitionDuration] = time   'ms';
618     },
619     transitionTimingFunction: function (easing) {
620       this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
621     },
622     refresh: function () {
623 
624       this.transitionTime();
625 
626       var r = this.wrapper.offsetHeight; // force refresh
627 
628       this.wrapperHeight = this.wrapper.clientHeight;
629 
630 
631       this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
632       this.indicatorStyle.height = this.indicatorHeight   'px';
633 
634 
635       this.maxPosY = this.wrapperHeight - this.indicatorHeight;
636       this.sizeRatioY = (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
637 
638       this.updatePosition();
639     },
640     updatePosition: function () {
641       var y = Math.round(this.sizeRatioY * this.scroller.y) || 0;
642       this.y = y;
643 
644       //不需要兼容方式了
645       this.indicatorStyle[utils.style.transform] = 'translate(0px,'   y   'px)'   this.scroller.translateZ;
646 
647     },
648     fade: function (val, hold) {
649       if (hold && !this.visible) {
650         return;
651       }
652 
653       clearTimeout(this.fadeTimeout);
654       this.fadeTimeout = null;
655 
656       var time = val ? 250 : 500,
657             delay = val ? 0 : 300;
658 
659       val = val ? '1' : '0';
660 
661       this.wrapperStyle[utils.style.transitionDuration] = time   'ms';
662 
663       this.fadeTimeout = setTimeout((function (val) {
664         this.wrapperStyle.opacity = val;
665         this.visible =  val;
666       }).bind(this, val), delay);
667 
668     }
669   };
670 
671   IScroll.utils = utils;
672 
673 
674   window.IScroll = IScroll;
675 
676 
677 })(window, document, Math);

View Code

前言

近期几天大家前前后后为主将iScroll源码学的七七八八了,小说中未涉及的诸位就要本人去看了

  • 1. 【iScroll源码学习03】iScroll事件机制与滚动条的贯彻
  • 2. 【iScroll源码学习02】分解iScroll八个为主事件点
  • 3. 【iScroll源码学习01】企图阶段
  • 4. 【iScroll源码学习00】模拟iScroll

大家上学源码的指标决不是上学人家的源码,而是由权威的代码里面学习思想,也许钻探实施方案,就拿大家这一次学习iScroll,小编的指标便是

“抄袭”,作者前天就针对自身的供给来抄袭iScroll的源码,组成和谐的库,然后用于项目,然后快意的装X.......

_initIndicator

基于该方法会初步化一个滚动条,当然我们能够安顿参数不让滚动条出现

 1 _initIndicator: function () {
 2   //滚动条
 3   var el = createDefaultScrollbar();
 4   this.wrapper.appendChild(el);
 5   this.indicator = new Indicator(this, { el: el });
 6 
 7   this.on('scrollEnd', function () {
 8     this.indicator.fade();
 9   });
10 
11   var scope = this;
12   this.on('scrollCancel', function () {
13     scope.indicator.fade();
14   });
15 
16   this.on('scrollStart', function () {
17     scope.indicator.fade(1);
18   });
19 
20   this.on('beforeScrollStart', function () {
21     scope.indicator.fade(1, true);
22   });
23 
24   this.on('refresh', function () {
25     scope.indicator.refresh();
26   });
27 
28 },

因为滚动条的类,我们前边会详细说,这里便不关心了

_start/_move/_end

touch时候实行的艺术,那多少个主意大家前边详细解析

_transitionEnd

CSS3动画停止时候会接触的平地风波,这几个里面会将isInTransition设置为false,这是三个动画片的严重性参数依靠,大家后边要详细说

版权声明:本文由彩民之家高手论坛发布于编程技术,转载请注明出处:【iScroll源码学习04】分离IScroll宗旨彩民之家论坛