在移动设备上实现“更少”时仅触摸一次移动火力

Posted

技术标签:

【中文标题】在移动设备上实现“更少”时仅触摸一次移动火力【英文标题】:Touch move fire only once when implementing "less" like scrolling on mobile 【发布时间】:2020-06-10 04:17:09 【问题描述】:

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

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

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

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

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

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

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

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

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

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

【问题讨论】:

它可能相关,也可能不相关,但是移动 safari 中存在一个错误,即滑动和释放后滚动事件不会触发。我对此了解不多,但我在这篇文章的介绍中看到了它:destroytoday.com/blog/casper-homepage-section @JamesTomasino 我正在 Android 上进行测试。 @jcubic “如果有人对调查感兴趣,我可以将我所有的代码放在 Github 上的 jQuery 终端仓库中”:考虑我感兴趣(只有相关代码的 jsfiddle / *** sn-p [但是作为一个可执行的独立样本] 会更受欢迎) 【参考方案1】:

您需要的是简单的.terminal-wrapper pointer-events: none; (基于devel 分支)。但是使用此规则您无法选择文本,这就是为什么您只需要在移动设备上使用它。

我不确定这是否会阻止在移动设备上选择文本,但如果是这样,您可以尝试将其添加到 touchstart(甚至在 touchmove 作为第一条指令) em> 并在 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;

【讨论】:

感谢您的回答,我回家后会检查的。如果它可以解决我的问题,我将创建另一个赏金并给你积分。我现在无法奖励赏金,因为我无法测试您的解决方案。但它看起来很有希望。 终于测试了您的解决方案,非常完美。也可以用手指选择文本完美地工作,而无需切换指针事件。关于另一个赏金的最后一条评论是因为我认为它会在我能够测试解决方案之前到期。 有一个问题,我需要将 3 个移动功能合并到一个库中,专注于点击/触摸(使用 contenteditable)、触摸滚动和点击链接。当时我只能使用其中的两个。如果我使用指针事件,我无法点击链接。而且我无法触发在 touchstart 中添加指针事件,它需要在 touchstart 发生之前添加。您还有其他解决方案吗? 您可以在链接上使用pointer-events: visible;,它应该使它们“可点击”,例如:codesandbox.io/s/frosty-sun-zrxxq (黑色按钮具有该属性并将文本记录到控制台,而灰色则没有) 太棒了,谢谢,这 100% 符合我的要求。我认为指针事件就像不透明度一样工作,你不能在孩子身上启用它们。

以上是关于在移动设备上实现“更少”时仅触摸一次移动火力的主要内容,如果未能解决你的问题,请参考以下文章

在移动设备上实现 DLNA/UPnP (Win7 Play To)

干货 | 移动设备上实现“诗人也能用TensorFlow”

Forsta推出Digital Diaries移动应用,在桌面智能手机和平板电脑设备上实现无缝的消费者旅程和消费者画像捕捉

怎么在QGraphicsView上实现鼠标移动事件

svg上实现图形移动

即时通讯开发如何在WebSocket基础上实现Hybrid移动应用的消息推送