Java 如何在Selenium中在HTML5画布上执行鼠标滚轮滚动?

Java 如何在Selenium中在HTML5画布上执行鼠标滚轮滚动?,java,selenium,selenium-webdriver,html5-canvas,mousewheel,Java,Selenium,Selenium Webdriver,Html5 Canvas,Mousewheel,我正在研究GWT应用程序(类似于油漆)。在这里,我有一个HTML5画布,其中有一个功能,上下滚动鼠标滚轮将放大和缩小画布 我搜索了很多,但没有找到解决此问题的方法。以下是我们所做的: int PosX = 0; int PosY = 10; JavascriptExecutor executor = (JavascriptExecutor) getDriver(); String script = "document.getElementById('frontCanvas').scrollBy(

我正在研究GWT应用程序(类似于油漆)。在这里,我有一个HTML5画布,其中有一个功能,上下滚动鼠标滚轮将放大和缩小画布

我搜索了很多,但没有找到解决此问题的方法。以下是我们所做的:

int PosX = 0;
int PosY = 10;
JavascriptExecutor executor = (JavascriptExecutor) getDriver();
String script = "document.getElementById('frontCanvas').scrollBy("
                                + PosX + "," + PosY + ")";
executor.executeScript(script); 

WebDriverWait wait = new WebDriverWait(getDriver(), 20);
wait.until(ExpectedConditions.javaScriptThrowsNoExceptions(script));
现在,上面的代码适用于另一个Angular应用程序,我在其中上下滚动div元素(有一个滚动条),但它不适用于GWT应用程序中的画布(没有滚动条)

我正在使用Selenium 3.14.0并在Chrome浏览器上运行此代码。
有人可以建议如何解决此问题吗?

这将使用JS在当前页面中滚动特定内容

JavascriptExecutor executor = (JavascriptExecutor) getDriver();
executor.executeScript("window.scrollBy(" + start + "," + end + ")");
否则,您可以滚动直到找到WebElement,例如:

WebElement x;
JavascriptExecutor executor = (JavascriptExecutor) getDriver();
getJs().executeScript("arguments[0].scrollIntoView();", x);
谢谢

HTML元素用于通过JavaScript动态绘制图形。元素只是图形的容器。您必须使用JavaScript来实际绘制图形。Canvas有几种用于绘制路径、框、圆、文本和添加图像的方法

一般来说,要上下滚动鼠标滚轮,我们可以选择该类。但是,据我们所知,这个API似乎并不那么可靠。在Firefox中,每次
鼠标下压
鼠标上压
,或
鼠标点击
都发生在元素的中心。因此,上面的代码将生成一个
鼠标移动事件(xy),然后将
鼠标移动事件移动到画布的中心,然后将
鼠标下移
鼠标向上移动
,然后单击画布中心的所有内容。对于按钮来说,这可能很好,但是对于画布来说,这是不可行的,因为您希望能够
在特定位置悬停
单击
,等等。Safari的情况更糟,它只生成一个异常,表明不支持鼠标移动事件。同时,铬也可以很好地工作

可供替代的 一种解决方法是使用该接口,使用JavaScript手动调度合成的鼠标事件

从@FlorentB.中翻出一页,要向上滚动鼠标滚轮和向下滚动,可以通过脚本注入将鼠标滚轮、鼠标移动和滚轮事件发射到顶部元素,并且可以使用以下解决方案:

  • 代码块:

    package demo;
    
    import org.openqa.selenium.By;
    import org.openqa.selenium.JavascriptExecutor;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebDriverException;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.chrome.ChromeDriver;
    import org.openqa.selenium.chrome.ChromeOptions;
    import org.openqa.selenium.support.ui.ExpectedConditions;
    import org.openqa.selenium.support.ui.WebDriverWait;
    
    public class Canvas {
    
        static WebDriver driver;
        public static void main(String[] args) {
    
            System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
            ChromeOptions options = new ChromeOptions();
            options.addArguments("start-maximized");
            options.addArguments("disable-infobars");
            options.addArguments("--disable-extensions");
            driver = new ChromeDriver(options);
            driver.get("https://www.google.co.uk/maps");
            WebElement elm = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#scene > div.widget-scene > canvas")));
            // Mouse wheel UP or Zoom In 
            wheel_element(elm, -500, 0, 0);
            System.out.println("Mouse wheel UP or Zoom In through Wheel achieved !!!");
            // Mouse wheel DOWN or Zoom Out 
            wheel_element(elm, 120, 0, 0);
            System.out.println("Mouse wheel DOWN or Zoom Out through Wheel achieved !!!");
            System.out.println("Mouse Scroll through Wheel achieved !!!");
        }
    
        public static void wheel_element(WebElement element, int deltaY, int offsetX, int offsetY)
        {
            try{
                  String script = "var element = arguments[0];"
                    +"var deltaY = arguments[1];"
                    +"var box = element.getBoundingClientRect();"
                    +"var clientX = box.left + (arguments[2] || box.width / 2);"
                    +"var clientY = box.top + (arguments[3] || box.height / 2);"
                    +"var target = element.ownerDocument.elementFromPoint(clientX, clientY);"
                    +"for (var e = target; e; e = e.parentElement) {"
                      +"if (e === element) {"
                    +"target.dispatchEvent(new MouseEvent('mouseover', {view: window, bubbles: true, cancelable: true, clientX: clientX, clientY: clientY}));"
                    +"target.dispatchEvent(new MouseEvent('mousemove', {view: window, bubbles: true, cancelable: true, clientX: clientX, clientY: clientY}));"
                    +"target.dispatchEvent(new WheelEvent('wheel',     {view: window, bubbles: true, cancelable: true, clientX: clientX, clientY: clientY, deltaY: deltaY}));"
                    +"return;"
                      +"}"
                    +"}";  
    
                  WebElement parent = (WebElement) ((JavascriptExecutor) driver).executeScript("return arguments[0].parentNode;", element);
                  ((JavascriptExecutor) driver).executeScript(script, parent, deltaY, offsetX, offsetY);
                }catch(WebDriverException e)
                {
                System.out.println("Exception caught in Catch block");
                }
        }
    
    }
    
  • 控制台输出:

    Mouse wheel UP or Zoom In through Wheel achieved !!!
    Mouse wheel DOWN or Zoom Out through Wheel achieved !!!
    Mouse Scroll through Wheel achieved !!!
    

参考文献 您可以在以下内容中找到一些相关的详细讨论:


为什么要调用html元素上的
scrollBy
事件,而不是直接在
窗口上调用它?只有当
canvas
元素的父元素具有固定的高度和宽度时,它才会起作用。@DipenShah直接调用窗口在我的情况下不起作用,那么我建议从父元素到父元素,找到宽度和高度小于
canvas
元素本身的父元素。我想这是唯一能让它工作的方法。@DipenShah,我不确定这段代码是否能用于实现预期的目标。这只是为了演示我之前所说的,但是NVM。我尝试了这种方法,但在我正在工作的应用程序的画布上它没有任何作用。