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