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 相关文章推荐
js 加载并解析XML字符串的代码
Dec 13 Javascript
jQuery 学习入门篇附实例代码
Mar 16 Javascript
JavaScript中的replace()方法使用详解
Jun 06 Javascript
jQuery鼠标事件汇总
Aug 30 Javascript
JS实现复制内容到剪贴板功能
Feb 05 Javascript
[原创]SyntaxHighlighter自动识别并加载脚本语言
Feb 07 Javascript
bootstrap模态框示例代码分享
May 17 Javascript
jQuery.form.js的使用详解
Jun 14 jQuery
ES6中Array.find()和findIndex()函数的用法详解
Sep 16 Javascript
微信页面弹出键盘后iframe内容变空白的解决方案
Sep 20 Javascript
bootstrap table合并行数据并居中对齐效果
Oct 17 Javascript
Node.js API详解之 zlib模块用法分析
May 19 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 简单日历实现代码
2009/10/28 PHP
php实现兼容2038年后Unix时间戳转换函数
2015/03/18 PHP
PHP图像裁剪缩略裁切类源码及使用方法
2016/01/07 PHP
Laravel框架路由和控制器的绑定操作方法
2018/06/12 PHP
jquery判断checkbox(复选框)是否被选中的代码
2010/10/20 Javascript
基于node.js的快速开发透明代理
2010/12/25 Javascript
Javascript编写俄罗斯方块思路及实例
2015/07/07 Javascript
轻松实现javascript图片轮播特效
2016/01/13 Javascript
jquery获取img的src值的简单实例
2016/05/17 Javascript
jQuery学习笔记之入门
2016/12/14 Javascript
Bootstrap整体框架之JavaScript插件架构
2016/12/15 Javascript
canvas实现探照灯效果
2017/02/07 Javascript
深入探究AngularJs之$scope对象(作用域)
2017/07/20 Javascript
vue组件之Alert的实现代码
2017/10/17 Javascript
vue中promise的使用及异步请求数据的方法
2018/11/08 Javascript
玩转Koa之koa-router原理解析
2018/12/29 Javascript
vue自定义组件(通过Vue.use()来使用)即install的用法说明
2020/08/11 Javascript
Python使用函数默认值实现函数静态变量的方法
2014/08/18 Python
Python批量更改文件名的实现方法
2017/10/29 Python
python 读取修改pcap包的例子
2019/07/23 Python
python3实现微型的web服务器
2019/09/03 Python
python 实现多线程下载m3u8格式视频并使用fmmpeg合并
2019/11/15 Python
python模式 工厂模式原理及实例详解
2020/02/11 Python
利用Tensorboard绘制网络识别准确率和loss曲线实例
2020/02/15 Python
自学python用什么系统好
2020/06/23 Python
一个入门级python爬虫教程详解
2021/01/27 Python
中东最大的在线宠物店:Dubai Pet Food
2020/06/11 全球购物
副厂长岗位职责
2014/02/02 职场文书
职业道德模范事迹材料
2014/08/24 职场文书
党员批评与自我批评材料
2014/10/14 职场文书
2014年法院工作总结
2014/11/24 职场文书
2015年幼儿园后勤工作总结
2015/04/25 职场文书
上学路上观后感
2015/06/16 职场文书
副校长2015年教育教学工作总结
2015/07/27 职场文书
公司环境卫生管理制度
2015/08/05 职场文书
vue如何使用模拟的json数据查看效果
2022/03/31 Vue.js