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 相关文章推荐
一些易混淆且不常用的属性,希望有用
Jan 29 Javascript
javascript 密码强弱度检测万能插件
Feb 25 Javascript
javascript预览上传图片发现的问题的解决方法
Nov 25 Javascript
jquery ajax请求方式与提示用户正在处理请稍等
Sep 01 Javascript
jQuery中focus事件用法实例
Dec 26 Javascript
javascript使用smipleChart实现简单图表
Jan 02 Javascript
jQuery中removeAttr()方法用法实例
Jan 05 Javascript
jQuery中prev()方法用法实例
Jan 08 Javascript
深入理解node exports和module.exports区别
Jun 01 Javascript
对比分析Django的Q查询及AngularJS的Datatables分页插件
Feb 07 Javascript
AngularJS自定义表单验证功能实例详解
Aug 24 Javascript
vue-router 起步步骤详解
Mar 26 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 CURL 多线程操作代码实例
2015/05/13 PHP
Thinkphp通过一个入口文件如何区分移动端和PC端
2017/04/18 PHP
thinkphp5框架实现的自定义扩展类操作示例
2019/05/16 PHP
PHP实现限制域名访问的实现代码(本地验证)
2020/09/13 PHP
关于__defineGetter__ 和__defineSetter__的说明
2007/05/12 Javascript
YUI 读码日记之 YAHOO.util.Dom - Part.1
2008/03/22 Javascript
JavaScript地图拖动功能SpryMap的简单实现
2013/07/17 Javascript
一个不错的仿携程自定义数据下拉选择select
2014/09/01 Javascript
JS中的form.submit()不能提交表单的错误原因
2014/10/08 Javascript
javaScript事件学习小结(四)event的公共成员(属性和方法)
2016/06/09 Javascript
js print打印网页指定区域内容的简单实例
2016/11/01 Javascript
javascript 中事件冒泡和事件捕获机制的详解
2017/09/01 Javascript
Vue中之nextTick函数源码分析详解
2017/10/17 Javascript
基于Two.js实现星球环绕动画效果的示例
2017/11/06 Javascript
jQuery简单判断值是否存在于数组中的方法示例
2018/04/17 jQuery
JavaScript常见鼠标事件与用法分析
2019/01/03 Javascript
通过实例讲解JS如何防抖动
2019/06/15 Javascript
js利用递归与promise 按顺序请求数据的方法
2019/08/30 Javascript
微信小程序 生成携带参数的二维码
2019/10/23 Javascript
jQuery 淡入/淡出效果函数用法分析
2020/05/19 jQuery
python实现目录树生成示例
2014/03/28 Python
Django修改app名称和数据表迁移方案实现
2020/09/17 Python
纯CSS打造(无图像无js)的非常流行的讲话(语音)气泡效果
2012/12/28 HTML / CSS
HTML5地理定位_动力节点Java学院整理
2017/07/12 HTML / CSS
植村秀加拿大官网:Shu Uemura加拿大
2019/09/03 全球购物
文员个人求职自荐信
2013/09/21 职场文书
大学应届生求职简历的自我评价
2013/10/08 职场文书
24岁生日感言
2014/01/13 职场文书
小学安全教育材料
2014/02/17 职场文书
大学生村官座谈会发言材料
2014/05/25 职场文书
房地产公司工程部经理岗位职责
2015/04/09 职场文书
汽车销售助理岗位职责
2015/04/14 职场文书
2016重阳节红领巾广播稿
2015/12/18 职场文书
安全生产协议书
2016/03/22 职场文书
2019假期福利管理制度!
2019/07/15 职场文书
导游词之河北野三坡
2019/12/11 职场文书