UDN-企业互联网技术人气社区

板块导航

浏览  : 396
回复  : 3

[原生js] AlloyTouch实战–60行代码搞定QQ看点资料卡

[复制链接]
小辫儿的头像 楼主
发表于 2016-12-31 15:27:12 | 显示全部楼层 |阅读模式
  如你体验所见,流程的滚动的同时还能支持头部的动画?不断地加载新数据还能做到流畅的滑动!怎么做得的?使用AlloyTouch CSS 0.2.0及以上版本便可!

  头部动画
1.gif

  加载更多
2.gif

  实现代码
  1. var infoList = document.getElementById("infoList"),
  2.     mockHTML = infoList.innerHTML,
  3.     scroller = document.getElementById("scroller"),
  4.     header = document.getElementById("header"),
  5.     userLogo = document.getElementById("user-logo-wrapper"),
  6.     loading = false,
  7.     alloyTouch = null;

  8. Transform(scroller, true);
  9. Transform(header);
  10. header.originY = -70;
  11. header.translateY = -70;
  12. Transform(userLogo);

  13. alloyTouch = new AlloyTouch({
  14.     touch: "#wrapper",
  15.     vertical: true,
  16.     target: scroller,
  17.     property: "translateY",
  18.     maxSpeed: 2,
  19.     outFactor: 0.1,
  20.     min: 160 * -20 + window.innerHeight - 202 - 50,
  21.     max: 0,
  22.     lockDirection: false,
  23.     touchStart: function () {
  24.         reastMin();
  25.     },
  26.     lockDirection: false,
  27.     change: function (v) {
  28.         if (v <= this.min + 5 && !loading) {
  29.             loading = true;
  30.             loadMore();
  31.         }
  32.         if (v < 0) {
  33.             if (v < -140) v = -140;
  34.             var scaleY = (240 + v) / 240;
  35.             header.scaleY = scaleY;
  36.             userLogo.scaleX = userLogo.scaleY = scaleY;
  37.             userLogo.translateY = v / 1.7;
  38.         } else {
  39.             var scaleY = 1 + v / 240;
  40.             header.scaleY = scaleY;
  41.             userLogo.scaleX = userLogo.scaleY = scaleY;
  42.             userLogo.translateY = v / 1.7;
  43.         }
  44.     }
  45. })

  46. function loadMore() {
  47.     setTimeout(function () {
  48.         infoList.innerHTML += mockHTML;
  49.         loading = false;
  50.         reastMin();
  51.     }, 500)
  52. }

  53. function reastMin() {
  54.     alloyTouch.min = -1 * parseInt(getComputedStyle(scroller).height) + window.innerHeight - 202;
  55. }

  56. document.addEventListener("touchmove", function (evt) {
  57.     evt.preventDefault();
  58. }, false);
复制代码

  就这么多代码。当然你要引用一个transformjs和alloy_touch.css.js。先看这一堆:
  1. Transform(scroller, true);
  2. Transform(header);
  3. header.originY = -70;
  4. header.translateY = -70;
  5. Transform(userLogo);
复制代码

  Transform(xxx)是什么意思?

  赋予xxx transformation能力

  第一个scroller加上true代表关闭透视投影,为什么要关闭透视投影?

  因为scroller里面是有文本,防止文本在IOS中模糊的情况。

  header是顶部的那个蓝色的区域。为什么要设置originY和translateY?为什么要设置为-70?

  因为header的高度为140px,用户向上滚动的过程中,需要对其进行scaleY变换。通常我们的做法是设置CSS3 transform-origin为 center top。而使用transformjs之后,可以抛弃transform-origin,使用originY或者originX属性便可。originY 设置为 -70,相对于高度为140的header来说就是center top。

  再看这一堆:
  1. alloyTouch = new AlloyTouch({
  2.     touch: "#wrapper",
  3.     vertical: true,
  4.     target: scroller,
  5.     property: "translateY",
  6.     maxSpeed: 2,
  7.     outFactor: 0.1,
  8.     lockDirection: false,
  9.     min: 160 * -20 + window.innerHeight - 202 - 50,
  10.     max: 0,
  11.     touchStart: function () {
  12.         resetMin();
  13.     },
  14.     lockDirection: false,
  15.     ...
  16.     ...
  17.     ...
  18. })
  19. ...
  20. ...
  21. function resetMin() {
  22.     alloyTouch.min = -1 * parseInt(getComputedStyle(scroller).height) + window.innerHeight - 202;
  23. }
复制代码

  使用AlloyTouch最关键的一点就是计算min和max的值。min和max决定了可以滚到哪里,到了哪里会进行回弹等等。这里max是0毫无疑问。

  但是min那一堆加减乘除是什么东西?

  这里首次加载是20行数据,每一行高度大概160,主意是大概, window.innerHeight是视窗的高度,202px是滚动的容器的padding top的值,50px是用来留给显示 加载更多 的…
1.png

  如上图所示,主要是需要求???的高度。

  那么怎么解决大概160*20的问题?

  touchStart的时候reastMin。resetMin会去通过getComputedStyle计算整个scroller的高度。

  maxSpeed是干什么用的?

  用来限制滚动的最大速度,个人感觉调整到2挺舒适,这个可以根据场景和被运动的属性灵活配置。

  outFactor是干什么用的?

  用来设置超出min或者max进行拖拽的运动比例系数,系数越小,超出min和max越难拖动,也就是受到的阻力越大。

  lockDirection是干什么用的?

  lockDirection默认值是true。代表用户起手时候是横向的,而你监听的是竖直方向的touch,这样的话是不会触发运动。只有起手和监听对应上才会有触摸运动。这里把lockDirection设置成false就没有这个限制,不管用户起手的direction,都会有触摸运动。

  再看AlloyTouch注入的change事件!头部动效核心的一个配置函数:
  1. change: function (v) {
  2.     if (v <= this.min + 5 && !loading) {
  3.         loading = true;
  4.         loadMore();
  5.     }
  6.     if (v < 0) {
  7.         if (v < -140) v = -140;
  8.         var scaleY = (240 + v) / 240;
  9.         header.scaleY = scaleY;
  10.         userLogo.scaleX = userLogo.scaleY = scaleY;
  11.         userLogo.translateY = v / 1.7;
  12.     } else {
  13.         var scaleY = 1 + v / 240;
  14.         header.scaleY = scaleY;
  15.         userLogo.scaleX = userLogo.scaleY = scaleY;
  16.         userLogo.translateY = v / 1.7;
  17.     }
  18. }
复制代码

  v代表当前被运动对象的被运动属性的当前的值,根据这个v去做一些效果和加载更多。

  什么时候加载更多?

  当滚动你能看到加载更多的时候去加载更多

  什么时候能看到加载更多?

  v <= this.min + 5。 可以看到change回调里可以拿到this,也就是AlloyTouch对象的实例,当v等于this.min代表滚到了底部,所以这里加上5代表快要滚动底部已经看到了加载更多。就去执行loadMore函数。

  loading是干什么用的?

  防止重复loadMore用得,因为change执行得很频繁,所以这里会通过loading的状态去锁上。

  下面一堆设置scaleX、scaleY、translateY以及一堆数字是怎么来的?

  慢慢调试得出的最佳效果~~反正就是根据v的数值映射到 header和用户头像的transform属性上,这里就不一一讲了。

  再看loadMore:
  1. function loadMore() {
  2.     setTimeout(function () {
  3.         infoList.innerHTML += mockHTML;
  4.         loading = false;
  5.         reastMin();
  6.     }, 500)
  7. }
复制代码

  这里使用了一段假的HTML去模拟AJAX异步请求以及数据转HTML的过程,整个耗时500ms,500ms后会去:

  • 插入HTML
  • 重置loading状态
  • 重置AlloyTouch的min

  最后:
  1. document.addEventListener("touchmove", function (evt) {
  2.     evt.preventDefault();
  3. }, false);
复制代码

  阻止掉整个document的默认事件,不会把整个页面拖下来,在手Q里的话,你就看不到网址和X5内核提供技术支持了。

  开始AlloyTouch

  Github: https://github.com/AlloyTeam/AlloyTouch

相关帖子

发表于 2016-12-31 15:27:41 | 显示全部楼层
LZ是闲人,天天发帖,坚定完毕
使用道具 举报

回复

发表于 2016-12-31 15:27:42 | 显示全部楼层
Very Good!
使用道具 举报

回复

发表于 2016-12-31 15:27:42 | 显示全部楼层
LZ敢整点更有创意的不?兄弟们等着围观捏~
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部