Godot 4.3自定义可缩放画布滚动位置同步问题求助
Godot 4.3 画布缩放与滚动条同步问题
约一周前,我尝试在Godot 4.3中实现类似Photoshop、Krita的功能:通过鼠标滚轮围绕光标位置缩放作为画布的TextureRect。目前已实现画布缩放及位置调整,滚动条尺寸也可适配,但始终无法让滚动条位置与画布缩放状态成比例同步。
初始代码
extends Control @onready var canvas: TextureRect = $Canvas @onready var h_scroll_bar: HScrollBar = $HScrollBar @onready var v_scroll_bar: VScrollBar = $VScrollBar var min_zoom = 1.0 var max_zoom = 15.0 var zoom_step = 0.1 var zoom = 1.0 var original_canvas_width: int var original_canvas_height: int func _ready(): original_canvas_width = canvas.size.x original_canvas_height = canvas.size.y # Initialize the scrollbars when the scene starts update_scrollbars() func _input(event): # Handle zooming with mouse wheel if event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_WHEEL_UP: zoom_canvas(event.global_position, zoom_step) elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN: zoom_canvas(event.global_position, -zoom_step) func zoom_canvas(mouse_position: Vector2, zoom_delta: float): var new_zoom = clamp(zoom + zoom_delta, min_zoom, max_zoom) ifif new_zoom == zoom: return var scale_factor = new_zoom / zoom zoom = new_zoom # Calculate the new scale var old_size = canvas.size var new_size = old_size * scale_factor # Adjust the position so that zooming centers around the mouse var offset = mouse_position - canvas.position var zoom_offset = offset * (1 - scale_factor) canvas.size = new_size canvas.position += zoom_offset # Update scrollbars update_scrollbars() func update_scrollbars(): var canvas_size_x_ratio: float = (original_canvas_width/ size.x) var canvas_size_y_ratio: float = (original_canvas_height/ size.y) h_scroll_bar.page = ( canvas_size_x_ratio / zoom ) * h_scroll_bar.max_value v_scroll_bar.page = ( canvas_size_y_ratio / zoom ) * v_scroll_bar.max_value var x = 0.5 var y = 0.5 h_scroll_bar.value = (h_scroll_bar.max_value-h_scroll_bar.page) - (x * (h_scroll_bar.max_value-h_scroll_bar.page)) v_scroll_bar.value = (v_scroll_bar.max_value-v_scroll_bar.page) - (y * (v_scroll_bar.max_value-v_scroll_bar.page))
我认为滚动条value的计算公式逻辑正确,但需找到合适的x、y相对值使滚动条位置与缩放位置匹配。
更新:新增代码元素
extends Control @onready var canvas: TextureRect = $Canvas @onready var h_scroll_bar: HScrollBar = $HScrollBar @onready var v_scroll_bar: VScrollBar = $VScrollBar var min_zoom = 1.0 var max_zoom = 15.0 var zoom_step = 0.1 var zoom = 1.0 var original_canvas_width: int var original_canvas_height: int var virtual_space_h: int var virtual_space_v: int var virtual_space_pos: Vector2 var last_mouse_pos: Vector2 = Vector2.ZERO # Store the last mouse position #var last_mouse_pos: Vector2 = Vector2(size.x/2, size.y/2) # Store the last mouse position func _ready(): original_canvas_width = canvas.size.x original_canvas_height = canvas.size.y virtual_space_h = size.x virtual_space_v = size.y virtual_space_pos = Vector2(0,0) update_scrollbars() func _input(event): if event is InputEventMouseButton: if event.button_index == MOUSE_BUTTON_WHEEL_UP: zoom_canvas(event.global_position, zoom_step) elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN: zoom_canvas(event.global_position, -zoom_step) func zoom_canvas(mouse_position: Vector2, zoom_delta: float): var new_zoom = clamp(zoom + zoom_delta, min_zoom, max_zoom) if new_zoom == zoom: return var scale_factor = new_zoom / zoom zoom = new_zoom # Get mouse position relative to canvas before scaling var mouse_offset = mouse_position - canvas.position var old_size = canvas.size var old_space = size var new_size = old_size * scale_factor var new_space = old_space * scale_factor # Adjust the position based on zoom around the mouse cursor var zoom_offset = mouse_offset * (1 - scale_factor) canvas.size = new_size canvas.position += zoom_offset virtual_space_h = new_space.x virtual_space_v = new_space.y virtual_space_pos += zoom_offset # Update the scrollbars to match the new canvas size and zoom update_scrollbars() # Store the last mouse position (relative to the canvas) last_mouse_pos = mouse_position func update_scrollbars(): # Calculate the ratio of the canvas size relative to the control size var canvas_size_x_ratio: float = (original_canvas_width / size.x) var canvas_size_y_ratio: float = (original_canvas_height / size.y) # Update the scrollbar page values based on zoom level h_scroll_bar.page = (canvas_size_x_ratio / zoom) * h_scroll_bar.max_value v_scroll_bar.page = (canvas_size_y_ratio / zoom) * v_scroll_bar.max_value # Calculate the relative position adjustments based on the last mouse position #var x = (last_mouse_pos.x - canvas.position.x) / canvas.size.x #var y = (last_mouse_pos.y - canvas.position.y) / canvas.size.y var x = (last_mouse_pos.x - virtual_space_pos.x) / virtual_space_h var y = (last_mouse_pos.y - virtual_space_pos.y) / virtual_space_v # Update the scrollbar values based on mouse position relative to canvas h_scroll_bar.value = (h_scroll_bar.max_value - h_scroll_bar.page) - (x * (h_scroll_bar.max_value - h_scroll_bar.page)) v_scroll_bar.value = (v_scroll_bar.max_value - v_scroll_bar.page) - (y * (v_scroll_bar.max_value - v_scroll_bar.page))
目前围绕鼠标位置缩放画布的功能流畅可用,但滚动条仍无法与画布状态良好同步,寻求解决方法。
内容的提问来源于stack exchange,提问作者New developer
相关产品推荐
相关产品推荐

