Programmatically generate SVG (vector) images, animations, and interactive Jupyter widgets
1from .elements import DrawingElement, DrawingParentElement 2 3 4class DrawingDef(DrawingParentElement): 5 '''Parent class of SVG nodes that must be direct children of <defs>.''' 6 def get_svg_defs(self): 7 return (self,) 8 9class DrawingDefSub(DrawingParentElement): 10 '''Parent class of SVG nodes that are meant to be descendants of a Def.''' 11 pass 12 13class LinearGradient(DrawingDef): 14 ''' 15 A linear gradient to use as a fill or other color. 16 17 Has <stop> nodes as children, added with `.add_stop()`. 18 ''' 19 TAG_NAME = 'linearGradient' 20 def __init__(self, x1, y1, x2, y2, gradientUnits='userSpaceOnUse', 21 **kwargs): 22 super().__init__(x1=x1, y1=y1, x2=x2, y2=y2, 23 gradientUnits=gradientUnits, **kwargs) 24 def add_stop(self, offset, color, opacity=None, **kwargs): 25 stop = GradientStop(offset=offset, stop_color=color, 26 stop_opacity=opacity, **kwargs) 27 self.append(stop) 28 29class RadialGradient(DrawingDef): 30 ''' 31 A radial gradient to use as a fill or other color 32 33 Has <stop> nodes as children, added with `.add_stop()`. 34 ''' 35 TAG_NAME = 'radialGradient' 36 def __init__(self, cx, cy, r, gradientUnits='userSpaceOnUse', fy=None, 37 **kwargs): 38 super().__init__(cx=cx, cy=cy, r=r, gradientUnits=gradientUnits, 39 fy=fy, **kwargs) 40 def add_stop(self, offset, color, opacity=None, **kwargs): 41 stop = GradientStop(offset=offset, stop_color=color, 42 stop_opacity=opacity, **kwargs) 43 self.append(stop) 44 45class GradientStop(DrawingDefSub): 46 '''A control point for a radial or linear gradient.''' 47 TAG_NAME = 'stop' 48 has_content = False 49 50class ClipPath(DrawingDef): 51 ''' 52 A shape used to crop another element by not drawing outside of this shape. 53 54 Has regular drawing elements as children. 55 ''' 56 TAG_NAME = 'clipPath' 57 58class Mask(DrawingDef): 59 ''' 60 A drawing where the gray value and transparency are used to control the 61 transparency of another shape. 62 63 Has regular drawing elements as children. 64 ''' 65 TAG_NAME = 'mask' 66 67class Filter(DrawingDef): 68 ''' 69 A filter to apply to geometry. 70 71 For example a blur filter. 72 ''' 73 TAG_NAME = 'filter' 74 75class FilterItem(DrawingDefSub): 76 '''A child of Filter with any tag name.''' 77 has_content = False 78 def __init__(self, tag_name, **args): 79 super().__init__(**args) 80 self.TAG_NAME = tag_name 81 82class Marker(DrawingDef): 83 ''' 84 A small drawing that can be placed at the ends of (or along) a path. 85 86 This can be used for arrow heads or points on a graph for example. 87 By default, units are multiples of stroke width. 88 ''' 89 TAG_NAME = 'marker' 90 def __init__(self, minx, miny, maxx, maxy, scale=1, orient='auto', 91 **kwargs): 92 width = maxx - minx 93 height = maxy - miny 94 kwargs = { 95 'markerWidth': width if scale == 1 else float(width) * scale, 96 'markerHeight': height if scale == 1 else float(height) * scale, 97 'viewBox': '{} {} {} {}'.format(minx, miny, width, height), 98 'orient': orient, 99 **kwargs, 100 } 101 super().__init__(**kwargs)