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的滚动新闻列表
Jun 19 Javascript
js获取客户端外网ip的简单实例
Nov 21 Javascript
js写的方法实现上传图片之后查看大图
Mar 05 Javascript
JSONP之我见
Mar 24 Javascript
理解javascript异步编程
Jan 27 Javascript
javascript的几种继承方法介绍
Mar 22 Javascript
jQuery中DOM节点的删除方法总结(超全面)
Jan 22 Javascript
d3.js实现立体柱图的方法详解
Apr 28 Javascript
JavaScript无操作后屏保功能的实现方法
Jul 04 Javascript
Javascript中toFixed计算错误(依赖银行家舍入法的缺陷)解决方法
Aug 22 Javascript
vue源码学习之Object.defineProperty对象属性监听
May 30 Javascript
深入了解Vue3模板编译原理
Nov 19 Vue.js
面试题: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
APMServ使用说明
2006/10/23 PHP
php操作xml入门之xml基本介绍及xml标签元素
2015/01/23 PHP
PHP结合Mysql数据库实现留言板功能
2016/03/04 PHP
PDO::query讲解
2019/01/29 PHP
JavaScript 继承的实现
2009/07/09 Javascript
jquery ready函数源代码研究
2009/12/06 Javascript
jQuery 自动增长的文本输入框实现代码
2010/04/02 Javascript
JS中confirm,alert,prompt函数区别分析
2011/01/17 Javascript
javascript关于open.window子页面执行完成后刷新父页面的问题分析
2015/04/27 Javascript
Sublime Text 3常用插件及安装方法
2015/12/16 Javascript
js+canvas绘制五角星的方法
2016/01/28 Javascript
jQuery Mobile开发中日期插件Mobiscroll使用说明
2016/03/02 Javascript
如何使用jquery修改css中带有!important的样式属性
2016/04/28 Javascript
jQuery通用的全局遍历方法$.each()用法实例
2016/07/04 Javascript
Angular.js中$apply()和$digest()的深入理解
2016/10/13 Javascript
AngularJs上传前预览图片的实例代码
2017/01/20 Javascript
bootstrap multiselect 多选功能实现方法
2017/06/05 Javascript
jquery ajaxfileupload异步上传插件
2017/11/21 jQuery
bootstrap Table实现合并相同行
2019/07/19 Javascript
vue实现手机端省市区区域选择
2019/09/27 Javascript
javascript json对象小技巧之键名作为变量用法分析
2019/11/11 Javascript
python虚拟环境 virtualenv的简单使用
2020/01/21 Javascript
Angular8 简单表单验证的实现示例
2020/06/03 Javascript
用实例分析Python中method的参数传递过程
2015/04/02 Python
Python输出汉字字库及将文字转换为图片的方法
2016/06/04 Python
Python快速从注释生成文档的方法
2016/12/26 Python
Python连接mysql数据库及简单增删改查操作示例代码
2020/08/03 Python
python 实现简易的记事本
2020/11/30 Python
python中openpyxl和xlsxwriter对Excel的操作方法
2021/03/01 Python
英国著名的茶叶品牌:Whittard of Chelsea
2016/09/22 全球购物
竞选班干部演讲稿
2014/04/24 职场文书
标准离婚协议书(2014版)
2014/10/05 职场文书
网球场地租赁协议范本
2014/10/07 职场文书
公安纪律作风整顿剖析材料
2014/10/10 职场文书
发工资啦!教你用Python实现邮箱自动群发工资条
2021/05/10 Python
MySQL如何使用使用Xtrabackup进行备份和恢复
2021/06/21 MySQL