Zoom y paneo
Arrastra para mover y gira la rueda para hacer zoom en el puntero en vez del centro de la pantalla, que son dos líneas de matemáticas sobre Camera2D.zoom.
El editor de arriba está ejecutando este proyecto. Cambia una línea y se recarga.
Clases de Godot usadas
Camera2DInputEventMouseButtonLine2D
El código
scripts/main.gd
extends Node
const CELL: float = 120.0
const HALF: Vector2 = Vector2(1200, 960)
const MIN_ZOOM: Vector2 = Vector2(0.35, 0.35)
const MAX_ZOOM: Vector2 = Vector2(3.0, 3.0)
var camera: Camera2D
var readout: Label
var elapsed: float = 0.0
var manual: bool = false
func _ready() -> void:
_add_background()
_add_grid()
_add_landmarks()
camera = Camera2D.new()
add_child(camera)
camera.make_current()
_add_hud()
print('drag with the left button to pan, use the wheel to zoom at the pointer')
func _process(delta: float) -> void:
elapsed += delta
if not manual:
camera.position = Vector2(sin(elapsed * 0.5) * 520.0, sin(elapsed * 0.31) * 320.0)
camera.zoom = Vector2.ONE * (0.95 + 0.45 * sin(elapsed * 0.7))
readout.text = 'zoom %.2f camera %d, %d' % [camera.zoom.x, camera.position.x, camera.position.y]
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventMouseButton and event.pressed:
var button: InputEventMouseButton = event as InputEventMouseButton
if button.button_index == MOUSE_BUTTON_WHEEL_UP:
_zoom_at(button.position, 1.12)
elif button.button_index == MOUSE_BUTTON_WHEEL_DOWN:
_zoom_at(button.position, 1.0 / 1.12)
elif event is InputEventMouseMotion:
var motion: InputEventMouseMotion = event as InputEventMouseMotion
if motion.button_mask & MOUSE_BUTTON_MASK_LEFT:
manual = true
camera.position -= motion.relative / camera.zoom
func _zoom_at(screen_point: Vector2, factor: float) -> void:
manual = true
var view: Vector2 = get_viewport().get_visible_rect().size
var before: Vector2 = camera.position + (screen_point - view * 0.5) / camera.zoom
camera.zoom = (camera.zoom * factor).clamp(MIN_ZOOM, MAX_ZOOM)
camera.position = before - (screen_point - view * 0.5) / camera.zoom
func _add_grid() -> void:
var x: float = -HALF.x
while x <= HALF.x:
var accent: bool = is_zero_approx(x)
_add_line(Vector2(x, -HALF.y), Vector2(x, HALF.y), 6.0 if accent else 2.0, Color('#8da5f3') if accent else Color('#2a2f3d'))
x += CELL
var y: float = -HALF.y
while y <= HALF.y:
var accent: bool = is_zero_approx(y)
_add_line(Vector2(-HALF.x, y), Vector2(HALF.x, y), 6.0 if accent else 2.0, Color('#8da5f3') if accent else Color('#2a2f3d'))
y += CELL
func _add_landmarks() -> void:
var colors: Array[Color] = [Color('#8eef97'), Color('#fc7f7f'), Color('#f3d48d'), Color('#8da5f3')]
var rng: RandomNumberGenerator = RandomNumberGenerator.new()
rng.seed = 11
for row in 8:
for column in 10:
var size: float = rng.randf_range(34, 78)
var block: Polygon2D = Polygon2D.new()
block.polygon = PackedVector2Array([Vector2(-size, -size) * 0.5, Vector2(size, -size) * 0.5, Vector2(size, size) * 0.5, Vector2(-size, size) * 0.5])
block.color = colors[(row + column) % colors.size()]
block.position = Vector2(-1080 + column * 240, -840 + row * 240)
block.rotation = rng.randf_range(-0.4, 0.4)
add_child(block)
var origin: Label = Label.new()
origin.text = '0, 0'
origin.add_theme_font_size_override('font_size', 28)
origin.add_theme_color_override('font_color', Color('#8da5f3'))
origin.position = Vector2(14, 6)
add_child(origin)
func _add_line(from: Vector2, to: Vector2, width: float, color: Color) -> void:
var line: Line2D = Line2D.new()
line.points = PackedVector2Array([from, to])
line.width = width
line.default_color = color
add_child(line)
func _add_hud() -> void:
var hud: CanvasLayer = CanvasLayer.new()
add_child(hud)
var title: Label = Label.new()
title.text = 'drag to pan, wheel to zoom at the pointer'
title.add_theme_font_size_override('font_size', 22)
title.add_theme_color_override('font_color', Color('#8eef97'))
title.position = Vector2(40, 34)
hud.add_child(title)
readout = Label.new()
readout.add_theme_font_size_override('font_size', 20)
readout.add_theme_color_override('font_color', Color('#f3d48d'))
readout.position = Vector2(40, 66)
hud.add_child(readout)
func _add_background() -> void:
var layer: CanvasLayer = CanvasLayer.new()
layer.layer = -1
add_child(layer)
var background: ColorRect = ColorRect.new()
background.color = Color('#12141a')
layer.add_child(background)
# ColorRect defaults to MOUSE_FILTER_STOP and would eat the click before _unhandled_input
background.mouse_filter = Control.MOUSE_FILTER_IGNORE
background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)