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实现动态表格点击按钮表格增加一行
Aug 24 Javascript
JS实现仿google、百度搜索框输入信息智能提示的实现方法
Apr 20 Javascript
深入分析JSON编码格式提交表单数据
Jun 25 Javascript
javascript模块化简单解析
Apr 07 Javascript
基于jquery实现三级下拉菜单
May 10 Javascript
Javascript 数组去重的方法(四种)详解及实例代码
Nov 24 Javascript
jQuery插件DataTable使用方法详解(.Net平台)
Dec 22 Javascript
零基础轻松学JavaScript闭包
Dec 30 Javascript
vue2.0中vue-cli实现全选、单选计算总价格的实例代码
Jul 18 Javascript
在vue中动态添加class类进行显示隐藏实例
Nov 09 Javascript
8个非常实用的Vue自定义指令
Dec 15 Vue.js
JavaScript实现简单拖拽效果
Sep 15 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 常用字符串函数总结
2008/03/15 PHP
简单PHP上传图片、删除图片实现代码
2010/05/12 PHP
『PHP』PHP截断函数mb_substr()使用介绍
2013/04/22 PHP
java模拟PHP的pack和unpack类
2016/04/13 PHP
php图片添加水印例子
2016/07/20 PHP
laravel框架语言包拓展实现方法分析
2019/11/22 PHP
常用简易JavaScript函数
2009/04/09 Javascript
基于jQuery的Spin Button自定义文本框数值自增或自减
2010/07/17 Javascript
关于 文本框默认值 的操作js代码
2012/01/12 Javascript
JavaScript 函数replace深入了解
2013/03/14 Javascript
JS的千分位算法实现思路
2013/07/31 Javascript
JavaScript实现快速排序的方法
2015/07/31 Javascript
javascript函数命名的三种方式及区别介绍
2016/03/22 Javascript
angularJS之$http:与服务器交互示例
2017/03/17 Javascript
详解Vue中添加过渡效果
2017/03/20 Javascript
express框架实现基于Websocket建立的简易聊天室
2017/08/10 Javascript
浅谈在Vue-cli里基于axios封装复用请求
2017/11/06 Javascript
微信小程序搭建自己的Https服务器
2019/05/02 Javascript
Vue的click事件防抖和节流处理详解
2019/11/13 Javascript
javascript设计模式 ? 代理模式原理与用法实例分析
2020/04/16 Javascript
微信跳一跳python自动代码解读1.0
2018/01/12 Python
python 处理微信对账单数据的实例代码
2019/07/19 Python
Tensorflow训练模型越来越慢的2种解决方案
2020/02/07 Python
pycharm激活码快速激活及使用步骤
2020/03/12 Python
python导入库的具体方法
2020/06/18 Python
印尼太阳百货公司网站:Matahari
2018/02/04 全球购物
什么是反射?如何实现反射?
2016/07/25 面试题
超级搞笑检讨书
2014/01/15 职场文书
法制教育演讲稿
2014/09/10 职场文书
作风建设整改方案
2014/10/27 职场文书
2014年英语工作总结
2014/12/20 职场文书
一年级数学上册复习计划
2015/01/17 职场文书
开国大典观后感
2015/06/04 职场文书
Nginx部署vue项目和配置代理的问题解析
2021/08/04 Servers
html中两种获取标签内的值的方法
2022/06/16 jQuery
Java中的Kafka为什么性能这么快及4大核心详析
2022/09/23 Java/Android