Programmatically generate SVG (vector) images, animations, and interactive Jupyter widgets

Fix as_gif/mp4/video and save_gif/mp4/video API

+25 -9
+25 -9
drawsvg/drawing.py
··· 5 5 import string 6 6 import xml.sax.saxutils as xml 7 7 8 - from . import types, elements as elements_module, raster, video, jupyter 8 + from . import ( 9 + types, elements as elements_module, raster, video, jupyter, native_animation 10 + ) 9 11 10 12 11 13 XML_HEADER = '<?xml version="1.0" encoding="UTF-8"?>\n' ··· 330 332 video.''' 331 333 if context is None: 332 334 context = self.context 333 - if duration is None and context.animation_config is not None: 334 - duration = context.animation_config.duration 335 + config = context.animation_config 336 + if duration is None and config is not None: 337 + duration = config.duration 335 338 if duration is None: 336 339 raise ValueError('unknown animation duration, specify duration') 340 + if config is None: 341 + config = native_animation.SyncedAnimationConfig(duration) 337 342 frames = [] 338 343 for i in range(int(duration * fps + 1)): 339 344 time = i / fps 340 345 frame_context = dataclasses.replace( 341 346 context, 342 347 animation_config=dataclasses.replace( 343 - context.animation_config, 348 + config, 344 349 freeze_frame_at=time, 345 350 show_playback_controls=False)) 346 351 frames.append(self.display_inline(context=frame_context)) 347 352 return frames 348 - def save_gif(self, fname, fps=10, duration=None, context=None): 349 - self.as_gif(fname, fps=fps, duration=duration, context=context) 350 - def save_mp4(self, fname, fps=10, duration=None, context=None): 351 - self.as_mp4(fname, fps=fps, duration=duration, context=context) 353 + def save_video(self, fname, fps=10, duration=None, mime_type=None, 354 + file_type=None, context=None, verbose=False): 355 + self.as_video( 356 + fname, fps=fps, duration=duration, mime_type=mime_type, 357 + file_type=file_type, context=context, verbose=verbose) 358 + def save_gif(self, fname, fps=10, duration=None, context=None, 359 + verbose=False): 360 + self.as_gif( 361 + fname, fps=fps, duration=duration, context=context, 362 + verbose=verbose) 363 + def save_mp4(self, fname, fps=10, duration=None, context=None, 364 + verbose=False): 365 + self.as_mp4( 366 + fname, fps=fps, duration=duration, context=context, 367 + verbose=verbose) 352 368 def as_video(self, to_file=None, fps=10, duration=None, 353 - mime_type=None, file_type=None, context=None, verbose=False): 369 + mime_type=None, file_type=None, context=None, verbose=False): 354 370 if file_type is None and mime_type is None: 355 371 if to_file is None or '.' not in str(to_file): 356 372 file_type = 'mp4'