class LinearNumberSlider(ControlMobject): CONFIG = { # Since, only slider circle listnes to drag event "listen_to_events": False, "value_type": np.float64, "min_value": -10.0, "max_value": 10.0, "step": 1.0, "rounded_rect_kwargs": { "height": 0.075, "width": 2, "corner_radius": 0.0375 }, "circle_kwargs": { "radius": 0.1, "stroke_color": GREY_A, "fill_color": GREY_A, "fill_opacity": 1.0 } } def __init__(self, value=0, **kwargs): digest_config(self, kwargs) self.bar = RoundedRectangle(**self.rounded_rect_kwargs) self.slider = Circle(**self.circle_kwargs) self.slider_axis = Line(start=self.bar.get_bounding_box_point(LEFT), end=self.bar.get_bounding_box_point(RIGHT)) self.slider_axis.set_opacity(0.0) self.slider.move_to(self.slider_axis) self.slider.listen_to_events = True self.slider.on_mouse_drag = self.slider_on_mouse_drag super().__init__(value, self.bar, self.slider, self.slider_axis, **kwargs) def assert_value(self, value): assert (self.min_value <= value <= self.max_value) def set_value_anim(self, value): prop = (value - self.min_value) / (self.max_value - self.min_value) self.slider.move_to(self.slider_axis.point_from_proportion(prop)) def slider_on_mouse_drag(self, point, d_point, buttons, modifiers): self.set_value(self.get_value_from_point(point)) return False # Helper Methods def get_value_from_point(self, point): start, end = self.slider_axis.get_start_and_end() point_on_line = get_closest_point_on_line(start, end, point) prop = get_norm(point_on_line - start) / get_norm(end - start) value = self.min_value + prop * (self.max_value - self.min_value) no_of_steps = int((value - self.min_value) / self.step) value_nearest_to_step = self.min_value + no_of_steps * self.step return value_nearest_to_step
class LinearNumberSlider(ControlMobject): CONFIG = { "value_type": np.float64, "min_value": -10.0, "max_value": 10.0, "step": 1.0, "rounded_rect_kwargs": { "height": 0.075, "width": 2, "corner_radius": 0.0375 }, "circle_kwargs": { "radius": 0.1, "stroke_color": GREY_A, "fill_color": GREY_A, "fill_opacity": 1.0 } } def __init__(self, value: float = 0, **kwargs): digest_config(self, kwargs) self.bar = RoundedRectangle(**self.rounded_rect_kwargs) self.slider = Circle(**self.circle_kwargs) self.slider_axis = Line( start=self.bar.get_bounding_box_point(LEFT), end=self.bar.get_bounding_box_point(RIGHT) ) self.slider_axis.set_opacity(0.0) self.slider.move_to(self.slider_axis) self.slider.add_mouse_drag_listner(self.slider_on_mouse_drag) super().__init__(value, self.bar, self.slider, self.slider_axis, **kwargs) def assert_value(self, value: float) -> None: assert(self.min_value <= value <= self.max_value) def set_value_anim(self, value: float) -> None: prop = (value - self.min_value) / (self.max_value - self.min_value) self.slider.move_to(self.slider_axis.point_from_proportion(prop)) def slider_on_mouse_drag(self, mob, event_data: dict[str, np.ndarray]) -> bool: self.set_value(self.get_value_from_point(event_data["point"])) return False # Helper Methods def get_value_from_point(self, point: np.ndarray) -> float: start, end = self.slider_axis.get_start_and_end() point_on_line = get_closest_point_on_line(start, end, point) prop = get_norm(point_on_line - start) / get_norm(end - start) value = self.min_value + prop * (self.max_value - self.min_value) no_of_steps = int((value - self.min_value) / self.step) value_nearest_to_step = self.min_value + no_of_steps * self.step return value_nearest_to_step
def __init__(self, value=0, **kwargs): digest_config(self, kwargs) self.bar = RoundedRectangle(**self.rounded_rect_kwargs) self.slider = Circle(**self.circle_kwargs) self.slider_axis = Line(start=self.bar.get_bounding_box_point(LEFT), end=self.bar.get_bounding_box_point(RIGHT)) self.slider_axis.set_opacity(0.0) self.slider.move_to(self.slider_axis) super().__init__(value, self.bar, self.slider, self.slider_axis, **kwargs)
def rect_to_mobject(self, rect_element, style): stroke_width = rect_element.getAttribute("stroke-width") corner_radius = rect_element.getAttribute("rx") if stroke_width in ["", "none", "0"]: stroke_width = 0 if corner_radius in ["", "0", "none"]: corner_radius = 0 corner_radius = float(corner_radius) parsed_style = parse_style(style, self.generate_default_style()) parsed_style["stroke_width"] = stroke_width if corner_radius == 0: mob = Rectangle( width=self.attribute_to_float( rect_element.getAttribute("width")), height=self.attribute_to_float( rect_element.getAttribute("height")), **parsed_style, ) else: mob = RoundedRectangle(width=self.attribute_to_float( rect_element.getAttribute("width")), height=self.attribute_to_float( rect_element.getAttribute("height")), corner_radius=corner_radius, **parsed_style) mob.shift(mob.get_center() - mob.get_corner(UP + LEFT)) return mob
def __init__(self, file_name=None, **kwargs): Container.__init__(self, **kwargs) self.file_name = file_name or self.file_name self.ensure_valid_file() self.style = self.style.lower() self.gen_html_string() strati = self.html_string.find("background:") self.background_color = self.html_string[strati + 12:strati + 19] self.gen_code_json() self.code = self.gen_colored_lines() if self.insert_line_no: self.line_numbers = self.gen_line_numbers() self.line_numbers.next_to(self.code, direction=LEFT, buff=self.line_no_buff) if self.background == "rectangle": if self.insert_line_no: forground = VGroup(self.code, self.line_numbers) else: forground = self.code self.background_mobject = SurroundingRectangle(forground, buff=self.margin, color=self.background_color, fill_color=self.background_color, stroke_width=0, fill_opacity=1, ) self.background_mobject.round_corners(self.corner_radius) else: if self.insert_line_no: forground = VGroup(self.code, self.line_numbers) else: forground = self.code height = forground.get_height() + 0.1 * 3 + 2 * self.margin width = forground.get_width() + 0.1 * 3 + 2 * self.margin rrect = RoundedRectangle(corner_radius=self.corner_radius, height=height, width=width, stroke_width=0, color=self.background_color, fill_opacity=1) button_radius = 0.09 red_button = Dot(radius=button_radius, stroke_width=0, color='#ff5f56') red_button.shift(LEFT * button_radius * 3) yellow_button = Dot(radius=button_radius, stroke_width=0, color='#ffbd2e') green_button = Dot(radius=button_radius, stroke_width=0, color='#27c93f') green_button.shift(RIGHT * button_radius * 3) buttons = VGroup(red_button, yellow_button, green_button) buttons.shift( UP * (height / 2 - 0.1 * 2 - 0.05) + LEFT * (width / 2 - 0.1 * 5 - self.corner_radius / 2 - 0.05)) self.background_mobject = VGroup(rrect, buttons) x = (height - forground.get_height()) / 2 - 0.1 * 3 self.background_mobject.shift(forground.get_center()) self.background_mobject.shift(UP * x) if self.insert_line_no: VGroup.__init__(self, self.background_mobject, self.line_numbers, *self.code, **kwargs) else: VGroup.__init__(self, self.background_mobject, Dot(fill_opacity=0, stroke_opacity=0), *self.code, **kwargs) self.move_to(np.array([0, 0, 0]))
def rect_to_mobject(self, rect_element): fill_color = rect_element.getAttribute("fill") stroke_color = rect_element.getAttribute("stroke") stroke_width = rect_element.getAttribute("stroke-width") corner_radius = rect_element.getAttribute("rx") # input preprocessing if fill_color in ["", "none", "#FFF", "#FFFFFF"] or Color(fill_color) == Color(WHITE): opacity = 0 fill_color = BLACK # shdn't be necessary but avoids error msgs if fill_color in ["#000", "#000000"]: fill_color = WHITE if stroke_color in ["", "none", "#FFF", "#FFFFFF"] or Color(stroke_color) == Color(WHITE): stroke_width = 0 stroke_color = BLACK if stroke_color in ["#000", "#000000"]: stroke_color = WHITE if stroke_width in ["", "none", "0"]: stroke_width = 0 if corner_radius in ["", "0", "none"]: corner_radius = 0 corner_radius = float(corner_radius) if corner_radius == 0: mob = Rectangle( width=self.attribute_to_float( rect_element.getAttribute("width") ), height=self.attribute_to_float( rect_element.getAttribute("height") ), stroke_width=stroke_width, stroke_color=stroke_color, fill_color=fill_color, fill_opacity=opacity ) else: mob = RoundedRectangle( width=self.attribute_to_float( rect_element.getAttribute("width") ), height=self.attribute_to_float( rect_element.getAttribute("height") ), stroke_width=stroke_width, stroke_color=stroke_color, fill_color=fill_color, fill_opacity=opacity, corner_radius=corner_radius ) mob.shift(mob.get_center() - mob.get_corner(UP + LEFT)) return mob
def rect_to_mobject(self, rect: se.Rect) -> Rectangle: if rect.rx == 0 or rect.ry == 0: mob = Rectangle( width=rect.width, height=rect.height, ) else: mob = RoundedRectangle(width=rect.width, height=rect.height * rect.rx / rect.ry, corner_radius=rect.rx) mob.stretch_to_fit_height(rect.height) mob.shift( _convert_point_to_3d(rect.x + rect.width / 2, rect.y + rect.height / 2)) return mob
def rect_to_mobject(self, rect_element: MinidomElement, style: dict): """Converts a SVG <rect> command to a VMobject. Parameters ---------- rect_element : minidom.Element A SVG rect path command. style : dict Style specification, using the SVG names for properties. Returns ------- Rectangle Creates either a Rectangle, or RoundRectangle, VMobject from a rect element. """ stroke_width = rect_element.getAttribute("stroke-width") corner_radius = rect_element.getAttribute("rx") if stroke_width in ["", "none", "0"]: stroke_width = 0 if corner_radius in ["", "0", "none"]: corner_radius = 0 corner_radius = float(corner_radius) parsed_style = parse_style(style) parsed_style["stroke_width"] = stroke_width if corner_radius == 0: mob = Rectangle( width=self.attribute_to_float(rect_element.getAttribute("width")), height=self.attribute_to_float(rect_element.getAttribute("height")), **parsed_style, ) else: mob = RoundedRectangle( width=self.attribute_to_float(rect_element.getAttribute("width")), height=self.attribute_to_float(rect_element.getAttribute("height")), corner_radius=corner_radius, **parsed_style, ) mob.shift(mob.get_center() - mob.get_corner(UP + LEFT)) return mob
def __init__(self, file_name=None, code_str=None, **kwargs): Container.__init__(self, **kwargs) self.file_name = file_name self.code_str = code_str self.ensure_valid_file() self.style = self.style.lower() self.gen_html_string() strati = self.html_string.find("background:") self.background_color = self.html_string[strati + 12:strati + 19] self.gen_code_json() self.code = self.gen_colored_lines() if self.insert_line_no: self.line_numbers = self.gen_line_numbers() self.line_numbers.next_to(self.code, direction=LEFT, buff=self.line_no_buff) if self.background == "rectangle": if self.insert_line_no: forground = VGroup(self.code, self.line_numbers) else: forground = self.code self.background_mobject = SurroundingRectangle( forground, buff=self.margin, color=self.background_color, fill_color=self.background_color, stroke_width=0, fill_opacity=1, ) self.background_mobject.round_corners(self.corner_radius) else: if self.insert_line_no: forground = VGroup(self.code, self.line_numbers) else: forground = self.code height = forground.get_height() + 0.1 * 3 + 2 * self.margin width = forground.get_width() + 0.1 * 3 + 2 * self.margin rrect = RoundedRectangle(corner_radius=self.corner_radius, height=height, width=width, stroke_width=0, color=GREY_E, fill_opacity=1) red_button = Dot(radius=0.1, stroke_width=0, color='#ff5f56') red_button.shift(LEFT * 0.1 * 3) yellow_button = Dot(radius=0.1, stroke_width=0, color='#ffbd2e') green_button = Dot(radius=0.1, stroke_width=0, color='#27c93f') green_button.shift(RIGHT * 0.1 * 3) buttons = VGroup(red_button, yellow_button, green_button) buttons.shift( UP * (height / 2 - 0.1 * 2 - 0.05) + LEFT * (width / 2 - 0.1 * 5 - self.corner_radius / 2 - 0.05)) self.background_mobject = VGroup(rrect, buttons) x = (height - forground.get_height()) / 2 - 0.1 * 3 self.background_mobject.shift(forground.get_center()) self.background_mobject.shift(UP * x) if self.insert_line_no: VGroup.__init__(self, self.background_mobject, self.line_numbers, *self.code, **kwargs) else: VGroup.__init__(self, self.background_mobject, Dot(fill_opacity=0, stroke_opacity=0), *self.code, **kwargs) window = RIGHT_SIDE[0] - LEFT_SIDE[0] width = self.background_mobject.get_width() print(width) scale_x = window / width * 0.96 window = TOP[1] - BOTTOM[1] print(window) width = self.background_mobject.get_height() scale_y = window / width * 0.96 if self.adapting_x and scale_x < scale_y: self.scale(scale_x) if self.adapting_y and scale_y <= scale_x: self.scale(scale_y) self.align_to(LEFT_SIDE + self.margin, LEFT) self.align_to( TOP - self.margin + 0.42 * (self.code.char_height + self.code.line_spacing) * self.scale_factor, UP)