def __init__(self, mobject, midle_color=None, **kwargs): digest_config(self, kwargs) self.mobject = mobject self.rectangle_kwargs["color"] = self.color if midle_color == None: midle_color = self.rectangle_kwargs["color"] rectangle = Rectangle(height=mobject.get_height() + self.margin, width=mobject.get_width() + self.margin, **self.rectangle_kwargs) rectangle.move_to(mobject) rectangle.init_state = rectangle.copy() rectangle_width = rectangle.get_width() def return_updater(mob, alpha): dx = interpolate(-PI / 2, PI / 2, alpha) mob.become(mob.init_state) mob.set_width(rectangle_width * np.cos(dx), stretch=True) # dx should not be zero sign = -abs(dx) / (dx + 0.00000000001) direction = LEFT * sign reference_line = Line( rectangle.init_state.get_corner(UP + direction), rectangle.init_state.get_corner(DOWN + direction)) mob.next_to(reference_line, -direction, buff=0) opacity = self.init_opacity + (self.max_opacity - self.init_opacity) * np.cos(dx) mob.set_style(fill_opacity=opacity) mob.set_color( interpolate_color(self.rectangle_kwargs["color"], midle_color, np.cos(dx))) super().__init__(rectangle, return_updater)
def add_black_keys(self): key = Rectangle(*self.black_key_dims) key.set_fill(self.black_key_color, 1) key.set_stroke(width=0) self.black_keys = VGroup() for i in range(len(self.white_keys) - 1): if i % self.white_keys_per_octave not in self.black_pattern: continue wk1 = self.white_keys[i] wk2 = self.white_keys[i + 1] bk = key.copy() bk.move_to(midpoint(wk1.get_top(), wk2.get_top()), UP) big_bk = bk.copy() big_bk.stretch((bk.get_width() + self.key_buff) / bk.get_width(), 0) big_bk.stretch((bk.get_height() + self.key_buff) / bk.get_height(), 1) big_bk.move_to(bk, UP) for wk in wk1, wk2: wk.become(Difference(wk, big_bk).match_style(wk)) self.black_keys.add(bk) self.add(*self.black_keys)