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 防止表单重复提交代码
Jan 21 Javascript
jquery图片上下tab切换效果
Mar 18 Javascript
stream.js 一个很小、完全独立的Javascript类库
Oct 28 Javascript
JavaScript实现的石头剪刀布游戏源码分享
Aug 22 Javascript
谈谈Jquery ajax中success和complete有哪些不同点
Nov 20 Javascript
javascript加减乘除的简单实例
Jul 12 Javascript
jquery动态遍历Json对象的属性和值的方法
Jul 27 Javascript
requireJS模块化实现返回顶部功能的方法详解
Oct 16 Javascript
详解vue 单页应用(spa)前端路由实现原理
Apr 04 Javascript
微信小程序开发之tabbar图标和颜色的实现
Oct 17 Javascript
nvm、nrm、npm 安装和使用详解(小结)
Jan 17 Javascript
Javascript读取上传文件内容/类型/字节数
Apr 30 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中执行cmd命令的方法
2014/10/11 PHP
PHP文件锁函数flock()详细介绍
2014/11/18 PHP
CodeIgniter基于Email类发邮件的方法
2016/03/29 PHP
执行iframe中的javascript方法
2008/10/07 Javascript
自用js开发框架小成 学习js的朋友可以看看
2010/11/16 Javascript
js禁止回车提交表单的示例代码
2013/12/23 Javascript
javascript模拟map输出与去除重复项的方法
2015/02/09 Javascript
js实现兼容IE、Firefox的图片缩放代码
2015/12/08 Javascript
原生js实现百叶窗效果及原理介绍
2016/04/12 Javascript
jQuery mobile的header和footer在点击屏幕的时候消失的解决办法
2016/07/01 Javascript
Javascript 数组去重的方法(四种)详解及实例代码
2016/11/24 Javascript
WEB开发之注册页面验证码倒计时代码的实现
2016/12/15 Javascript
vue.js内部自定义指令与全局自定义指令的实现详解(利用directive)
2017/07/11 Javascript
浅谈Redux中间件的实践
2018/07/27 Javascript
总结javascript三元运算符知识点
2018/09/28 Javascript
基于VUE实现的九宫格抽奖功能
2018/09/30 Javascript
[01:02:38]DOTA2-DPC中国联赛定级赛 LBZS vs Phoenix BO3第二场 1月10日
2021/03/11 DOTA
Python递归实现汉诺塔算法示例
2018/03/19 Python
PyQt5每天必学之关闭窗口
2018/04/19 Python
python ddt数据驱动最简实例代码
2019/02/22 Python
Pyqt5实现英文学习词典
2019/06/24 Python
pygame实现俄罗斯方块游戏(对战篇1)
2019/10/29 Python
利用python读取YUV文件 转RGB 8bit/10bit通用
2019/12/09 Python
Python class的继承方法代码实例
2020/02/14 Python
python判断两个序列的成员是否一样的实例代码
2020/03/01 Python
解决numpy矩阵相减出现的负值自动转正值的问题
2020/06/03 Python
css3高级选择器使用方法
2013/12/02 HTML / CSS
Parts Express:音频、视频和扬声器的第一来源
2017/04/25 全球购物
高中生的自我评价
2014/03/04 职场文书
销售员岗位职责
2015/02/10 职场文书
节约用电倡议书
2015/04/28 职场文书
幼儿园开学家长寄语(2015秋季)
2015/05/27 职场文书
教师节老师寄语
2015/05/28 职场文书
安全伴我行主题班会
2015/08/13 职场文书
Python生成九宫格图片的示例代码
2021/04/14 Python
python数字图像处理之图像自动阈值分割示例
2022/06/28 Python