实现 "less" 就像在移动设备上滚动一样,只触摸一次移动开火

Touch move fire only once when implementing "less" like scrolling on mobile

我正在尝试在 jQuery 终端的较少扩展中实现触摸滚动。它的工作原理类似于 less unix 命令。

我有这个代码:

self.touch_scroll(function(event) {
    // how much difference changed since last touch move
    var delta = event.current.clientY - event.previous.clientY;
    var ret;
    var interpreter = interpreters.top();
    if (is_function(interpreter.touchscroll)) {
        ret = interpreter.touchscroll(event, delta, self);
    } else if (is_function(settings.touchscroll)) {
        ret = settings.touchscroll(event, delta, self);
    }
    if (ret === true) {
        return;
    }
    return false;
});
// make_callback_plugin is helper that use $.Callbacks and make sure that there is only
// one handler on the element
$.fn.touch_scroll = make_callback_plugin({
    name: 'touch',
    init: function(handler) {
        var origin;
        var previous;
        $(this).on('touchstart.scroll', function(e) {
            e = e.originalEvent;
            if (e.touches.length === 1) {
                previous = origin = e.touches[0];
            }
        }).on('touchmove.scroll', function(e) {
            e = e.originalEvent;
            console.log(!!origin + ' && ' + (e.touches.length) + ' === 1');
            if (origin && e.touches.length === 1) {
                var current = e.touches[0];
                var ret = handler({
                    origin: origin,
                    previous: previous,
                    current: current
                });
                if (ret === false) {
                    // this don't change anything
                    e.preventDefault();
                }
                previous = current;
            }
        }).on('touchend.scroll', function() {
            if (origin || previous) {
                origin = previous = null;
            }
        });
    },
    destroy: function() {
        $(this).off('touchstart.scroll touchmove.scroll touchend.scroll');
    }
});

里面 less 我有:

    function scroll(delta, scroll_by) {
        if (delta > 0) {
            pos -= scroll_by;
            if (pos < 0) {
                pos = 0;
            }
        } else {
            pos += scroll_by;
            if (pos - 1 > lines.length - rows) {
                pos = lines.length - rows + 1;
            }
        }
        print();
        return true;
    }
    term.push($.noop, {
        onResize: refresh_view,
        touchscroll: function(event, delta) {
            console.log({delta});
            var offset = Math.abs(delta);
            // 14 is default height of single line in pixels
            scroll(delta, Math.ceil(offset / 14));
            return false;
        },
        mousewheel: function(event, delta) {
            return scroll(delta, scroll_by);
        }, 

我也有这个css:

.terminal-less {
    touch-action: none;
    overscroll-behavior-y: contain;
}

在鼠标滚轮滚动时效果很好,它以相同数量的 scroll_by 滚动,默认情况下为 3(似乎是正确的)。 (pos 是行偏移量,所以如果我使用 pos++ 它 move/scroll 一行,touchscroll 中的增量在大约 -20 到 20 像素之间为正或负。

我遇到的问题是,如何让它用手指滚动?感觉不对。此外,它仅在不随手指移动时才滚动。 touchmove 只触发一次,当我在触摸 phone 时移动手指时它不应该触发吗?

有人有过这种触摸滚动行为的经验吗?

我正在搜索类似的问题,但没有找到解决方案。你知道为什么 touchmove 可以触发一次吗?我唯一能想到的是用作剪贴板的文本区域(在移动设备上它也用于启用虚拟键盘),但我已将背景设置为红色并且它不会继续移动 Android。我正在测试此绘图演示中的其他代码:

https://zipso.net/a-simple-touchscreen-sketchpad-using-javascript-and-html5/

它工作正常,当你移动手指时,触摸移动会一直触发。

有什么想法吗?这将很难复制,但如果有人对调查感兴趣,我可以将我所有的代码放在 jQuery 终端仓库(在某些分支中)的 github 上。

奇怪的是 touchend 在 touchmove 之后不触发,它只在我点击终端启用键盘时触发一次。

我试过猴子补丁 jQuery 并在每次触发时记录但我没有任何其他事件(这可能会阻止默认行为)也根据 docs mouse events fire after touchend 和那些不火。

你需要的很简单.terminal-wrapper { pointer-events: none; }(基于devel分支)。但是根据此规则,您不能 select 文本,这就是为什么您只需要将它用于移动设备。

I'm not sure if this will block the selection of text on mobile, but if so, you can try to add this on touchstart (or even on touchmove as the first instruction) and remove it on touchend.

此外,我不得不添加一些 JS 代码,因为没有它 interpreter.touchScroll 就是 undefined。但这不是问题的主要原因。

interpreters = new Stack($.extend({}, settings.extra, {
    name: settings.name,
    prompt: prompt,
    keypress: settings.keypress,
    keydown: settings.keydown,
    resize: settings.onResize,
    greetings: settings.greetings,
    mousewheel: settings.mousewheel,
    touchScroll: settings.touchScroll, // NEW LINE
    history: settings.history,
    keymap: new_keymap
}, interpreter));
self.touch_scroll(function(event) {
    var delta = event.current.clientY - event.previous.clientY;
    var ret;
    var interpreter = interpreters.top(); // NEW LINE
    if (is_function(interpreter.touchScroll)) {
        ret = interpreter.touchScroll(event, delta, self);
    } else if (is_function(settings.touchScroll)) {
        ret = settings.touchScroll(event, delta, self);
    }
    if (ret === true) {
        return;
    }
});

没有pointer-events: none;

pointer-events: none;