vue + any-touch实现一个iscroll 实现拖拽和滑动动画效果


Posted in Javascript onApril 08, 2019

vue + any-touch实现一个iscroll 实现拖拽和滑动动画效果

https://github.com/383514580/any-touch

先看demo

demo

说点湿的

 vue + any-touch实现一个iscroll 实现拖拽和滑动动画效果

iscroll其实代码量挺大的(近2100行, 还有另一个类似的库 betterScroll 他的代码量和iscroll差不多, 因为原理都是一样的), 阅读他们的代码

发现里面很多逻辑 其实都是在做手势判断 , 比如拖拽(pan), 和划(swipe), 还有部分元素(表单元素等)需要单独判断点击(tap), 这部分代码接近1/3, 所以我决定用自己开发的手势库(any-touch)实现一个iscroll, 同时配合文字让大家 最终都可以以最少的代码实现一个iscroll .

vue

观察了一段时间推荐排行, 发现大家都对 vue 感兴趣, 所以本次的"iscroll"将以vue组件的形式实现, 同时我也希望借助vue强大的抽象能力, 让最终代码控制在500行以内 , 希望大家喜欢.

本文是个系列文章

本文先实现拖拽和滑动动画, 因为这2部分都依赖 手势 , 借此用最少的代码先实现最核心的功能, 也让大家对后续的内容有信心.

简单说下iscroll原理

添加2个div, 最内的div(子div)通过设置css的transform的translate的值来模拟系统滚动效果.

说完逻辑再说代码

拖拽的时候通过panstart/panmove手势返回的 位移增量 (deltaX/Y)进行位置变化, 同时关闭动画效果.
发生快速划(swipe)的时候, 开启动画, 同时通过计算 目标位置 和 动画时间 来触发滑动动画.
代码

<div class="any-scroll-view">
  <div ref="body" :style="bodyStyle" class="any-scroll-view__body"><slot></slot></div>
</div>
.any-scroll-view {
  position: relative;
  width: 100%;
  height: 90vh; 
  overflow: hidden;

  &__body {
    transition-timing-function: cubic-bezier(0.1, 0.57, 0.1, 1);
    background: #eee;
    position: absolute;
    width: 100%;
    height: 100%;
  }
}
import AnyTouch from 'any-touch';
export default {
  name: 'any-scroll-view',

  props: {
    // 减速度, 单位px/s²
    acceleration: {
      type: Number,
      default: 3600
    }
  },

  data() {
    return {
      scrollTop: 0,
      scrollLeft: 0,
      transitionDuration: 300
    };
  },

  computed: {
    bodyStyle() {
      return {
        transitionDuration: `${this.transitionDuration}ms`,
        transform: `translate(${this.scrollLeft}px, ${
          this.scrollTop
        }px)`
      };
    }
  },

  mounted() {
    const at = new AnyTouch(this.$el);

    // 第一次触碰
    at.on('inputstart', (ev) => {
      this.stopRoll();
    });

    // 拖拽开始
    at.on('panstart', (ev) => {
      this.move(ev);
    });

    // 拖拽中
    at.on('panmove', (ev) => {
      this.move(ev);
    });

    // 快速滑动
    at.on('swipe', (ev) => {
      this.decelerate(ev);
    });

    this.$on('hook:destroy', () => {
      at.destroy();
    });
  },

  methods: {
    // https://github.com/nolimits4web/swiper/blob/master/dist/js/swiper.esm.js#L87
    // https://github.com/nolimits4web/Swiper/blob/master/src/utils/utils.js#L25
    getCurrentTranslate() {
      const style = getComputedStyle(this.$refs.body, null);
      const { transform } = style;
      const array = transform.match(/(\-?)(\d)+(\.\d{0,})?/g);
      return { x: Math.round(array[4]), y: Math.round(array[5]) };
    },

    stopRoll() {
      const { x, y } = this.getCurrentTranslate();
      this.moveTo({ scrollTop: y, scrollLeft: x });
    },

    /**
     * 移动body
     * @param {Object} 拖拽产生的数据
     * @param {Number} deltaX: x轴位移变化
     * @param {Number} deltaY: y轴位移变化
     */
    move({ deltaX, deltaY }, transitionDuration = 0) {
      this.transitionDuration = transitionDuration;
      this.scrollLeft += deltaX;
      this.scrollTop += deltaY;
    },

    /**
     * 移动到
     */
    moveTo({ scrollTop, scrollLeft }, transitionDuration = 0) {
      this.transitionDuration = transitionDuration;
      this.scrollLeft = scrollLeft;
      this.scrollTop = scrollTop;
    },

    /**
     * 拖拽松手后减速移动至停止
     * velocityX/Y的单位是px/ms
     */
    decelerate(ev) {
      const directionSign = { up: -1, right: 1, down: 1, left: -1 }[
        ev.direction
      ];

      // Top? | Left?
      let SCROLL_SUFFIX = 'Top';
      // x ? | y?
      let AXIS_SUFFIX = 'Y';
      if (ev.velocityX > ev.velocityY) {
        SCROLL_SUFFIX = 'Left';
        AXIS_SUFFIX = 'X';
      }

      // 减速时间, 单位ms
      // t = (v₂ - v₁) / a
      const velocity = ev[`velocity${AXIS_SUFFIX}`];
      this.transitionDuration = Math.round(
        ((velocity * 1000) / this.acceleration) * 1000
      );

      // 滑动距离
      // s = (v₂² - v₁²) / (2 * a)
      const scrollAxis = `scroll${SCROLL_SUFFIX}`;
      this[scrollAxis] +=
        directionSign *
        Math.round(
          Math.pow(velocity * 1000, 2) / (2 * this.acceleration)
        );
    }
  }
};

总结

以上所述是小编给大家介绍的vue + any-touch实现一个iscroll 实现拖拽和滑动动画效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jQuery 可以拖动的div实现代码 脚本之家修正版
Jun 26 Javascript
鼠标滑上去后图片放大浮出效果的js代码
May 28 Javascript
js登录弹出层特效
Mar 07 Javascript
jquery制作select列表双向选择示例代码
Sep 02 Javascript
初识Node.js
Sep 03 Javascript
JavaScript生成图形验证码
Aug 24 Javascript
jquery实现的简单轮播图功能【适合新手】
Aug 17 jQuery
vue自定义全局共用函数详解
Sep 18 Javascript
vue-cli项目无法用本机IP访问的解决方法
Sep 20 Javascript
Vue解析带html标签的字符串为dom的实例
Nov 13 Javascript
解决vue项目中页面调用数据 在数据加载完毕之前出现undefined问题
Nov 14 Javascript
浅谈Web Storage API的使用
Jun 23 Javascript
面试题:react和vue的区别分析
Apr 08 #Javascript
vue router 组件的高级应用实例代码
Apr 08 #Javascript
JavaScript中的一些实用小技巧总结
Apr 07 #Javascript
详解vue 不同环境配置不同的打包命令
Apr 07 #Javascript
JavaScript数组去重的几种方法
Apr 07 #Javascript
vue表单验证你真的会了吗?vue表单验证(form)validate
Apr 07 #Javascript
js中Generator函数的深入讲解
Apr 07 #Javascript
You might like
php高级编程-函数-郑阿奇
2011/07/04 PHP
php Session存储到Redis的方法
2013/11/04 PHP
学习php中的正则表达式
2014/08/17 PHP
php魔术函数__call()用法实例分析
2015/02/13 PHP
示例详解Laravel的注册重构
2016/08/14 PHP
解决jquery .ajax 在IE下卡死问题的解决方法
2009/10/26 Javascript
JavaScript DOM 学习第九章 选取范围的介绍
2010/02/19 Javascript
javascript定义函数的方法
2010/12/06 Javascript
Jquery submit()无法提交问题
2013/04/21 Javascript
javascript自然分类法算法实现代码
2013/10/11 Javascript
JS实现多物体缓冲运动实例代码
2013/11/29 Javascript
Javascript玩转继承(一)
2014/05/08 Javascript
浅谈JavaScript正则表达式分组匹配
2015/04/10 Javascript
JS实现点击按钮获取页面高度的方法
2015/11/02 Javascript
JavaScript实现打开链接页面的方式汇总
2016/06/02 Javascript
jQuery simpleModal插件的使用介绍
2016/08/30 Javascript
AngularJS实现标签页的两种方式
2016/09/05 Javascript
react redux入门示例
2018/04/19 Javascript
swiper.js插件实现pc端文本上下滑动功能示例
2018/12/03 Javascript
vue路由传参三种基本方式详解
2019/12/09 Javascript
[01:13:18]Secret vs Infamous 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.23
2019/09/05 DOTA
使用Python编写简单的端口扫描器的实例分享
2015/12/18 Python
轻松实现TensorFlow微信跳一跳的AI
2018/01/05 Python
python爬虫爬取淘宝商品信息(selenum+phontomjs)
2018/02/24 Python
Python 实现微信防撤回功能
2019/04/29 Python
Python命令行参数解析工具 docopt 安装和应用过程详解
2019/09/26 Python
canvas因为图片资源不在同一域名下而导致的跨域污染画布的解决办法
2019/01/18 HTML / CSS
详解如何在登录过期后跳出Ifram框架
2020/09/10 HTML / CSS
泰坦健身器材:Titan Fitness
2018/02/13 全球购物
英国第一职业高尔夫商店:Clickgolf.co.uk
2020/11/18 全球购物
机电一体化应届生求职信范文
2014/01/24 职场文书
学习标兵获奖感言
2014/02/20 职场文书
法定代表人授权委托书格式
2014/10/14 职场文书
个人培训总结
2015/03/05 职场文书
2015年优质护理服务工作总结
2015/04/08 职场文书
Golang实现AES对称加密的过程详解
2021/05/20 Golang