text: from manimlib.web.utils import serialize_args, serialize_config
  from manimlib.animation.animation import Animation
  from manimlib.animation.animation import DEFAULT_ANIMATION_LAG_RATIO
  from manimlib.animation.transform import Transform
  from manimlib.constants import DOWN
  from manimlib.mobject.types.vectorized_mobject import VMobject
  from manimlib.utils.bezier import interpolate
  from manimlib.utils.rate_functions import there_and_back
  
  
  DEFAULT_FADE_LAG_RATIO = 0
  
  
  class FadeOut(Transform):
      CONFIG = {
          "remover": True,
          "lag_ratio": DEFAULT_FADE_LAG_RATIO,
      }
  
      def get_args(self):
          return [self.mobject]
  
      def create_target(self):
          return self.mobject.copy().fade(1)
  
      def clean_up_from_scene(self, scene=None):
          super().clean_up_from_scene(scene)
          self.interpolate(0)
  
  
  class FadeIn(Transform):
      CONFIG = {
          "lag_ratio": DEFAULT_FADE_LAG_RATIO,
      }
  
      def get_args(self):
          return [self.mobject]
  
      def create_target(self):
          return self.mobject
  
      def create_starting_mobject(self):
          start = super().create_starting_mobject()
          start.fade(1)
          if isinstance(start, VMobject):
              start.set_stroke(width=0)
              start.set_fill(opacity=0)
          return start
  
  
  class FadeInFrom(Transform):
      CONFIG = {
          "direction": DOWN,
          "lag_ratio": DEFAULT_ANIMATION_LAG_RATIO,
      }
  
      def __init__(self, mobject, direction=None, **kwargs):
          if not hasattr(self, "args"):
              self.args = serialize_args([mobject])
          if not hasattr(self, "config"):
              self.config = serialize_config({
                  'direction': direction,
                  **kwargs,
              })
          if direction is not None:
              self.direction = direction
          super().__init__(mobject, **kwargs)
  
      def create_target(self):
          return self.mobject.copy()
  
      def begin(self):
          super().begin()
          self.starting_mobject.shift(self.direction)
          self.starting_mobject.fade(1)
  
  
  class FadeInFromDown(FadeInFrom):
      """
      Identical to FadeInFrom, just with a name that
      communicates the default
      """
      CONFIG = {
          "direction": DOWN,
          "lag_ratio": DEFAULT_ANIMATION_LAG_RATIO,
      }
  
  
  class FadeOutAndShift(FadeOut):
      CONFIG = {
          "direction": DOWN,
      }
  
      def __init__(self, mobject, direction=None, **kwargs):
          if not hasattr(self, "args"):
              self.args = serialize_args([mobject])
          if not hasattr(self, "config"):
              self.config = serialize_config({
                  'direction': direction,
                  **kwargs,
              })
          if direction is not None:
              self.direction = direction
          super().__init__(mobject, **kwargs)
  
      def create_target(self):
          target = super().create_target()
          target.shift(self.direction)
          return target
  
  
  class FadeOutAndShiftDown(FadeOutAndShift):
      """
      Identical to FadeOutAndShift, just with a name that
      communicates the default
      """
      CONFIG = {
          "direction": DOWN,
      }
  
  
  class FadeInFromPoint(FadeIn):
      def __init__(self, mobject, point, **kwargs):
          if not hasattr(self, "args"):
              self.args = serialize_args([mobject, point])
          if not hasattr(self, "config"):
              self.config = serialize_config({
                  **kwargs,
              })
          self.point = point
          super().__init__(mobject, **kwargs)
  
      def create_starting_mobject(self):
          start = super().create_starting_mobject()
          start.scale(0)
          start.move_to(self.point)
          return start
  
  
  class FadeInFromLarge(FadeIn):
      CONFIG = {
          "scale_factor": 2,
      }
  
      def __init__(self, mobject, scale_factor=2, **kwargs):
          if not hasattr(self, "args"):
              self.args = serialize_args([mobject])
          if not hasattr(self, "config"):
              self.config = serialize_config({
                  'scale_factor': scale_factor,
                  **kwargs,
              })
          if scale_factor is not None:
              self.scale_factor = scale_factor
          super().__init__(mobject, **kwargs)
  
      def create_starting_mobject(self):
          start = super().create_starting_mobject()
          start.scale(self.scale_factor)
          return start
  
  
  class VFadeIn(Animation):
      """
      VFadeIn and VFadeOut only work for VMobjects,
      """
      CONFIG = {
          "suspend_mobject_updating": False,
      }
  
      def interpolate_submobject(self, submob, start, alpha):
          submob.set_stroke(
              opacity=interpolate(0, start.get_stroke_opacity(), alpha)
          )
          submob.set_fill(
              opacity=interpolate(0, start.get_fill_opacity(), alpha)
          )
  
  
  class VFadeOut(VFadeIn):
      CONFIG = {
          "remover": True
      }
  
      def interpolate_submobject(self, submob, start, alpha):
          super().interpolate_submobject(submob, start, 1 - alpha)
  
  
  class VFadeInThenOut(VFadeIn):
      CONFIG = {
          "rate_func": there_and_back,
          "remover": True,
      }
  