0 votes

Hi, Is there any algorithm or example for pinch zoom?

in Engine by (19 points)
edited by

3 Answers

0 votes
Best answer

this works for pinch and pan:

extends Camera2D
var first_distance =0
var events={}
var percision = 10
var current_zoom
var maximum_zoomin = Vector2(0.5,0.5)
var minimum_zoomout = Vector2(3,3)
var center
func _ready():
    set_process_unhandled_input(true)
    pass

func is_zooming():
    return events.size()>1

func dist():
    var first_event =null
    var result 
    for event in events:
        if first_event!=null:
            result = events[event].pos.distance_to(first_event.pos)
            break
        first_event = events[event]
    return result

func center():
    var first_event =null
    var result 
    for event in events:
        if first_event!=null:
            result = (map_pos(events[event].pos) + map_pos(first_event))/2
            break
        first_event = events[event].pos
    return result

func map_pos(pos):
    var mtx = get_viewport().get_canvas_transform()
    var mt = mtx.affine_inverse()
    var p = mt.xform(pos)
    return p 
func _unhandled_input(event):

    if event.type == InputEvent.SCREEN_TOUCH and event.is_pressed():
        events[event.index]=event

        if events.size()>1:
            current_zoom=get_zoom()
            first_distance = dist()
            center = center()
    elif event.type == InputEvent.SCREEN_TOUCH and not event.is_pressed():
        events.erase(event.index)
    elif event.type == InputEvent.SCREEN_DRAG :
        events[event.index] = event

        if events.size()>1:
            var second_distance = dist()
            if abs(first_distance-second_distance)>percision:
                var new_zoom =Vector2(first_distance/second_distance,first_distance/second_distance)
                var zoom = new_zoom*current_zoom
                if zoom<minimum_zoomout and zoom>maximum_zoomin:
                    set_zoom(zoom)
                elif zoom>minimum_zoomout:
                    set_zoom(minimum_zoomout)
                elif zoom<maximum_zoomin:
                    set_zoom(maximum_zoomin)
                set_global_pos(center)
        elif events.size()==1:
            set_global_pos(get_global_pos()-event.relative_pos*get_zoom()*2)
by (19 points)

Thx for your example. I had some errors In Godot 3.2.2

I tried to update your code.

extends Camera2D

var first_distance =0
var events={}
var percision = 10
var current_zoom
var maximum_zoomin = Vector2(0.5,0.5)
var minimum_zoomout = Vector2(3,3)
var center

func _ready():
    set_process_unhandled_input(true)
    pass

func is_zooming():
    return events.size()>1

func dist():
    var first_event =null
    var result 
    for event in events:
        if first_event!=null:
            result = events[event].get_position().distance_to(first_event.get_position())
            break
        first_event = events[event]
    return result

func centerino():
    var first_event =null
    var result 
    for event in events:
        if first_event!=null:
            result = (map_pos(events[event].get_position()) + map_pos(first_event))/2
            break
        first_event = events[event].get_position()
    return result

func map_pos(pos):
    var mtx = get_viewport().get_canvas_transform()
    var mt = mtx.affine_inverse()
    var p = mt.xform(pos)
    return p 
func _unhandled_input(event):
        if event is InputEventScreenTouch and event.is_pressed():
            events[event.index]=event

            if events.size()>1:
                current_zoom=get_zoom()
                first_distance = dist()
                center = centerino()
        elif event is InputEventScreenTouch and not event.is_pressed():
            events.erase(event.index)
        elif event is InputEventScreenDrag :
            events[event.index] = event

            if events.size()>1:
                var second_distance = dist()
                if abs(first_distance-second_distance)>percision:
                    var new_zoom =Vector2(first_distance/second_distance,first_distance/second_distance)
                    var zoom = new_zoom*current_zoom
                    if zoom<minimum_zoomout and zoom>maximum_zoomin:
                        set_zoom(zoom)
                    elif zoom>minimum_zoomout:
                        set_zoom(minimum_zoomout)
                    elif zoom<maximum_zoomin:
                        set_zoom(maximum_zoomin)
                    set_global_position(center)
            elif events.size()==1:
                set_global_position(get_global_position()-event.get_relative()*get_zoom()*2)
0 votes

This isn't as simple in godot as everyone would like it to be, but you can find some examples that kinda work on this thread: http://godotdevelopers.org/index.php?topic=3931.msg3952#msg3952

by (54 points)
0 votes

For anyone running across this question nowadays, I'd highly recommend the tutorial at https://kidscancode.org/godot_recipes/2d/touchscreen_camera/ :)

by (14 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.