python-lottie  0.6.10+dev2509936
A framework to work with lottie files and telegram animated stickers (tgs)
properties.py
Go to the documentation of this file.
1 import math
2 from functools import reduce
3 from .base import LottieObject, LottieProp, PseudoList, PseudoBool
4 from . import easing
5 from ..nvector import NVector
6 from .bezier import Bezier
7 from ..utils.color import Color
8 
9 
11  NEWTON_ITERATIONS = 4
12  NEWTON_MIN_SLOPE = 0.001
13  SUBDIVISION_PRECISION = 0.0000001
14  SUBDIVISION_MAX_ITERATIONS = 10
15  SPLINE_TABLE_SIZE = 11
16  SAMPLE_STEP_SIZE = 1.0 / (SPLINE_TABLE_SIZE - 1.0)
17 
18  def __init__(self, h1, h2):
19  self.h1 = h1
20  self.h2 = h2
21  self._sample_values = None
22 
23  @classmethod
24  def from_keyframe(cls, keyframe):
25  return cls(keyframe.out_value, keyframe.in_value)
26 
27  def bezier(self):
28  bez = Bezier()
29  bez.add_point(NVector(0, 0), outp=NVector(self.h1.x, self.h1.y))
30  bez.add_point(NVector(1, 1), inp=NVector(self.h2.x-1, self.h2.y-1))
31  return bez
32 
33  def _a(self, c1, c2):
34  return 1 - 3 * c2 + 3 * c1
35 
36  def _b(self, c1, c2):
37  return 3 * c2 - 6 * c1
38 
39  def _c(self, c1):
40  return 3 * c1
41 
42  def _bezier_component(self, t, c1, c2):
43  return ((self._a(c1, c2) * t + self._b(c1, c2)) * t + self._c(c1)) * t
44 
45  def point_at(self, t):
46  return NVector(
47  self._bezier_component(t, self.h1.x, self.h2.x),
48  self._bezier_component(t, self.h1.y, self.h2.y)
49  )
50 
51  def _slope_component(self, t, c1, c2):
52  return 3 * self._a(c1, c2) * t * t + 2 * self._b(c1, c2) * t + self._c(c1)
53 
54  def slope_at(self, t):
55  return NVector(
56  self._slope_component(t, self.h1.x, self.h2.x),
57  self._slope_component(t, self.h1.y, self.h2.y)
58  )
59 
60  def _binary_subdivide(self, x, interval_start, interval_end):
61  current_x = None
62  t = None
63  i = 0
64  for i in range(self.SUBDIVISION_MAX_ITERATIONS):
65  if current_x is not None and abs(current_x) < self.SUBDIVISION_PRECISION:
66  break
67  t = interval_start + (interval_end - interval_start) / 2.0
68  current_x = self._bezier_component(t, self.h1.x, self.h2.x) - x
69  if current_x > 0.0:
70  interval_end = t
71  else:
72  interval_start = t
73  return t
74 
75  def _newton_raphson(self, x, t_guess):
76  for i in range(self.NEWTON_ITERATIONS):
77  slope = self._slope_component(t_guess, self.h1.x, self.h2.x)
78  if slope == 0:
79  return t_guess
80  current_x = self._bezier_component(t_guess, self.h1.x, self.h2.x) - x
81  t_guess -= current_x / slope
82  return t_guess
83 
84  def _get_sample_values(self):
85  if self._sample_values is None:
86  self._sample_values = [
87  self._bezier_component(i * self.SAMPLE_STEP_SIZE, self.h1.x, self.h2.x)
88  for i in range(self.SPLINE_TABLE_SIZE)
89  ]
90  return self._sample_values
91 
92  def t_for_x(self, x):
93  sample_values = self._get_sample_values()
94  interval_start = 0
95  current_sample = 1
96  last_sample = self.SPLINE_TABLE_SIZE - 1
97  while current_sample != last_sample and sample_values[current_sample] <= x:
98  interval_start += self.SAMPLE_STEP_SIZE
99  current_sample += 1
100  current_sample -= 1
101 
102  dist = (x - sample_values[current_sample]) / (sample_values[current_sample+1] - sample_values[current_sample])
103  t_guess = interval_start + dist * self.SAMPLE_STEP_SIZE
104  initial_slope = self._slope_component(t_guess, self.h1.x, self.h2.x)
105  if initial_slope >= self.NEWTON_MIN_SLOPE:
106  return self._newton_raphson(x, t_guess)
107  if initial_slope == 0:
108  return t_guess
109  return self._binary_subdivide(x, interval_start, interval_start + self.SAMPLE_STEP_SIZE)
110 
111  def y_at_x(self, x):
112  t = self.t_for_x(x)
113  return self._bezier_component(t, self.h1.y, self.h2.y)
114 
115 
116 ## @ingroup Lottie
118  _props = [
119  LottieProp("time", "t", float, False),
120  LottieProp("in_value", "i", easing.KeyframeBezierHandle, False),
121  LottieProp("out_value", "o", easing.KeyframeBezierHandle, False),
122  LottieProp("jump", "h", PseudoBool),
123  ]
124 
125  def __init__(self, time=0, easing_function=None):
126  """!
127  @param time Start time of keyframe segment
128  @param easing_function Callable that performs the easing
129  """
130  ## Start time of keyframe segment.
131  self.time = time
132  ## Bezier curve easing in value.
133  self.in_value = None
134  ## Bezier curve easing out value.
135  self.out_value = None
136  ## Jump to the end value
137  self.jump = None
138 
139  if easing_function:
140  easing_function(self)
141 
142  def bezier(self):
143  if self.jump:
144  bez = Bezier()
145  bez.add_point(NVector(0, 0))
146  bez.add_point(NVector(1, 0))
147  bez.add_point(NVector(1, 1))
148  return bez
149  else:
150  return KeyframeBezier.from_keyframe(self).bezier()
151 
152  def lerp_factor(self, ratio):
153  return KeyframeBezier.from_keyframe(self).y_at_x(ratio)
154 
155  def __str__(self):
156  return "%s %s" % (self.time, self.start)
157 
158 
159 ## @ingroup Lottie
161  """!
162  Keyframe for MultiDimensional values
163 
164  @par Bezier easing
165  @parblock
166  Imagine a quadratic bezier, with starting point at (0, 0) and end point at (1, 1).
167 
168  @p out_value and @p in_value are the other two handles for a quadratic bezier,
169  expressed as absolute values in this 0-1 space.
170 
171  See also https://cubic-bezier.com/
172  @endparblock
173  """
174  _props = [
175  LottieProp("start", "s", NVector, False),
176  LottieProp("end", "e", NVector, False),
177  LottieProp("in_tan", "ti", NVector, False),
178  LottieProp("out_tan", "to", NVector, False),
179  ]
180 
181  def __init__(self, time=0, start=None, end=None, easing_function=None, in_tan=None, out_tan=None):
182  Keyframe.__init__(self, time, easing_function)
183  ## Start value of keyframe segment.
184  self.start = start
185  ## End value of keyframe segment.
186  self.end = end
187  ## In Spatial Tangent. Only for spatial properties. (for bezier smoothing on position)
188  self.in_tan = in_tan
189  ## Out Spatial Tangent. Only for spatial properties. (for bezier smoothing on position)
190  self.out_tan = out_tan
191 
192  def interpolated_value(self, ratio, next_start=None):
193  end = next_start if self.end is None else self.end
194  if end is None:
195  return self.start
196  if not self.in_value or not self.out_value:
197  return self.start
198  if ratio == 1:
199  return end
200  if ratio == 0:
201  return self.start
202  if self.in_tan and self.out_tan:
203  bezier = Bezier()
204  bezier.add_point(self.start, NVector(0, 0), self.out_tan)
205  bezier.add_point(end, self.in_tan, NVector(0, 0))
206  return bezier.point_at(ratio)
207 
208  lerpv = self.lerp_factor(ratio)
209  return self.start.lerp(end, lerpv)
210 
211  def interpolated_tangent_angle(self, ratio, next_start=None):
212  end = next_start if self.end is None else self.end
213  if end is None or not self.in_tan or not self.out_tan:
214  return 0
215 
216  bezier = Bezier()
217  bezier.add_point(self.start, NVector(0, 0), self.out_tan)
218  bezier.add_point(end, self.in_tan, NVector(0, 0))
219  return bezier.tangent_angle_at(ratio)
220 
221  def __repr__(self):
222  return "<%s.%s %s %s%s>" % (
223  type(self).__module__,
224  type(self).__name__,
225  self.time,
226  self.start,
227  (" -> %s" % self.end) if self.end is not None else ""
228  )
229 
230 
232  keyframe_type = Keyframe
233 
234  def __init__(self, value=None):
235  ## Non-animated value
236  self.value = value
237  ## Property index
238  self.property_index = None
239  ## Whether it's animated
240  self.animated = False
241  ## Keyframe list
242  self.keyframes = None
243 
244  def clear_animation(self, value):
245  """!
246  Sets a fixed value, removing animated keyframes
247  """
248  self.value = value
249  self.animated = False
250  self.keyframes = None
251 
252  def add_keyframe(self, time, value, interp=easing.Linear(), *args, **kwargs):
253  """!
254  @param time The time this keyframe appears in
255  @param value The value the property should have at @p time
256  @param interp The easing callable used to update the tangents of the previous keyframe
257  @param args Extra arguments to pass the keyframe constructor
258  @param kwargs Extra arguments to pass the keyframe constructor
259  @note Always call add_keyframe with increasing @p time value
260  """
261  if not self.animated:
262  self.value = None
263  self.keyframes = []
264  self.animated = True
265  else:
266  if self.keyframes[-1].time == time:
267  if value != self.keyframes[-1].start:
268  self.keyframes[-1].start = value
269  return
270  else:
271  self.keyframes[-1].end = value.clone()
272 
273  self.keyframes.append(self.keyframe_type(
274  time,
275  value,
276  None,
277  interp,
278  *args,
279  **kwargs
280  ))
281 
282  def get_value(self, time=0):
283  """!
284  @brief Returns the value of the property at the given frame/time
285  """
286  if not self.animated:
287  return self.value
288 
289  if not self.keyframes:
290  return None
291 
292  return self._get_value_helper(time)[0]
293 
294  def _get_value_helper(self, time):
295  val = self.keyframes[0].start
296  for i in range(len(self.keyframes)):
297  k = self.keyframes[i]
298  if time - k.time <= 0:
299  if k.start is not None:
300  val = k.start
301 
302  kp = self.keyframes[i-1] if i > 0 else None
303  if kp:
304  t = (time - kp.time) / (k.time - kp.time)
305  end = kp.end
306  if end is None:
307  end = val
308  if end is not None:
309  val = kp.interpolated_value(t, end)
310  return val, end, kp, t
311  return val, None, None, None
312  if k.end is not None:
313  val = k.end
314  return val, None, None, None
315 
316  def to_dict(self):
317  d = super().to_dict()
318  if self.animated:
319  if "k" not in d:
320  return d
321  last = d["k"][-1]
322  last.pop("i", None)
323  last.pop("o", None)
324  return d
325 
326  def __repr__(self):
327  if self.keyframes and len(self.keyframes) > 1:
328  val = "%s -> %s" % (self.keyframes[0].start, self.keyframes[-2].end)
329  else:
330  val = self.value
331  return "<%s.%s %s>" % (type(self).__module__, type(self).__name__, val)
332 
333  def __str__(self):
334  if self.animated:
335  return "animated"
336  return str(self.value)
337 
338  @classmethod
339  def merge_keyframes(cls, items, conversion):
340  """
341  @todo Remove similar functionality from SVG/sif parsers
342  """
343  keyframes = []
344  for animatable in items:
345  if animatable.animated:
346  keyframes.extend(animatable.keyframes)
347 
348  # TODO properly interpolate tangents
349  new_kframes = []
350  for keyframe in sorted(keyframes, key=lambda kf: kf.time):
351  if new_kframes and new_kframes[-1].time == keyframe.time:
352  continue
353  kfcopy = keyframe.clone()
354  kfcopy.start = conversion(*(i.get_value(keyframe.time) for i in items))
355  new_kframes.append(kfcopy)
356 
357  for i in range(0, len(new_kframes) - 1):
358  new_kframes[i].end = new_kframes[i+1].start
359 
360  return new_kframes
361 
362  @classmethod
363  def load(cls, lottiedict):
364  obj = super().load(lottiedict)
365  if "a" not in lottiedict:
366  obj.animated = prop_animated(lottiedict)
367  return obj
368 
369 
371  if "a" in l:
372  return l["a"]
373  if "k" not in l:
374  return False
375  if isinstance(l["k"], list) and l["k"] and isinstance(l["k"][0], dict):
376  return True
377  return False
378 
379 
381  return not prop_animated(l)
382 
383 
384 ## @ingroup Lottie
386  """!
387  An animatable property that holds a NVector
388  """
389  keyframe_type = OffsetKeyframe
390  _props = [
391  LottieProp("value", "k", NVector, False, prop_not_animated),
392  LottieProp("property_index", "ix", int, False),
393  LottieProp("animated", "a", PseudoBool, False),
394  LottieProp("keyframes", "k", OffsetKeyframe, True, prop_animated),
395  ]
396 
397  def get_tangent_angle(self, time=0):
398  """!
399  @brief Returns the value tangent angle of the property at the given frame/time
400  """
401  if not self.keyframes or len(self.keyframes) < 2:
402  return 0
403 
404  val, end, kp, t = self._get_value_helper(time)
405  if kp:
406  return kp.interpolated_tangent_angle(t, end)
407 
408  if self.keyframes[0].time >= time:
409  end = self.keyframes[0].end if self.keyframes[0].end is not None else self.keyframes[1].start
410  return self.keyframes[0].interpolated_tangent_angle(0, end)
411 
412  return 0
413 
414 
416  _props = [
417  LottieProp("value", "k", NVector, False, prop_not_animated),
418  LottieProp("property_index", "ix", int, False),
419  LottieProp("animated", "a", PseudoBool, False),
420  LottieProp("keyframes", "k", OffsetKeyframe, True, prop_animated),
421  ]
422 
423  @classmethod
424  def load(cls, lottiedict):
425  obj = super().load(lottiedict)
426  if lottiedict.get("s", False):
427  cls._load_split(lottiedict, obj)
428 
429  return obj
430 
431  @classmethod
432  def _load_split(cls, lottiedict, obj):
433  components = [
434  Value.load(lottiedict.get("x", {})),
435  Value.load(lottiedict.get("y", {})),
436  ]
437  if "z" in lottiedict:
438  components.append(Value.load(lottiedict.get("z", {})))
439 
440  has_anim = any(x for x in components if x.animated)
441  if not has_anim:
442  obj.value = NVector(*(a.value for a in components))
443  obj.animated = False
444  obj.keyframes = None
445  return
446 
447  obj.animated = True
448  obj.value = None
449  obj.keyframes = cls.merge_keyframes(components, NVector)
450 
451 
453  """!
454  An animatable property that holds a Color
455  """
456  keyframe_type = OffsetKeyframe
457  _props = [
458  LottieProp("value", "k", Color, False, prop_not_animated),
459  LottieProp("property_index", "ix", int, False),
460  LottieProp("animated", "a", PseudoBool, False),
461  LottieProp("keyframes", "k", OffsetKeyframe, True, prop_animated),
462  ]
463 
464 
465 ## @ingroup Lottie
467  """!
468  Represents colors and offsets in a gradient
469 
470  Colors are represented as a flat list interleaving offsets and color components in weird ways
471  There are two possible layouts:
472 
473  Without alpha, the colors are a sequence of offset, r, g, b
474 
475  With alpha, same as above but at the end of the list there is a sequence of offset, alpha
476 
477  Examples:
478 
479  For the gradient [0, red], [0.5, yellow], [1, green]
480  The list would be [0, 1, 0, 0, 0.5, 1, 1, 0, 1, 0, 1, 0]
481 
482  For the gradient [0, red at 80% opacity], [0.5, yellow at 70% opacity], [1, green at 60% opacity]
483  The list would be [0, 1, 0, 0, 0.5, 1, 1, 0, 1, 0, 1, 0, 0, 0.8, 0.5, 0.7, 1, 0.6]
484  """
485  _props = [
486  LottieProp("colors", "k", MultiDimensional),
487  LottieProp("count", "p", int),
488  ]
489 
490  def __init__(self, stops=[]):
491  ## Animatable colors, as a vector containing [offset, r, g, b] values as a flat array
493  ## Number of colors
494  self.count = 0
495  if stops:
496  self.set_stops(stops)
497 
498  @staticmethod
499  def color_to_stops(self, colors):
500  """
501  Converts a list of colors (Color) to tuples (offset, color)
502  """
503  return [
504  (i / (len(colors)-1), color)
505  for i, color in enumerate(colors)
506  ]
507 
508  def set_stops(self, stops, keyframe=None):
509  """!
510  @param stops iterable of (offset, Color) tuples
511  @param keyframe keyframe index (or None if not animated)
512  """
513  flat = self._flatten_stops(stops)
514  if self.colors.animated and keyframe is not None:
515  if keyframe > 1:
516  self.colors.keyframes[keyframe-1].end = flat
517  self.colors.keyframes[keyframe].start = flat
518  else:
519  self.colors.clear_animation(flat)
520  self.count = len(stops)
521 
522  def _flatten_stops(self, stops):
523  flattened_colors = NVector(*reduce(
524  lambda a, b: a + b,
525  (
526  [off] + color.components[:3]
527  for off, color in stops
528  )
529  ))
530 
531  if any(len(c) > 3 for o, c in stops):
532  flattened_colors.components += reduce(
533  lambda a, b: a + b,
534  (
535  [off] + [self._get_alpha(color)]
536  for off, color in stops
537  )
538  )
539  return flattened_colors
540 
541  def _get_alpha(self, color):
542  if len(color) > 3:
543  return color[3]
544  return 1
545 
546  def _add_to_flattened(self, offset, color, flattened):
547  flat = [offset] + list(color[:3])
548  rgb_size = 4 * self.count
549 
550  if len(flattened) == rgb_size:
551  # No alpha
552  flattened.extend(flat)
553  if self.count == 0 and len(color) > 3:
554  flattened.append(offset)
555  flattened.append(color[3])
556  else:
557  flattened[rgb_size:rgb_size] = flat
558  flattened.append(offset)
559  flattened.append(self._get_alpha(color))
560 
561  def add_color(self, offset, color, keyframe=None):
562  if self.colors.animated:
563  if keyframe is None:
564  for kf in self.colors.keyframes:
565  if kf.start:
566  self._add_to_flattened(offset, color, kf.start.components)
567  if kf.end:
568  self._add_to_flattened(offset, color, kf.end.components)
569  else:
570  if keyframe > 1:
571  self._add_to_flattened(offset, color, self.colors.keyframes[keyframe-1].end.components)
572  self._add_to_flattened(offset, color, self.colors.keyframes[keyframe].start.components)
573  else:
574  self._add_to_flattened(offset, color, self.colors.value.components)
575  self.count += 1
576 
577  def add_keyframe(self, time, stops, ease=easing.Linear()):
578  """!
579  @param time Frame time
580  @param stops Iterable of (offset, Color) tuples
581  @param ease Easing function
582  """
583  self.colors.add_keyframe(time, self._flatten_stops(stops), ease)
584 
585  def get_stops(self, keyframe=None):
586  if keyframe is not None:
587  colors = self.colors.keyframes[keyframe].start
588  else:
589  colors = self.colors.value
590  return self._stops_from_flat(colors)
591 
592  def _stops_from_flat(self, colors):
593  if len(colors) == 4 * self.count:
594  for i in range(self.count):
595  off = i * 4
596  yield colors[off], Color(*colors[off+1:off+4])
597  else:
598  for i in range(self.count):
599  off = i * 4
600  aoff = self.count * 4 + i * 2 + 1
601  yield colors[off], Color(colors[off+1], colors[off+2], colors[off+3], colors[aoff])
602 
603  def stops_at(self, time):
604  return self._stops_from_flat(self.colors.get_value(time))
605 
606 
607 ## @ingroup Lottie
609  """!
610  An animatable property that holds a float
611  """
612  keyframe_type = OffsetKeyframe
613  _props = [
614  LottieProp("value", "k", float, False, prop_not_animated),
615  LottieProp("property_index", "ix", int, False),
616  LottieProp("animated", "a", PseudoBool, False),
617  LottieProp("keyframes", "k", keyframe_type, True, prop_animated),
618  ]
619 
620  def __init__(self, value=0):
621  super().__init__(value)
622 
623  def add_keyframe(self, time, value, ease=easing.Linear()):
624  super().add_keyframe(time, NVector(value), ease)
625 
626  def get_value(self, time=0):
627  v = super().get_value(time)
628  if self.animated and self.keyframes:
629  return v[0]
630  return v
631 
632 
633 ## @ingroup Lottie
635  """!
636  Keyframe holding Bezier objects
637  """
638  _props = [
639  LottieProp("start", "s", Bezier, PseudoList),
640  LottieProp("end", "e", Bezier, PseudoList),
641  ]
642 
643  def __init__(self, time=0, start=None, end=None, easing_function=None):
644  Keyframe.__init__(self, time, easing_function)
645  ## Start value of keyframe segment.
646  self.start = start
647  ## End value of keyframe segment.
648  self.end = end
649 
650  def interpolated_value(self, ratio, next_start=None):
651  end = next_start if self.end is None else self.end
652  if end is None:
653  return self.start
654  if not self.in_value or not self.out_value:
655  return self.start
656  if ratio == 1:
657  return end
658  if ratio == 0 or len(self.start.vertices) != len(end.vertices):
659  return self.start
660 
661  lerpv = self.lerp_factor(ratio)
662  bez = Bezier()
663  bez.closed = self.start.closed
664  for i in range(len(self.start.vertices)):
665  bez.vertices.append(self.start.vertices[i].lerp(end.vertices[i], lerpv))
666  bez.in_tangents.append(self.start.in_tangents[i].lerp(end.in_tangents[i], lerpv))
667  bez.out_tangents.append(self.start.out_tangents[i].lerp(end.out_tangents[i], lerpv))
668  return bez
669 
670 
671 ## @ingroup Lottie
673  """!
674  An animatable property that holds a Bezier
675  """
676  keyframe_type = ShapePropKeyframe
677  _props = [
678  LottieProp("value", "k", Bezier, False, prop_not_animated),
679  #LottieProp("expression", "x", str, False),
680  LottieProp("property_index", "ix", float, False),
681  LottieProp("animated", "a", PseudoBool, False),
682  LottieProp("keyframes", "k", keyframe_type, True, prop_animated),
683  ]
684 
685  def __init__(self, bezier=None):
686  super().__init__(bezier or Bezier())
lottie.objects.properties.GradientColors.__init__
def __init__(self, stops=[])
Definition: properties.py:490
lottie.utils.color.Color
Definition: color.py:368
lottie.objects.properties.KeyframeBezier.NEWTON_ITERATIONS
int NEWTON_ITERATIONS
Definition: properties.py:11
lottie.objects.properties.AnimatableMixin.__init__
def __init__(self, value=None)
Definition: properties.py:234
lottie.objects.properties.KeyframeBezier._bezier_component
def _bezier_component(self, t, c1, c2)
Definition: properties.py:42
lottie.objects.properties.KeyframeBezier.y_at_x
def y_at_x(self, x)
Definition: properties.py:111
lottie.objects.properties.Keyframe.lerp_factor
def lerp_factor(self, ratio)
Definition: properties.py:152
lottie.objects.properties.AnimatableMixin.__repr__
def __repr__(self)
Definition: properties.py:326
lottie.objects.properties.Value
An animatable property that holds a float.
Definition: properties.py:608
lottie.objects.properties.Value.get_value
def get_value(self, time=0)
Returns the value of the property at the given frame/time.
Definition: properties.py:626
lottie.objects.properties.ShapePropKeyframe.end
end
End value of keyframe segment.
Definition: properties.py:648
lottie.objects.properties.GradientColors._flatten_stops
def _flatten_stops(self, stops)
Definition: properties.py:522
lottie.objects.properties.OffsetKeyframe.end
end
End value of keyframe segment.
Definition: properties.py:186
lottie.objects.properties.GradientColors._stops_from_flat
def _stops_from_flat(self, colors)
Definition: properties.py:592
lottie.objects.properties.Keyframe
Definition: properties.py:117
lottie.objects.properties.KeyframeBezier._a
def _a(self, c1, c2)
Definition: properties.py:33
lottie.objects.properties.Value.add_keyframe
def add_keyframe(self, time, value, ease=easing.Linear())
Definition: properties.py:623
lottie.objects.properties.GradientColors.colors
colors
Animatable colors, as a vector containing [offset, r, g, b] values as a flat array.
Definition: properties.py:492
lottie.objects.properties.ShapePropKeyframe.__init__
def __init__(self, time=0, start=None, end=None, easing_function=None)
Definition: properties.py:643
lottie.objects.properties.KeyframeBezier.NEWTON_MIN_SLOPE
float NEWTON_MIN_SLOPE
Definition: properties.py:12
lottie.objects.bezier.Bezier
Single bezier curve.
Definition: bezier.py:123
lottie.objects.properties.AnimatableMixin
Definition: properties.py:231
lottie.objects.properties.ShapePropKeyframe.start
start
Start value of keyframe segment.
Definition: properties.py:646
lottie.objects.properties.OffsetKeyframe.start
start
Start value of keyframe segment.
Definition: properties.py:184
lottie.objects.properties.KeyframeBezier.t_for_x
def t_for_x(self, x)
Definition: properties.py:92
lottie.objects.properties.OffsetKeyframe.in_tan
in_tan
In Spatial Tangent.
Definition: properties.py:188
lottie.objects.properties.PositionValue._load_split
def _load_split(cls, lottiedict, obj)
Definition: properties.py:432
lottie.objects.properties.OffsetKeyframe
Keyframe for MultiDimensional values.
Definition: properties.py:160
lottie.objects.properties.ShapeProperty
An animatable property that holds a Bezier.
Definition: properties.py:672
lottie.objects.properties.PositionValue.load
def load(cls, lottiedict)
Loads from a JSON object.
Definition: properties.py:424
lottie.objects.properties.GradientColors._add_to_flattened
def _add_to_flattened(self, offset, color, flattened)
Definition: properties.py:546
lottie.objects.properties.KeyframeBezier
Definition: properties.py:10
lottie.objects.properties.KeyframeBezier._binary_subdivide
def _binary_subdivide(self, x, interval_start, interval_end)
Definition: properties.py:60
lottie.objects.properties.KeyframeBezier._sample_values
_sample_values
Definition: properties.py:21
lottie.objects.properties.ShapePropKeyframe
Keyframe holding Bezier objects.
Definition: properties.py:634
lottie.objects.properties.KeyframeBezier.SUBDIVISION_MAX_ITERATIONS
int SUBDIVISION_MAX_ITERATIONS
Definition: properties.py:14
lottie.objects.properties.KeyframeBezier.h1
h1
Definition: properties.py:19
lottie.objects.properties.AnimatableMixin.clear_animation
def clear_animation(self, value)
Sets a fixed value, removing animated keyframes.
Definition: properties.py:244
lottie.objects.base.LottieObject
Base class for mapping Python classes into Lottie JSON objects.
Definition: base.py:224
lottie.objects.properties.AnimatableMixin.animated
animated
Whether it's animated.
Definition: properties.py:240
lottie.objects.properties.GradientColors.add_color
def add_color(self, offset, color, keyframe=None)
Definition: properties.py:561
lottie.objects.properties.AnimatableMixin.add_keyframe
def add_keyframe(self, time, value, interp=easing.Linear(), *args, **kwargs)
Definition: properties.py:252
lottie.objects.properties.KeyframeBezier._c
def _c(self, c1)
Definition: properties.py:39
lottie.objects.properties.KeyframeBezier._newton_raphson
def _newton_raphson(self, x, t_guess)
Definition: properties.py:75
lottie.objects.properties.KeyframeBezier.from_keyframe
def from_keyframe(cls, keyframe)
Definition: properties.py:24
lottie.objects.properties.prop_not_animated
def prop_not_animated(l)
Definition: properties.py:380
lottie.objects.easing.KeyframeBezierHandle
Bezier handle for keyframe interpolation.
Definition: easing.py:6
lottie.objects.properties.KeyframeBezier.point_at
def point_at(self, t)
Definition: properties.py:45
lottie.objects.base.LottieProp
Lottie <-> Python property mapper.
Definition: base.py:88
lottie.objects.properties.Keyframe.__str__
def __str__(self)
Definition: properties.py:155
lottie.objects.properties.AnimatableMixin.keyframes
keyframes
Keyframe list.
Definition: properties.py:242
lottie.objects.properties.KeyframeBezier.__init__
def __init__(self, h1, h2)
Definition: properties.py:18
lottie.objects.properties.KeyframeBezier.SAMPLE_STEP_SIZE
float SAMPLE_STEP_SIZE
Definition: properties.py:16
lottie.objects.properties.Keyframe.out_value
out_value
Bezier curve easing out value.
Definition: properties.py:135
lottie.objects.properties.MultiDimensional.get_tangent_angle
def get_tangent_angle(self, time=0)
Returns the value tangent angle of the property at the given frame/time.
Definition: properties.py:397
lottie.objects.properties.AnimatableMixin._get_value_helper
def _get_value_helper(self, time)
Definition: properties.py:294
lottie.objects.properties.GradientColors.add_keyframe
def add_keyframe(self, time, stops, ease=easing.Linear())
Definition: properties.py:577
lottie.objects.properties.AnimatableMixin.property_index
property_index
Property index.
Definition: properties.py:238
lottie.objects.properties.GradientColors.color_to_stops
def color_to_stops(self, colors)
Definition: properties.py:499
lottie.objects.properties.OffsetKeyframe.interpolated_tangent_angle
def interpolated_tangent_angle(self, ratio, next_start=None)
Definition: properties.py:211
lottie.objects.properties.ShapePropKeyframe.interpolated_value
def interpolated_value(self, ratio, next_start=None)
Definition: properties.py:650
lottie.objects.properties.KeyframeBezier._get_sample_values
def _get_sample_values(self)
Definition: properties.py:84
lottie.objects.properties.KeyframeBezier._b
def _b(self, c1, c2)
Definition: properties.py:36
lottie.objects.properties.Value.__init__
def __init__(self, value=0)
Definition: properties.py:620
lottie.objects.properties.KeyframeBezier._slope_component
def _slope_component(self, t, c1, c2)
Definition: properties.py:51
lottie.objects.properties.GradientColors.stops_at
def stops_at(self, time)
Definition: properties.py:603
lottie.objects.properties.AnimatableMixin.load
def load(cls, lottiedict)
Definition: properties.py:363
lottie.objects.properties.KeyframeBezier.SPLINE_TABLE_SIZE
int SPLINE_TABLE_SIZE
Definition: properties.py:15
lottie.objects.properties.AnimatableMixin.get_value
def get_value(self, time=0)
Returns the value of the property at the given frame/time.
Definition: properties.py:282
lottie.objects.properties.AnimatableMixin.keyframe_type
keyframe_type
Definition: properties.py:232
lottie.objects.properties.GradientColors.set_stops
def set_stops(self, stops, keyframe=None)
Definition: properties.py:508
lottie.objects.properties.OffsetKeyframe.__init__
def __init__(self, time=0, start=None, end=None, easing_function=None, in_tan=None, out_tan=None)
Definition: properties.py:181
lottie.objects.properties.GradientColors
Represents colors and offsets in a gradient.
Definition: properties.py:466
lottie.objects.properties.prop_animated
def prop_animated(l)
Definition: properties.py:370
lottie.objects.properties.GradientColors.get_stops
def get_stops(self, keyframe=None)
Definition: properties.py:585
lottie.objects.properties.Keyframe.bezier
def bezier(self)
Definition: properties.py:142
lottie.objects.properties.GradientColors.count
count
Number of colors.
Definition: properties.py:494
lottie.objects.properties.Keyframe.in_value
in_value
Bezier curve easing in value.
Definition: properties.py:133
lottie.objects.properties.GradientColors._get_alpha
def _get_alpha(self, color)
Definition: properties.py:541
lottie.objects.properties.MultiDimensional
An animatable property that holds a NVector.
Definition: properties.py:385
lottie.objects.properties.KeyframeBezier.slope_at
def slope_at(self, t)
Definition: properties.py:54
lottie.objects.properties.AnimatableMixin.__str__
def __str__(self)
Definition: properties.py:333
lottie.objects.properties.AnimatableMixin.value
value
Non-animated value.
Definition: properties.py:236
lottie.objects.properties.PositionValue
Definition: properties.py:415
lottie.objects.properties.OffsetKeyframe.interpolated_value
def interpolated_value(self, ratio, next_start=None)
Definition: properties.py:192
lottie.objects.properties.ShapeProperty.__init__
def __init__(self, bezier=None)
Definition: properties.py:685
lottie.objects.properties.AnimatableMixin.merge_keyframes
def merge_keyframes(cls, items, conversion)
Definition: properties.py:339
lottie.objects.properties.OffsetKeyframe.__repr__
def __repr__(self)
Definition: properties.py:221
lottie.objects.properties.KeyframeBezier.bezier
def bezier(self)
Definition: properties.py:27
lottie.objects.properties.AnimatableMixin.to_dict
def to_dict(self)
Definition: properties.py:316
lottie.objects.properties.KeyframeBezier.SUBDIVISION_PRECISION
float SUBDIVISION_PRECISION
Definition: properties.py:13
lottie.objects.properties.OffsetKeyframe.out_tan
out_tan
Out Spatial Tangent.
Definition: properties.py:190
lottie.objects.properties.Keyframe.time
time
Start time of keyframe segment.
Definition: properties.py:131
lottie.objects.properties.Keyframe.__init__
def __init__(self, time=0, easing_function=None)
Definition: properties.py:125
lottie.objects.properties.ColorValue
An animatable property that holds a Color.
Definition: properties.py:452
lottie.objects.properties.Keyframe.jump
jump
Jump to the end value.
Definition: properties.py:137
lottie.objects.properties.KeyframeBezier.h2
h2
Definition: properties.py:20
lottie.nvector.NVector
Definition: nvector.py:9