图标
创作项目友邻自述归档留言

ace编辑器设置惯性滚动

上个月我写了XK Editor这个项目,使用了 ace 编辑器和 tinymce 编辑器作为基础编辑器,但是当项目进入适配移动端的时候,遇到了一个很头疼的问题,ace 编辑器不支持惯性滚动,用起来会非常变扭,于是便为之增加惯性滚动的功能。

原理

惯性滚动,即在触屏设备中滑动手指,当手指离开屏幕后,滚动事件并不会立即停止,而是会继续移动一段距离,这段距离是由手离开屏幕时的滚动速度和预设的摩擦力决定的,通过这时的速度,预设的摩擦力和特定的公式计算出一系列滚动点,然后逐个滚动到滚动点,来模拟惯性滚动。

实现方案

  1. 监听开始触摸的事件,记录开始的时间和开始的坐标,同时重置滚动(防止连续滚动出现 Bug)
  2. 监听触摸结束的时间,记录结束的时间和结束的坐标
  3. 通过公式v = (endY - startY) / (endTime - startTime) * 1.5 1.5 的值可以调整
  4. 定义“摩擦力”deceleration = dir * 0.0018 0.0018 也可以调整
  5. 在每次微滚动前都计算一下滚动的坐标,然后进行滚动。
  6. 直至速度为 0 或者速度方向改变的时候停止滚动

实现代码

//惯性滚动
var editorDom = document.querySelector(".ace-editor");
var inertiaScrollTime = null;
editorDom.addEventListener("touchstart", function (event) {
  clearTimeout(inertiaScrollTime);
  var startY = event.changedTouches[0].pageY;
  var endY = 0;
  var startTime = Date.now();
  var endTime = 0;
  editorDom.addEventListener("touchend", function (event) {
    endY = event.changedTouches[0].pageY;
    endTime = Date.now();
    var _v = ((endY - startY) / (endTime - startTime)) * 1.5;

    function scrollToTop(v, sTime, contentY) {
      var dir = v > 0 ? -1 : 1;
      var deceleration = dir * 0.0018;
      var duration = v / deceleration;

      function inertiaMove() {
        // if(stopInertia) return
        var nowTime = Date.now();
        var t = nowTime - sTime;
        var nowV = v + t * deceleration;
        // 速度方向变化表示速度达到0了
        if (dir * nowV > 0) {
          return;
        }
        var moveY = (-(v + nowV) / 2) * t;
        window.$ace.session.setScrollTop(contentY + moveY);
        inertiaScrollTime = setTimeout(inertiaMove, 10);
      }
      inertiaMove();
    }
    scrollToTop(_v, endTime, window.$ace.session.getScrollTop());
  });
});
//惯性滚动
var editorDom = document.querySelector(".ace-editor");
var inertiaScrollTime = null;
editorDom.addEventListener("touchstart", function (event) {
  clearTimeout(inertiaScrollTime);
  var startY = event.changedTouches[0].pageY;
  var endY = 0;
  var startTime = Date.now();
  var endTime = 0;
  editorDom.addEventListener("touchend", function (event) {
    endY = event.changedTouches[0].pageY;
    endTime = Date.now();
    var _v = ((endY - startY) / (endTime - startTime)) * 1.5;

    function scrollToTop(v, sTime, contentY) {
      var dir = v > 0 ? -1 : 1;
      var deceleration = dir * 0.0018;
      var duration = v / deceleration;

      function inertiaMove() {
        // if(stopInertia) return
        var nowTime = Date.now();
        var t = nowTime - sTime;
        var nowV = v + t * deceleration;
        // 速度方向变化表示速度达到0了
        if (dir * nowV > 0) {
          return;
        }
        var moveY = (-(v + nowV) / 2) * t;
        window.$ace.session.setScrollTop(contentY + moveY);
        inertiaScrollTime = setTimeout(inertiaMove, 10);
      }
      inertiaMove();
    }
    scrollToTop(_v, endTime, window.$ace.session.getScrollTop());
  });
});

ace编辑器设置惯性滚动

https://blog.ixk.me/post/ace-editor-sets-inertial-scrolling
  • 许可协议

    BY-NC-SA

  • 本文作者

    Otstar Lin

  • 发布于

    2019/05/11

转载或引用本文时请遵守许可协议,注明出处、不得用于商业用途!

Acrylic - VSCode ExtensionJava二叉树实现