mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
优化点击逻辑
This commit is contained in:
parent
3dfbfb957f
commit
c6273d9bf2
@ -16,6 +16,7 @@ from .._commons.tools import get_usable_path
|
|||||||
from .._commons.web import make_absolute_link, get_ele_txt, format_html, is_js_func, offset_scroll
|
from .._commons.web import make_absolute_link, get_ele_txt, format_html, is_js_func, offset_scroll
|
||||||
from .._units.clicker import Clicker
|
from .._units.clicker import Clicker
|
||||||
from .._units.element_states import ChromiumElementStates, ShadowRootStates
|
from .._units.element_states import ChromiumElementStates, ShadowRootStates
|
||||||
|
from .._units.locations import Locations
|
||||||
from .._units.select_element import SelectElement
|
from .._units.select_element import SelectElement
|
||||||
from .._units.setter import ChromiumElementSetter
|
from .._units.setter import ChromiumElementSetter
|
||||||
from .._units.waiter import ChromiumElementWaiter
|
from .._units.waiter import ChromiumElementWaiter
|
||||||
@ -1438,103 +1439,6 @@ def send_key(ele, modifier, key):
|
|||||||
ele.page.run_cdp('Input.dispatchKeyEvent', **data)
|
ele.page.run_cdp('Input.dispatchKeyEvent', **data)
|
||||||
|
|
||||||
|
|
||||||
class Locations(object):
|
|
||||||
def __init__(self, ele):
|
|
||||||
"""
|
|
||||||
:param ele: ChromiumElement
|
|
||||||
"""
|
|
||||||
self._ele = ele
|
|
||||||
|
|
||||||
@property
|
|
||||||
def location(self):
|
|
||||||
"""返回元素左上角的绝对坐标"""
|
|
||||||
cl = self.viewport_location
|
|
||||||
return self._get_page_coord(cl[0], cl[1])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def midpoint(self):
|
|
||||||
"""返回元素中间点的绝对坐标"""
|
|
||||||
cl = self.viewport_midpoint
|
|
||||||
return self._get_page_coord(cl[0], cl[1])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def click_point(self):
|
|
||||||
"""返回元素接受点击的点的绝对坐标"""
|
|
||||||
cl = self.viewport_click_point
|
|
||||||
return self._get_page_coord(cl[0], cl[1])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def viewport_location(self):
|
|
||||||
"""返回元素左上角在视口中的坐标"""
|
|
||||||
m = self._get_viewport_rect('border')
|
|
||||||
return int(m[0]), int(m[1])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def viewport_midpoint(self):
|
|
||||||
"""返回元素中间点在视口中的坐标"""
|
|
||||||
m = self._get_viewport_rect('border')
|
|
||||||
return int(m[0] + (m[2] - m[0]) // 2), int(m[3] + (m[5] - m[3]) // 2)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def viewport_click_point(self):
|
|
||||||
"""返回元素接受点击的点视口坐标"""
|
|
||||||
m = self._get_viewport_rect('padding')
|
|
||||||
return int(self.viewport_midpoint[0]), int(m[1]) + 3
|
|
||||||
|
|
||||||
@property
|
|
||||||
def screen_location(self):
|
|
||||||
"""返回元素左上角在屏幕上坐标,左上角为(0, 0)"""
|
|
||||||
vx, vy = self._ele.page.rect.viewport_location
|
|
||||||
ex, ey = self.viewport_location
|
|
||||||
pr = self._ele.page.run_js('return window.devicePixelRatio;')
|
|
||||||
return int((vx + ex) * pr), int((ey + vy) * pr)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def screen_midpoint(self):
|
|
||||||
"""返回元素中点在屏幕上坐标,左上角为(0, 0)"""
|
|
||||||
vx, vy = self._ele.page.rect.viewport_location
|
|
||||||
ex, ey = self.viewport_midpoint
|
|
||||||
pr = self._ele.page.run_js('return window.devicePixelRatio;')
|
|
||||||
return int((vx + ex) * pr), int((ey + vy) * pr)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def screen_click_point(self):
|
|
||||||
"""返回元素中点在屏幕上坐标,左上角为(0, 0)"""
|
|
||||||
vx, vy = self._ele.page.rect.viewport_location
|
|
||||||
ex, ey = self.viewport_click_point
|
|
||||||
pr = self._ele.page.run_js('return window.devicePixelRatio;')
|
|
||||||
return int((vx + ex) * pr), int((ey + vy) * pr)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def rect(self):
|
|
||||||
"""返回元素四个角坐标,顺序:坐上、右上、右下、左下,没有大小的元素抛出NoRectError"""
|
|
||||||
vr = self._get_viewport_rect('border')
|
|
||||||
r = self._ele.page.run_cdp_loaded('Page.getLayoutMetrics')['visualViewport']
|
|
||||||
sx = r['pageX']
|
|
||||||
sy = r['pageY']
|
|
||||||
return [(vr[0] + sx, vr[1] + sy), (vr[2] + sx, vr[3] + sy), (vr[4] + sx, vr[5] + sy), (vr[6] + sx, vr[7] + sy)]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def viewport_rect(self):
|
|
||||||
"""返回元素四个角视口坐标,顺序:坐上、右上、右下、左下,没有大小的元素抛出NoRectError"""
|
|
||||||
r = self._get_viewport_rect('border')
|
|
||||||
return [(r[0], r[1]), (r[2], r[3]), (r[4], r[5]), (r[6], r[7])]
|
|
||||||
|
|
||||||
def _get_viewport_rect(self, quad):
|
|
||||||
"""按照类型返回在可视窗口中的范围
|
|
||||||
:param quad: 方框类型,margin border padding
|
|
||||||
:return: 四个角坐标
|
|
||||||
"""
|
|
||||||
return self._ele.page.run_cdp('DOM.getBoxModel', backendNodeId=self._ele.ids.backend_id)['model'][quad]
|
|
||||||
|
|
||||||
def _get_page_coord(self, x, y):
|
|
||||||
"""根据视口坐标获取绝对坐标"""
|
|
||||||
r = self._ele.page.run_cdp_loaded('Page.getLayoutMetrics')['visualViewport']
|
|
||||||
sx = r['pageX']
|
|
||||||
sy = r['pageY']
|
|
||||||
return x + sx, y + sy
|
|
||||||
|
|
||||||
|
|
||||||
class ChromiumScroll(object):
|
class ChromiumScroll(object):
|
||||||
"""用于滚动的对象"""
|
"""用于滚动的对象"""
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
@Contact : g1879@qq.com
|
@Contact : g1879@qq.com
|
||||||
"""
|
"""
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Union, Tuple, List, Any, Optional
|
from typing import Union, Tuple, List, Any
|
||||||
|
|
||||||
from .._base.base import DrissionElement, BaseElement
|
from .._base.base import DrissionElement, BaseElement
|
||||||
from .._commons.constants import NoneElement
|
from .._commons.constants import NoneElement
|
||||||
@ -15,6 +15,7 @@ from .._pages.chromium_page import ChromiumPage
|
|||||||
from .._pages.web_page import WebPage
|
from .._pages.web_page import WebPage
|
||||||
from .._units.clicker import Clicker
|
from .._units.clicker import Clicker
|
||||||
from .._units.element_states import ShadowRootStates, ChromiumElementStates
|
from .._units.element_states import ShadowRootStates, ChromiumElementStates
|
||||||
|
from .._units.locations import Locations
|
||||||
from .._units.select_element import SelectElement
|
from .._units.select_element import SelectElement
|
||||||
from .._units.setter import ChromiumElementSetter
|
from .._units.setter import ChromiumElementSetter
|
||||||
from .._units.waiter import ChromiumElementWaiter
|
from .._units.waiter import ChromiumElementWaiter
|
||||||
@ -363,48 +364,6 @@ def send_enter(ele: ChromiumElement) -> None: ...
|
|||||||
def send_key(ele: ChromiumElement, modifier: int, key: str) -> None: ...
|
def send_key(ele: ChromiumElement, modifier: int, key: str) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
class Locations(object):
|
|
||||||
def __init__(self, ele: ChromiumElement):
|
|
||||||
self._ele: ChromiumElement = ...
|
|
||||||
|
|
||||||
@property
|
|
||||||
def location(self) -> Tuple[int, int]: ...
|
|
||||||
|
|
||||||
@property
|
|
||||||
def midpoint(self) -> Tuple[int, int]: ...
|
|
||||||
|
|
||||||
@property
|
|
||||||
def click_point(self) -> Tuple[int, int]: ...
|
|
||||||
|
|
||||||
@property
|
|
||||||
def viewport_location(self) -> Tuple[int, int]: ...
|
|
||||||
|
|
||||||
@property
|
|
||||||
def viewport_midpoint(self) -> Tuple[int, int]: ...
|
|
||||||
|
|
||||||
@property
|
|
||||||
def viewport_click_point(self) -> Tuple[int, int]: ...
|
|
||||||
|
|
||||||
@property
|
|
||||||
def screen_location(self) -> Tuple[int, int]: ...
|
|
||||||
|
|
||||||
@property
|
|
||||||
def screen_midpoint(self) -> Tuple[int, int]: ...
|
|
||||||
|
|
||||||
@property
|
|
||||||
def screen_click_point(self) -> Tuple[int, int]: ...
|
|
||||||
|
|
||||||
@property
|
|
||||||
def rect(self) -> list: ...
|
|
||||||
|
|
||||||
@property
|
|
||||||
def viewport_rect(self) -> list: ...
|
|
||||||
|
|
||||||
def _get_viewport_rect(self, quad: str) -> Union[list, None]: ...
|
|
||||||
|
|
||||||
def _get_page_coord(self, x: int, y: int) -> Tuple[int, int]: ...
|
|
||||||
|
|
||||||
|
|
||||||
class ChromiumScroll(object):
|
class ChromiumScroll(object):
|
||||||
def __init__(self, page_or_ele: Union[ChromiumBase, ChromiumElement, ChromiumFrame]):
|
def __init__(self, page_or_ele: Union[ChromiumBase, ChromiumElement, ChromiumFrame]):
|
||||||
self.t1: str = ...
|
self.t1: str = ...
|
||||||
|
@ -103,6 +103,11 @@ class ChromiumBase(BasePage):
|
|||||||
self._driver.call_method('Page.enable')
|
self._driver.call_method('Page.enable')
|
||||||
self._driver.call_method('Emulation.setFocusEmulationEnabled', enabled=True)
|
self._driver.call_method('Emulation.setFocusEmulationEnabled', enabled=True)
|
||||||
|
|
||||||
|
r = self.run_cdp('Page.getFrameTree')
|
||||||
|
for i in findall(r"'id': '(.*?)'", str(r)):
|
||||||
|
self.browser._frames[i] = self.tab_id
|
||||||
|
self._frame_id = r['frameTree']['frame']['id']
|
||||||
|
|
||||||
self._driver.set_listener('Page.frameStartedLoading', self._onFrameStartedLoading)
|
self._driver.set_listener('Page.frameStartedLoading', self._onFrameStartedLoading)
|
||||||
self._driver.set_listener('Page.frameNavigated', self._onFrameNavigated)
|
self._driver.set_listener('Page.frameNavigated', self._onFrameNavigated)
|
||||||
self._driver.set_listener('Page.domContentEventFired', self._onDomContentEventFired)
|
self._driver.set_listener('Page.domContentEventFired', self._onDomContentEventFired)
|
||||||
@ -111,10 +116,6 @@ class ChromiumBase(BasePage):
|
|||||||
self._driver.set_listener('Page.frameAttached', self._onFrameAttached)
|
self._driver.set_listener('Page.frameAttached', self._onFrameAttached)
|
||||||
self._driver.set_listener('Page.frameDetached', self._onFrameDetached)
|
self._driver.set_listener('Page.frameDetached', self._onFrameDetached)
|
||||||
|
|
||||||
r = self.run_cdp('Page.getFrameTree')
|
|
||||||
for i in findall(r"'id': '(.*?)'", str(r)):
|
|
||||||
self.browser._frames[i] = self.tab_id
|
|
||||||
self._frame_id = r['frameTree']['frame']['id']
|
|
||||||
|
|
||||||
def _get_document(self):
|
def _get_document(self):
|
||||||
if self._is_reading:
|
if self._is_reading:
|
||||||
|
@ -7,7 +7,7 @@ from time import perf_counter, sleep
|
|||||||
|
|
||||||
from .._commons.constants import Settings
|
from .._commons.constants import Settings
|
||||||
from .._commons.web import offset_scroll
|
from .._commons.web import offset_scroll
|
||||||
from ..errors import CanNotClickError, CDPError
|
from ..errors import CanNotClickError, CDPError, NoRectError
|
||||||
|
|
||||||
|
|
||||||
class Clicker(object):
|
class Clicker(object):
|
||||||
@ -26,7 +26,7 @@ class Clicker(object):
|
|||||||
"""
|
"""
|
||||||
return self.left(by_js, timeout)
|
return self.left(by_js, timeout)
|
||||||
|
|
||||||
def left(self, by_js=False, timeout=1):
|
def left(self, by_js=False, timeout=2):
|
||||||
"""点击元素,可选择是否用js点击
|
"""点击元素,可选择是否用js点击
|
||||||
:param by_js: 是否用js点击,为None时先用模拟点击,遇到遮挡改用js,为True时直接用js点击,为False时只用模拟点击
|
:param by_js: 是否用js点击,为None时先用模拟点击,遇到遮挡改用js,为True时直接用js点击,为False时只用模拟点击
|
||||||
:param timeout: 模拟点击的超时时间,等待元素可见、不被遮挡、进入视口
|
:param timeout: 模拟点击的超时时间,等待元素可见、不被遮挡、进入视口
|
||||||
@ -35,34 +35,48 @@ class Clicker(object):
|
|||||||
if not by_js: # 模拟点击
|
if not by_js: # 模拟点击
|
||||||
can_click = False
|
can_click = False
|
||||||
timeout = self._ele.page.timeout if timeout is None else timeout
|
timeout = self._ele.page.timeout if timeout is None else timeout
|
||||||
if timeout == 0 and self._ele.states.has_rect:
|
rect = None
|
||||||
|
if timeout == 0:
|
||||||
|
try:
|
||||||
self._ele.scroll.to_see()
|
self._ele.scroll.to_see()
|
||||||
if self._ele.states.is_in_viewport and self._ele.states.is_enabled and self._ele.states.is_displayed:
|
if self._ele.states.is_enabled and self._ele.states.is_displayed:
|
||||||
|
rect = self._ele.locations.viewport_rect
|
||||||
can_click = True
|
can_click = True
|
||||||
|
except NoRectError:
|
||||||
|
if by_js is False:
|
||||||
|
raise
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
rect = self._ele.states.has_rect
|
||||||
end_time = perf_counter() + timeout
|
end_time = perf_counter() + timeout
|
||||||
while not self._ele.states.has_rect and perf_counter() < end_time:
|
while not rect and perf_counter() < end_time:
|
||||||
|
rect = self._ele.states.has_rect
|
||||||
sleep(.001)
|
sleep(.001)
|
||||||
if self._ele.states.has_rect:
|
|
||||||
|
self._ele.wait.stop_moving(timeout=end_time - perf_counter())
|
||||||
|
if rect:
|
||||||
self._ele.scroll.to_see()
|
self._ele.scroll.to_see()
|
||||||
|
rect = self._ele.locations.rect
|
||||||
while perf_counter() < end_time:
|
while perf_counter() < end_time:
|
||||||
if (self._ele.states.is_in_viewport and self._ele.states.is_enabled
|
if self._ele.states.is_enabled and self._ele.states.is_displayed:
|
||||||
and self._ele.states.is_displayed):
|
|
||||||
can_click = True
|
can_click = True
|
||||||
break
|
break
|
||||||
sleep(.001)
|
sleep(.001)
|
||||||
|
|
||||||
if not self._ele.states.has_rect or not self._ele.states.is_in_viewport:
|
elif by_js is False:
|
||||||
|
raise NoRectError
|
||||||
|
|
||||||
|
if can_click and not self._ele.states.is_in_viewport:
|
||||||
by_js = True
|
by_js = True
|
||||||
|
|
||||||
elif can_click and (by_js is False or not self._ele.states.is_covered):
|
elif can_click and (by_js is False or not self._ele.states.is_covered):
|
||||||
vx, vy = self._ele.locations.click_point
|
x = int(rect[1][0] - (rect[1][0] - rect[0][0]) / 2)
|
||||||
|
y = rect[0][0] + 3
|
||||||
try:
|
try:
|
||||||
r = self._ele.page.run_cdp('DOM.getNodeForLocation', x=vx, y=vy, includeUserAgentShadowDOM=True,
|
r = self._ele.page.run_cdp('DOM.getNodeForLocation', x=x, y=y, includeUserAgentShadowDOM=True,
|
||||||
ignorePointerEventsNone=True)
|
ignorePointerEventsNone=True)
|
||||||
if r['backendNodeId'] != self._ele.ids.backend_id:
|
if r['backendNodeId'] != self._ele.ids.backend_id:
|
||||||
vx, vy = self._ele.locations.viewport_click_point
|
vx, vy = self._ele.locations.viewport_midpoint
|
||||||
else:
|
else:
|
||||||
vx, vy = self._ele.locations.viewport_click_point
|
vx, vy = self._ele.locations.viewport_click_point
|
||||||
|
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
# -*- coding:utf-8 -*-
|
# -*- coding:utf-8 -*-
|
||||||
|
"""
|
||||||
|
@Author : g1879
|
||||||
|
@Contact : g1879@qq.com
|
||||||
|
"""
|
||||||
from .._commons.web import location_in_viewport
|
from .._commons.web import location_in_viewport
|
||||||
from ..errors import CDPError, NoRectError
|
from ..errors import CDPError, NoRectError
|
||||||
|
|
||||||
@ -71,9 +75,9 @@ class ChromiumElementStates(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def has_rect(self):
|
def has_rect(self):
|
||||||
"""返回元素是否拥有位置和大小,没有返回False,有返回大小元组"""
|
"""返回元素是否拥有位置和大小,没有返回False,有返回四个角在页面中坐标组成的列表"""
|
||||||
try:
|
try:
|
||||||
return self._ele.size
|
return self._ele.locations.rect
|
||||||
except NoRectError:
|
except NoRectError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
# -*- coding:utf-8 -*-
|
# -*- coding:utf-8 -*-
|
||||||
from typing import Union, Tuple
|
"""
|
||||||
|
@Author : g1879
|
||||||
|
@Contact : g1879@qq.com
|
||||||
|
"""
|
||||||
|
from typing import Union, Tuple, List
|
||||||
|
|
||||||
from .._elements.chromium_element import ChromiumShadowRoot, ChromiumElement
|
from .._elements.chromium_element import ChromiumShadowRoot, ChromiumElement
|
||||||
|
|
||||||
@ -33,7 +37,7 @@ class ChromiumElementStates(object):
|
|||||||
def is_covered(self) -> bool: ...
|
def is_covered(self) -> bool: ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def has_rect(self) -> Union[bool, Tuple[int, int]]: ...
|
def has_rect(self) -> Union[bool, List[Tuple[float, float]]]: ...
|
||||||
|
|
||||||
|
|
||||||
class ShadowRootStates(object):
|
class ShadowRootStates(object):
|
||||||
|
103
DrissionPage/_units/locations.py
Normal file
103
DrissionPage/_units/locations.py
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
# -*- coding:utf-8 -*-
|
||||||
|
"""
|
||||||
|
@Author : g1879
|
||||||
|
@Contact : g1879@qq.com
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class Locations(object):
|
||||||
|
def __init__(self, ele):
|
||||||
|
"""
|
||||||
|
:param ele: ChromiumElement
|
||||||
|
"""
|
||||||
|
self._ele = ele
|
||||||
|
|
||||||
|
@property
|
||||||
|
def location(self):
|
||||||
|
"""返回元素左上角的绝对坐标"""
|
||||||
|
cl = self.viewport_location
|
||||||
|
return self._get_page_coord(cl[0], cl[1])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def midpoint(self):
|
||||||
|
"""返回元素中间点的绝对坐标"""
|
||||||
|
cl = self.viewport_midpoint
|
||||||
|
return self._get_page_coord(cl[0], cl[1])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def click_point(self):
|
||||||
|
"""返回元素接受点击的点的绝对坐标"""
|
||||||
|
cl = self.viewport_click_point
|
||||||
|
return self._get_page_coord(cl[0], cl[1])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def viewport_location(self):
|
||||||
|
"""返回元素左上角在视口中的坐标"""
|
||||||
|
m = self._get_viewport_rect('border')
|
||||||
|
return int(m[0]), int(m[1])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def viewport_midpoint(self):
|
||||||
|
"""返回元素中间点在视口中的坐标"""
|
||||||
|
m = self._get_viewport_rect('border')
|
||||||
|
return int(m[0] + (m[2] - m[0]) // 2), int(m[3] + (m[5] - m[3]) // 2)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def viewport_click_point(self):
|
||||||
|
"""返回元素接受点击的点视口坐标"""
|
||||||
|
m = self._get_viewport_rect('padding')
|
||||||
|
return int(self.viewport_midpoint[0]), int(m[1]) + 3
|
||||||
|
|
||||||
|
@property
|
||||||
|
def screen_location(self):
|
||||||
|
"""返回元素左上角在屏幕上坐标,左上角为(0, 0)"""
|
||||||
|
vx, vy = self._ele.page.rect.viewport_location
|
||||||
|
ex, ey = self.viewport_location
|
||||||
|
pr = self._ele.page.run_js('return window.devicePixelRatio;')
|
||||||
|
return int((vx + ex) * pr), int((ey + vy) * pr)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def screen_midpoint(self):
|
||||||
|
"""返回元素中点在屏幕上坐标,左上角为(0, 0)"""
|
||||||
|
vx, vy = self._ele.page.rect.viewport_location
|
||||||
|
ex, ey = self.viewport_midpoint
|
||||||
|
pr = self._ele.page.run_js('return window.devicePixelRatio;')
|
||||||
|
return int((vx + ex) * pr), int((ey + vy) * pr)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def screen_click_point(self):
|
||||||
|
"""返回元素中点在屏幕上坐标,左上角为(0, 0)"""
|
||||||
|
vx, vy = self._ele.page.rect.viewport_location
|
||||||
|
ex, ey = self.viewport_click_point
|
||||||
|
pr = self._ele.page.run_js('return window.devicePixelRatio;')
|
||||||
|
return int((vx + ex) * pr), int((ey + vy) * pr)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rect(self):
|
||||||
|
"""返回元素四个角坐标,顺序:坐上、右上、右下、左下,没有大小的元素抛出NoRectError"""
|
||||||
|
vr = self._get_viewport_rect('border')
|
||||||
|
r = self._ele.page.run_cdp_loaded('Page.getLayoutMetrics')['visualViewport']
|
||||||
|
sx = int(r['pageX'])
|
||||||
|
sy = int(r['pageY'])
|
||||||
|
return [(vr[0] + sx, vr[1] + sy), (vr[2] + sx, vr[3] + sy),
|
||||||
|
(vr[4] + sx, vr[5] + sy), (vr[6] + sx, vr[7] + sy)]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def viewport_rect(self):
|
||||||
|
"""返回元素四个角视口坐标,顺序:坐上、右上、右下、左下,没有大小的元素抛出NoRectError"""
|
||||||
|
r = self._get_viewport_rect('border')
|
||||||
|
return [(int(r[0]), int(r[1])), (int(r[2]), int(r[3])), (int(r[4]), int(r[5])), (int(r[6]), int(r[7]))]
|
||||||
|
|
||||||
|
def _get_viewport_rect(self, quad):
|
||||||
|
"""按照类型返回在可视窗口中的范围
|
||||||
|
:param quad: 方框类型,margin border padding
|
||||||
|
:return: 四个角坐标
|
||||||
|
"""
|
||||||
|
return self._ele.page.run_cdp('DOM.getBoxModel', backendNodeId=self._ele.ids.backend_id)['model'][quad]
|
||||||
|
|
||||||
|
def _get_page_coord(self, x, y):
|
||||||
|
"""根据视口坐标获取绝对坐标"""
|
||||||
|
r = self._ele.page.run_cdp_loaded('Page.getLayoutMetrics')['visualViewport']
|
||||||
|
sx = r['pageX']
|
||||||
|
sy = r['pageY']
|
||||||
|
return x + sx, y + sy
|
50
DrissionPage/_units/locations.pyi
Normal file
50
DrissionPage/_units/locations.pyi
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# -*- coding:utf-8 -*-
|
||||||
|
"""
|
||||||
|
@Author : g1879
|
||||||
|
@Contact : g1879@qq.com
|
||||||
|
"""
|
||||||
|
from typing import Tuple, Union, List
|
||||||
|
|
||||||
|
from .._elements.chromium_element import ChromiumElement
|
||||||
|
|
||||||
|
|
||||||
|
class Locations(object):
|
||||||
|
def __init__(self, ele: ChromiumElement):
|
||||||
|
self._ele: ChromiumElement = ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def location(self) -> Tuple[int, int]: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def midpoint(self) -> Tuple[int, int]: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def click_point(self) -> Tuple[int, int]: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def viewport_location(self) -> Tuple[int, int]: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def viewport_midpoint(self) -> Tuple[int, int]: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def viewport_click_point(self) -> Tuple[int, int]: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def screen_location(self) -> Tuple[int, int]: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def screen_midpoint(self) -> Tuple[int, int]: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def screen_click_point(self) -> Tuple[int, int]: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rect(self) -> List[Tuple[int, int], ...]: ...
|
||||||
|
|
||||||
|
@property
|
||||||
|
def viewport_rect(self) -> List[Tuple[int, int], ...]: ...
|
||||||
|
|
||||||
|
def _get_viewport_rect(self, quad: str) -> Union[list, None]: ...
|
||||||
|
|
||||||
|
def _get_page_coord(self, x: int, y: int) -> Tuple[int, int]: ...
|
Loading…
x
Reference in New Issue
Block a user