Skip to content
Advertisement

How to zoom on a particular point with Kivy in python

So I need to create an interactive game map for other players. They could add some markers on it locally.

I imported the image of the map and saw a stackoverflow subject with someone having the same problem. I got the solution but it’s zooming at the center of the picture.

It’s a very large picture so i need to make the zoom possible on the cursor of the mouse.

Here’s the code I’ve already made :

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scatterlayout import ScatterLayout
from kivy.uix.scatter import Scatter
from kivy.core.window import Window
from kivy.graphics.transformation import Matrix
from kivy.lang import Builder

Builder.load_file('map.kv')

class Zoom(ScatterLayout):

    def on_touch_down(self, touch):
        x, y = touch.x, touch.y
        self.prev_x = touch.x
        self.prev_y = touch.y

        if touch.is_mouse_scrolling:
            if touch.button == 'scrolldown':
                print('down')
                ## zoom in
                if self.scale < 10:
                    self.scale = self.scale * 1.1

            elif touch.button == 'scrollup':
                print('up')  ## zoom out
                if self.scale > 1:
                    self.scale = self.scale * 0.9

        # if the touch isn't on the widget we do nothing
        if not self.do_collide_after_children:
            if not self.collide_point(x, y):
                return False

        if 'multitouch_sim' in touch.profile:
            touch.multitouch_sim = True
        # grab the touch so we get all it later move events for sure
        self._bring_to_front(touch)
        touch.grab(self)
        self._touches.append(touch)
        self._last_touch_pos[touch] = touch.pos

        return True


class Main_app(BoxLayout):
    pass


class Stacked(App):
    def build(self):
        Window.clearcolor = (1, 1, 1, 1)
        Window.size = (1000, 700)

Advertisement

Answer

Seems like that should be an option for Scatter and ScatterPlane, but it isn’t. Here is a hack I have used to accomplish what you asked about:

class MyScatterPlane(ScatterPlane):
    def on_touch_up(self, touch):
        if self.collide_point(*touch.pos):
            if touch.is_mouse_scrolling:
                if touch.button == 'scrolldown':
                    mat = Matrix().scale(.9, .9, .9)
                    self.apply_transform(mat, anchor=touch.pos)
                elif touch.button == 'scrollup':
                    mat = Matrix().scale(1.1, 1.1, 1.1)
                    self.apply_transform(mat, anchor=touch.pos)
        return super().on_touch_up(touch)

This is an extension of ScatterPlane, but it is not extensively tested. Use at your own risk.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement