我使用Cairo,OpenGL和rsvg渲染了一个包含大量元素的巨大SVG文件。我通过rsvg在cairo表面绘制svg并创建一个OpenGL纹理来绘制它。一切都好。现在我必须与SVG中的元素进行交互。例如,我想通过坐标猜测一个元素。我想改变SVG中某些路径的背景。在我想改变背景的情况下,我可以改变SVG DOM并以某种方式重新渲染SVG的一部分。但是在命中测试元素的情况下,我完全不好意思。
那么,是否有一些python库与SVG交互?是否有可能继续使用cairo和rsvg,我该如何自己实现呢?或者有更好的方法在OpenGL中呈现SVG并在python中与它交互?我想要的只是加载SVG,操纵它的DOM并渲染它
答案 0 :(得分:2)
我对librsvg了解不多,但自2005年以来似乎没有更新过,所以我倾向于建议使用不同的实现。
如果您对标准库之外的任何Python库没有依赖关系,那么您可以将Jython与Batik一起使用。这允许您添加事件处理程序,以及在呈现后更改DOM。
有关如何使用Java执行此操作的示例see this link。
这是Jython 2.2.1的快速端口(运行,但未经过全面测试):
from java.awt.event import WindowAdapter;
from java.awt.event import WindowEvent;
from javax.swing import JFrame;
from org.apache.batik.swing import JSVGCanvas;
from org.apache.batik.swing.svg import SVGLoadEventDispatcherAdapter;
from org.apache.batik.swing.svg import SVGLoadEventDispatcherEvent;
from org.apache.batik.script import Window;
from org.w3c.dom import Document;
from org.w3c.dom import Element;
from org.w3c.dom.events import Event;
from org.w3c.dom.events import EventListener;
from org.w3c.dom.events import EventTarget;
class SVGApplication :
def __init__(self) :
class MySVGLoadEventDispatcherAdapter(SVGLoadEventDispatcherAdapter):
def svgLoadEventDispatcherListener(e):
# At this time the document is available...
self.document = self.canvas.getSVGDocument();
# ...and the window object too.
self.window = self.canvas.getUpdateManager().getScriptingEnvironment().createWindow();
# Registers the listeners on the document
# just before the SVGLoad event is
# dispatched.
registerListeners();
# It is time to pack the frame.
self.frame.pack();
def windowAdapter(e):
# The canvas is ready to load the base document
# now, from the AWT thread.
self.canvas.setURI("doc.svg");
self.frame = JFrame(windowOpened = windowAdapter, size=(800, 600));
self.canvas = JSVGCanvas();
# Forces the canvas to always be dynamic even if the current
# document does not contain scripting or animation.
self.canvas.setDocumentState(JSVGCanvas.ALWAYS_DYNAMIC);
self.canvas.addSVGLoadEventDispatcherListener(MySVGLoadEventDispatcherAdapter()) ;
self.frame.getContentPane().add(self.canvas);
self.frame.show()
def registerListeners(self) :
# Gets an element from the loaded document.
elt = self.document.getElementById("elt-id");
t = elt;
def eventHandler(e):
print e, type(e)
self.window.setTimeout(500,run = lambda : self.window.alert("Delayed Action invoked!"));
#window.setInterval(Animation(), 50);
# Adds a 'onload' listener
t.addEventListener("SVGLoad", false, handleEvent = eventHandler );
# Adds a 'onclick' listener
t.addEventListener("click", false, handleEvent = eventHandler );
if __name__ == "__main__":
SVGApplication();
使用以下命令运行:
jython -Dpython.path=/usr/share/java/batik-all.jar:/home/jacob/apps/batik-1.7/lib/xml-apis-ext.jar test.py
答案 1 :(得分:1)
另一种方法是使用blender。它支持使用python进行svg导入和交互。我不认为它会允许你在导入后编辑dom。
答案 2 :(得分:0)
您可以使用GObject内省与Python 3上的librsvg进行交互;见my answer to a similar question here。
答案 3 :(得分:0)
我必须这样做(例如更改元素颜色),并且必须修改rsvg库,因为所有这些不错的功能都存在,但它们是隐藏的。你必须建立一个新的界面来链接好的功能。