一分钟搞定AlloyTouch图片轮播组件

crrtty 8年前
   <p>轮播图也涉及到触摸和触摸反馈,同时,AlloyTouch可以把惯性运动打开或者关闭,并且设置min和max为运动区域,超出会自动回弹。</p>    <p>除了一般的竖向滚动,AlloyTouch也可以支持横向滚动,甚至任何属性的运动,因为它的设计的本质就是属性无关,触摸可以反馈到任何属性的运动。所以 <a href="/misc/goto?guid=4959728755439180524" rel="nofollow,noindex">AlloyTouch</a> 制作各种各样的轮播组件还是得心应手。</p>    <p><img src="https://simg.open-open.com/show/7853e55148193186de94b7da2cb762d5.gif"></p>    <p>第一种轮播图如上图所示。下面开始实现的过程。</p>    <h2>第0秒</h2>    <pre>  <code class="language-javascript"><div id="carousel-container">      <div class="carousel">          <div class="carousel-scroller" id="carousel-scroller">              <img style="width: 88%;" src="asset/ci1.jpg">              <img style="width: 88%;" src="asset/ci2.jpg">              <img style="width: 88%;" src="asset/ci3.jpg">              <img style="width: 88%;" src="asset/ci4.jpg">              <img style="width: 88%;" src="asset/ci5.jpg">          </div>        </div>  </div></code></pre>    <p>一共五张图,每张图占有屏幕比例的百分之88,所以用户的屏幕里可以看到一张多一点的图片,给用户可以横向滑动查看的感觉。</p>    <h2>第10秒</h2>    <pre>  <code class="language-javascript"><script src="../transformjs/transform.js"></script>  <script src="../alloy_touch.js"></script>  <script>      var scroller = document.querySelector("#carousel-scroller");      Transform(scroller);   </script></code></pre>    <p>通过Transform(scroller); 注入CSS3 transform属性。</p>    <h2>第20秒</h2>    <pre>  <code class="language-javascript">new AlloyTouch({      touch: "#carousel-container",//反馈触摸的dom      vertical: false,// 监听用户横向触摸      target: scroller, //运动的对象      property: "translateX",  //被运动的属性      min:0.88 * window.innerWidth * -5 + window.innerWidth,       max: 0  })</code></pre>    <p>这里最大的难点(其实也没有什么难的),就是就是min的值。因为初始值是0,所有向左边滑动一定是负值。可以得到max一定是0。</p>    <p>那么min的值就是: 屏幕的宽度-图片的张数*图片的宽度</p>    <ul>     <li>图片的宽度为0.88 * window.innerWidth</li>     <li>屏幕的宽度为window.innerWidth</li>     <li>图片的张数为 5</li>    </ul>    <p><img src="https://simg.open-open.com/show/a470bb71a592e715eaa0448d34823534.gif"></p>    <h2>第30秒</h2>    <p>如上图所示,相对于传统的swipe然后再去触发滚动,上面的跟手然后再去校正的体验是更加良好的。那么怎么实现呢?</p>    <p>首先,AlloyTouch是支持step配置。</p>    <pre>  <code class="language-javascript">new AlloyTouch({      step: 100,      ...      ...      ...  })</code></pre>    <p>只要用户设置的step,最后运动结束之后,AlloyTouch都会帮用户校正到最接近的step的整数倍的位置。</p>    <p>比如上面是100:</p>    <ul>     <li>如果运动的对象停在 120,会被校正到100</li>     <li>如果运动的对象停在 151,会被校正到200</li>     <li>如果运动的对象停在 281,会被校正到300</li>     <li>如果运动的对象停在 21,会被校正到0</li>    </ul>    <h2>第40秒</h2>    <p>当然这有个问题,比如用户从0滑倒30,其实他是想去100,但是会被校正到0!!!</p>    <p>所以光使用校正是不够。还需要一个API去阻止校正自己去注入逻辑滚动相应的位置。所以你必须支持AlloyTouch的:</p>    <p>to 方法</p>    <pre>  <code class="language-javascript">to(v [, time, easing])</code></pre>    <p>其中time和easing不是必须。time的默认值是600.</p>    <h2>第50秒</h2>    <pre>  <code class="language-javascript">var items = document.querySelectorAll("#nav a");  var scroller = document.querySelector("#carousel-scroller");  Transform(scroller);  new AlloyTouch({      touch: "#carousel-container",//反馈触摸的dom      vertical: false,//不必需,默认是true代表监听竖直方向touch      target: scroller, //运动的对象      property: "translateX",  //被运动的属性      min: window.innerWidth * -3, //不必需,运动属性的最小值      max: 0, //不必需,滚动属性的最大值      step: window.innerWidth,      inertia: false, //不必需,是否有惯性。默认是true      touchEnd: function (evt, v, index) {            var step_v = index * this.step * -1;          var dx = v - step_v;            if (v < this.min) {              this.to(this.min);          } else if (v > this.max) {              this.to(this.max);          } else if (Math.abs(dx) < 30) {              this.to(step_v);          }          else if (dx > 0) {              this.to(step_v + this.step);          } else {              this.to(step_v - this.step);          }            return false;      },      animationEnd: function (evt , v) {          var i = 0,              len = items.length;          for (; i < len; i++) {              if (i === this.currentPage) {                  items[i].classList.add("active");              } else {                  items[i].classList.remove("active");              }          }        }  })</code></pre>    <p>因为一共四张图,所以</p>    <p>min得到的结果是 window.innerWidth * -3</p>    <p>max的值依然是0</p>    <p>step的值是 window.innerWidth</p>    <p>通过设置 inertia: false,把惯性运动关掉</p>    <p>注意看touchEnd里面的return false是为了不去计算手指离开屏幕后的校正位置、惯性运动等逻辑。</p>    <p>touchEnd可以拿到当前的位置v以及当前所处的位置index。</p>    <p>animationEnd是运动结束后的回调,用来设置nav的active。当然不是所有浏览器都支持classList,这里只是为了演示代码足够简洁。</p>    <p>再注意,在touchEnd和animationEnd中能拿到this,也就是AlloyTouch当前对象的实例。其中,</p>    <p>to方法用来运动当前对象</p>    <p>step是当前的步长</p>    <p>还可以拿到currentPage去获取当前所处的页码</p>    <p>还能拿到min和max值,得到运动的区间。</p>    <p> </p>    <p>来自:http://www.cnblogs.com/iamzhanglei/p/6149063.html</p>    <p> </p>