@@ -240,24 +240,59 @@ def set_attr(self, attr: str, value: str) -> bool:
240
240
except :
241
241
raise
242
242
243
- def drag_to (self , ele_or_loc : Union [tuple , WebElement , DrissionElement ]) -> bool :
243
+ def drag (self , x : int , y : int , speed : int = 40 , shake : bool = True ) -> bool :
244
+ """拖拽当前元素到相对位置
245
+ :param x: x变化值
246
+ :param y: y变化值
247
+ :param speed: 速度
248
+ :param shake: 是否随机抖动
249
+ :return: 是否推拽成功
250
+ """
251
+ x += self .location ['x' ] + self .size ['width' ] // 2
252
+ y += self .location ['y' ] + self .size ['height' ] // 2
253
+ return self .drag_to ((x , y ), speed , shake )
254
+
255
+ def drag_to (self ,
256
+ ele_or_loc : Union [tuple , WebElement , DrissionElement ],
257
+ speed : int = 40 ,
258
+ shake : bool = True ) -> bool :
244
259
"""拖拽当前元素,目标为另一个元素或坐标元组
245
- :param ele_or_loc: 另一个元素或相对当前位置
260
+ :param ele_or_loc: 另一个元素或坐标元组,坐标为元素中点的坐标
261
+ :param speed: 拖动的速度,默认为None即瞬间到达
262
+ :param shake: 是否随机抖动
246
263
:return: 是否拖拽成功
247
264
"""
248
- from selenium .webdriver import ActionChains
249
- loc1 = self .location
250
- actions = ActionChains (self ._driver )
251
-
252
- if isinstance (ele_or_loc , DriverElement ):
253
- actions .drag_and_drop (self .inner_ele , ele_or_loc .inner_ele )
254
- elif isinstance (ele_or_loc , WebElement ):
255
- actions .drag_and_drop (self .inner_ele , ele_or_loc )
265
+ # x, y:目标坐标点
266
+ if isinstance (ele_or_loc , DriverElement ) or isinstance (ele_or_loc , WebElement ):
267
+ target_x = ele_or_loc .location ['x' ] + ele_or_loc .size ['width' ] // 2
268
+ target_y = ele_or_loc .location ['y' ] + ele_or_loc .size ['height' ] // 2
256
269
elif isinstance (ele_or_loc , tuple ):
257
- actions . drag_and_drop_by_offset ( self . inner_ele , ele_or_loc [ 0 ], ele_or_loc [ 1 ])
270
+ target_x , target_y = ele_or_loc
258
271
else :
259
- raise KeyError ('Need WebElement object or coordinate information.' )
260
- actions .perform ()
272
+ raise KeyError ('Need DriverElement, WebElement object or coordinate information.' )
273
+
274
+ current_x = self .location ['x' ] + self .size ['width' ] // 2
275
+ current_y = self .location ['y' ] + self .size ['height' ] // 2
276
+ width = target_x - current_x
277
+ height = target_y - current_y
278
+ num = 0 if not speed else int (((abs (width ) ** 2 + abs (height ) ** 2 ) ** .5 ) // speed )
279
+ points = [(int (current_x + i * (width / num )), int (current_y + i * (height / num ))) for i in range (1 , num )]
280
+ points .append ((target_x , target_y ))
281
+
282
+ from selenium .webdriver import ActionChains
283
+ from random import randint
284
+ actions = ActionChains (self .driver )
285
+ loc1 = self .location
286
+ for x , y in points :
287
+ if shake :
288
+ x += randint (- 3 , 4 )
289
+ y += randint (- 3 , 4 )
290
+ dx = x - current_x
291
+ dy = y - current_y
292
+ actions .drag_and_drop_by_offset (self .inner_ele , dx , dy )
293
+ current_x , current_y = x , y
294
+
295
+ actions .release ().perform ()
261
296
loc2 = self .location
262
297
if loc1 == loc2 :
263
298
return False
0 commit comments