当前位置:   article > 正文

QWebEngineView 实现网页触屏滑动_qt qwebengineview 不能触屏

qt qwebengineview 不能触屏

问题描述:

最近遇到一个很棘手的bug,最初做需求的时候没考虑到通用,认为前端不会经常改架构,就写死了只对某个标签设置scrollbar的值,导致后面前端html架构改了之后,找不到相应的标签,触屏滑动失效。
先说环境和需求:

SUSE linux, qt5.15.0(内置Chrome浏览器内核), Elo触屏显示器。
用QWebEngineView加载网页,希望做到像在手机上一样,通过手指上下滑动达到屏幕滚动效果

最开始做的时候,前端把滚动条放在IFRAME中,通过document.activeElement可以得到IFRAME,所以,只需要识别到IFRAME 标签,然后调用document.activeElement.contentWindow.scrollBy(0,yOffet)就能实现屏幕滚动。
现在前端修改了html架构, 把IFRAME标签去掉了,这就导致当初的逻辑完全失效,屏幕无法滚动。

问题分析

由于Chrome浏览器的特殊性,无论点击网页什么位置(除了输入框之类),document.activeElement.tagName始终返回BODY,无法得到BODY内部实际active的元素。Google各种资料,发现可以通过event获取当前事件的target。当前event事件的target可能是一个TD,DIV或者其他自定义标签,滚动条一般在其父节点上。尝试通过当前事件的target往上依次查找其父节点,直到得到有滚动条的元素。js脚本如下:

       QString load = QStringLiteral(
            " function f(evt) {" \
                "if(evt && evt.target) { " \
                    "var element = evt.target;" \
                    "while(element)" \
                    "{"
                         "element = element.parentElement;" \  //依次得到父节点
                         "if(element)" \
                         "{" \ //判断当前元素是否带滚动条
                               "element.scrollBy(0,2);"
                               "if(element.scrollTop > 0)"
                                "{"
                                      "element.scrollBy(0,-2);"
                                      "window.scrollElt = element;" //保存在一个全局变量里,以便在后面设置滚动条位置。
                                      "break; "
                                "}"
                                "else {"
                                 "element.scrollTo(0,0);}"
                         "}" \
                    "}" \

                "}" \
            "}" \

            " function f2(evt) {" \
                "window.scrollElt = null;" \
            "}" \

            "document.addEventListener('mousedown',f,false);" \
            "document.addEventListener('mouseup',f2,false);" \
        );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

有了带滚动条的元素对象,就能在Qt代码中的mouseMoveEvent() 中通过j调用脚本执行window.scrollElt.scrollBy()来设置滚动条位置了。

尝试过程:

  1. 原代码调用window.scrollBy()不起作用,查资料发现通过window执行的是全局的滚动条,如果滚动条刚好设在全局,会起作用,反之,如果滚动条设在了body内部的某个或者某些标签上,就不会起作用。
  2. 最开始单纯地通过在html中找到当前这个带滚动条的tag,然后调用它的scrollBy方法document.querySelector(‘.table-scroll’).scrollBy(0,%1); 或者 document.getElementById(‘table-scrollTo’).scrollBy(0,%1),发现只对当前这个html页面起作用,其他页面因为没有指定的标签Id,所以无效。
  3. 通过暴力地遍历整个html页面的div标签,然后通过visibility overflow-y scrollHeight clientHeight这些参数过滤出带滚动条的div。先不说性能,对于个别网页上看上去起作用,但是会发现,无论在哪个位置拖动鼠标,屏幕都会滚动,很明显,是因为没有定位到鼠标mousedown位置的元素。另外,有些div元素(或者其他元素)不能通过这几个条件判断出是否scrollbar,原因未知。所以这种思路也不行。
                QString frameScrollCode = QStringLiteral("function frameScroll(){" \
                     "var divList = document.getElementsByTagName('div');" \
                     "var div;" \
                     "for(var index=0; index < divList.length; index++) {" \
                         "var bVisible = window.getComputedStyle(divList[index]).getPropertyValue('visibility');" \
                         "var isScroll =window.getComputedStyle(divList[index]).getPropertyValue('overflow-y');" \
                         "var height = window.getComputedStyle(divList[index]).getPropertyValue('height');" \
                         "var sHeight = divList[index].scrollHeight;" \
                         "var cHeight = divList[index].clientHeight;" \

                         "if((bVisible == 'visible') && (isScroll == 'auto' || isScroll=='scroll') && (sHeight>cHeight))" \
                          "{" \
                                "alert(divList[index]);" \
                                "divList[index].scrollBy(0,%1);" \
                                " break; " \
                          "}" \
                     "}" \

                "}" \
                "frameScroll();" \
                ).arg(iGapy);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  1. stackoverflow上有个方法,通过监听焦点事件,修改window.activeElement, 发现不起作用,focus和blur事件捕捉不到。但是发现‘mousedown’ 和‘mouseup’ 事件可以捕捉到,让问题有了新的转机。
function _dom_trackActiveElement(evt) {
    if (evt && evt.target) { 
        document.activeElement = evt.target == document ? null : evt.target;
    }
}

function _dom_trackActiveElementLost(evt) { 
    document.activeElement = null;
}

if (!document.activeElement) {
    document.addEventListener("focus",_dom_trackActiveElement,true);
    document.addEventListener("blur",_dom_trackActiveElementLost,true);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  1. 尝试了各种方法判断某个元素是否有滚动条均失败(不能cover到所有的case)。最后通过其他项目组做前端的同事建议,找到一种非常规的方法:https://www.feiniaomy.com/post/986.html, 先移动一下位置,再判断是否有偏移,如果偏移了,说明有滚动条,反之,没有。
 	 "element.scrollBy(0,2);"
       "if(element.scrollTop > 0)"
        "{"
              "element.scrollBy(0,-2);"
              "window.scrollElt = element;" //保存在一个全局变量里,以便在后面设置滚动条位置。
              "break; "
        "}"
        "else {"
         "element.scrollTo(0,0);}"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/253725
推荐阅读
相关标签
  

闽ICP备14008679号