Skip to content

Instantly share code, notes, and snippets.

@kived
Created May 27, 2015 18:06
Show Gist options
  • Save kived/f44ae8f47fb71681aced to your computer and use it in GitHub Desktop.
Save kived/f44ae8f47fb71681aced to your computer and use it in GitHub Desktop.
Kivy: PinchLabel font resize
import kivy
kivy.require('1.9.0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.vector import Vector
from kivy.properties import BoundedNumericProperty
class PinchLabel(Label):
font_size_min = BoundedNumericProperty(2, min=0)
font_size_max = BoundedNumericProperty(1e100, min=0)
def __init__(self, **kwargs):
super(PinchLabel, self).__init__(**kwargs)
self._touches = []
self._last_touch_pos = {}
def on_touch_down(self, touch):
if not self.collide_point(*touch.pos):
return
if 'multitouch_sim' in touch.profile:
touch.multitouch_sim = True
touch.grab(self)
self._touches.append(touch)
self._last_touch_pos[touch] = touch.pos
return True
def on_touch_move(self, touch):
if touch in self._touches and touch.grab_current == self:
self.scale_with_touch(touch)
self._last_touch_pos[touch] = touch.pos
if self.collide_point(*touch.pos):
return True
def on_touch_up(self, touch):
if touch in self._touches and touch.grab_state:
touch.ungrab(self)
del self._last_touch_pos[touch]
self._touches.remove(touch)
if self.collide_point(*touch.pos):
return True
def scale_with_touch(self, touch):
if len(self._touches) == 1:
return False
points = [Vector(self._last_touch_pos[t]) for t in self._touches if t is not touch]
points.append(Vector(touch.pos))
anchor = max(points[:-1], key=lambda p: p.distance(touch.pos))
farthest = max(points, key=anchor.distance)
if farthest is not points[-1]:
return False
old_line = Vector(*touch.ppos) - anchor
new_line = Vector(*touch.pos) - anchor
if not old_line.length():
return False
scale = new_line.length() / old_line.length()
new_scale = scale * self.font_size
new_scale = min(self.font_size_max, max(self.font_size_min, new_scale))
self.font_size = new_scale
return True
root = Builder.load_string('''
<PinchLabel>:
size_hint: None, None
size: self.texture_size
FloatLayout:
PinchLabel:
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
text: 'hello!'
''')
class TestApp(App):
def build(self):
return root
if __name__ == '__main__':
TestApp().run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment