This repository has been archived on 2023-03-25. You can view files and clone it, but cannot push or open issues or pull requests.

121 lines
6.5 KiB

#!/usr/bin/env python3
import inkex
import subprocess
import shutil
import os
import sys
from lxml import etree
import warnings
Extension for InkScape 1.X
- Create SVG preview file and show it in browser. Helps to quickly evaluate line order for cutting processes
Author: Mario Voigt / FabLab Chemnitz
Date: 21.04.2021
Last patch: 07.05.2021
License: GNU GPL v3
Used version of Vivus JS library: - MIT License
Browser config:
Firefox via about:config -> privacy.file_unique_origin = false
- adjust width and height (give options)
- embed config buttons inside html to adjust time/type/... (more flexible than clicking from Inkscape)
- we should do it the way like vivus instant -> /
- the generated SVGs can be downloaded again and include all animations!
- calculate the total length of all paths and auto-adjust the speed to have good visibility
- Possible feature request could be to handle "animate selected objects only". See "Export selection as ... " extension to steal that code.
class AnimateOrder(inkex.EffectExtension):
def spawnIndependentProcess(self, args):
warnings.simplefilter('ignore', ResourceWarning) #suppress "enable tracemalloc to get the object allocation traceback"
if == 'nt':
subprocess.Popen(args, close_fds=True, creationflags=DETACHED_PROCESS)
subprocess.Popen(args, start_new_session=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
warnings.simplefilter("default", ResourceWarning)
def add_arguments(self, pars):
pars.add_argument("--time", type=float, default = 5.0, help="Duration (frames)")
pars.add_argument("--fps", type=int, default = 60.0, help="Frames per second (fps)")
pars.add_argument("--sequence_type", help="Sequence type")
pars.add_argument("--reverse", type = inkex.Boolean, default = False, help="Reverse order")
pars.add_argument("--browser", help="Select your desired browser (must be installed and must exist in %PATH% variable).")
def effect(self):
#write current SVG to extensions' directory. Target name must be "drawing.svg" because it is embedded in animate_order.html statically
inFile = "drawing.svg"
extension_dir = os.path.dirname(os.path.realpath(__file__))
shutil.copy2(self.options.input_file, os.path.join(extension_dir, inFile))
target_html = os.path.join(extension_dir, "animate_order.html")
docTitle = self.document.getroot().get("{}docname")
animateId = self.document.getroot().get('id')
if docTitle is None:
title = "Animate Order - Vivus JS"
title = "Animate Order - " + docTitle
vivus_include = "./vivus-0.4.6/dist/vivus.js"
duration = self.options.time * self.options.fps # we guess we have 20 ... 60 fps. depends on performance of the machine
frames_per_second = self.options.fps
type = self.options.sequence_type
reverse = str(self.options.reverse).lower()
currentDoc = self.document_path()
if currentDoc == "":
self.msg("Your document is not saved as a permanent file yet. Please save first.")
svgfile = open(self.document_path(), 'r')
svgContent =
with open(target_html, "w") as text_file:
print( '<html>' , file=text_file)
print( ' <head>' , file=text_file)
print( ' <meta charset="UTF-8">' , file=text_file)
print( ' <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">' , file=text_file)
print( ' <meta name="viewport" content="width=device-width, initial-scale=1.0">' , file=text_file)
print(f' <title>{title}</title>' , file=text_file)
print( ' <meta name="description" content="SVG Drawing Animation">' , file=text_file)
print( ' </head>' , file=text_file)
print( ' <body>' , file=text_file)
print( ' <button onclick="vi.reset().play();">replay</button>' , file=text_file)
print( ' <br/>' , file=text_file)
#print(f' <object id="animate_order" type="image/svg+xml" data="{inFile}"></object>' , file=text_file)
print(svgContent , file=text_file)
print(f' <script src="{vivus_include}"></script>' , file=text_file)
print( ' <script>' , file=text_file)
print( " var vi = new Vivus('" + f'{animateId}' + "', {type: '" + f'{type}' + "', \
duration:" + f'{duration}' + ", reverseStack:" + f'{reverse}' + "});" , file=text_file)
print( ' </script>' , file=text_file)
print( ' </body>' , file=text_file)
print( '</html>' , file=text_file)
if os.path.exists(target_html) is False:
inkex.utils.debug("Error. Target file does not exist!")
#now open firefox
args = [self.options.browser, target_html]
except FileNotFoundError as e:
inkex.utils.debug("Error. Check for correct browser installation and try again!")
if __name__ == '__main__':