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 相关文章推荐
autoIMG 基于jquery的图片自适应插件代码
Mar 12 Javascript
js禁止document element对象选中文本实现代码
Mar 21 Javascript
jQuery的DOM操作之删除节点示例
Jan 03 Javascript
复杂的javascript窗口分帧解析
Feb 19 Javascript
javascript之IE版本检测超简单方法
Aug 20 Javascript
基于JavaScript实现随机颜色输入框
Dec 10 Javascript
Vue.js结合bootstrap实现分页控件
Mar 10 Javascript
微信JSAPI Ticket接口签名详解
Jun 28 Javascript
BootStrap Table复选框默认选中功能的实现代码(从数据库获取到对应的状态进行判断是否为选中状态)
Jul 11 Javascript
Vue组件中的data必须是一个function的原因浅析
Sep 03 Javascript
Vue开发中遇到的跨域问题及解决方法
Feb 11 Javascript
jquery实现轮播图特效
Apr 12 jQuery
面试题: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实现的生成静态HTML速度快类库
2007/03/31 PHP
php 攻击方法之谈php+mysql注射语句构造
2009/10/30 PHP
用PHP实现小写金额转换大写金额的代码(精确到分)
2012/01/10 PHP
PHP7.0安装笔记整理
2015/08/28 PHP
Zend Framework校验器Zend_Validate用法详解
2016/12/09 PHP
PHP命令Command模式用法实例分析
2018/08/08 PHP
JavaScript入门教程(7) History历史对象
2009/01/31 Javascript
JavaScript 自动分号插入(JavaScript synat:auto semicolon insertion)
2009/11/04 Javascript
javascript中运用闭包和自执行函数解决大量的全局变量问题
2010/12/30 Javascript
获取服务器传来的数据 用JS去空格的正则表达式
2012/03/26 Javascript
JavaScript跨浏览器获取页面中相同class节点的方法
2015/03/03 Javascript
使用Promise链式调用解决多个异步回调的问题
2017/01/15 Javascript
js实现类bootstrap模态框动画
2017/02/07 Javascript
JQuery validate 验证一个单独的表单元素实例
2017/02/17 Javascript
JS数组操作之增删改查的简单实现
2017/08/21 Javascript
深入浅析Vue中的slots/scoped slots
2018/04/03 Javascript
微信小程序swiper实现滑动放大缩小效果
2018/11/15 Javascript
jQuery访问json文件中数据的方法示例
2019/01/28 jQuery
ES10 特性的完整指南小结
2019/03/04 Javascript
Python实现读取TXT文件数据并存进内置数据库SQLite3的方法
2017/08/08 Python
python距离测量的方法
2018/03/06 Python
python实现NB-IoT模块远程控制
2018/06/20 Python
python: 判断tuple、list、dict是否为空的方法
2018/10/22 Python
详解python--模拟轮盘抽奖游戏
2019/04/12 Python
通过pycharm使用git的步骤(图文详解)
2019/06/13 Python
Tensorflow之MNIST CNN实现并保存、加载模型
2020/06/17 Python
python如何实时获取tcpdump输出
2020/09/16 Python
汽车队司机先进事迹材料
2014/02/01 职场文书
会计师职业生涯规划范文
2014/02/18 职场文书
《小松树和大松树》教学反思
2014/02/20 职场文书
教师爱岗敬业演讲稿
2014/05/05 职场文书
小学优秀班集体申报材料
2014/05/25 职场文书
2015年求职自荐信范文
2015/03/04 职场文书
2019年公司卫生管理制度样本
2019/08/21 职场文书
golang 实现Location跳转方式
2021/05/02 Golang
详解nodejs内置模块
2021/05/06 NodeJs