首页 > 解决方案 > 在移动设备上实现“更少”时仅触摸一次移动火力

问题描述

我正在尝试在 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');
    }
});

在里面我有:

    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++ 它移动/滚动一行,touchscroll 中的增量是从大约-20 到 20 像素的正数或负数。

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

有人对这种类型的触摸滚动行为有经验吗?

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

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

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

有任何想法吗?这将很难复制,但如果有人对调查感兴趣,我可以将我所有的代码放在 jQuery Terminal repo 的 github 上(在某个分支中)。

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

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

标签: javascriptandroidjquerytouch-eventjquery-terminal

解决方案


您需要的很简单.terminal-wrapper { pointer-events: none; } (基于devel分支)。但是使用此规则您无法选择文本,这就是为什么您需要仅将其用于移动设备的原因。

我不确定这是否会阻止在移动设备上选择文本,但如果是这样,您可以尝试将其添加到touchstart (甚至touchmove作为第一条指令)并将其删除touchend

另外,我必须添加一些 JS 代码,因为没有它interpreter.touchScrollundefined. 但这不是问题的主要原因。

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;

在此处输入图像描述


推荐阅读