SVG-взаимодействие в Python с Cairo, OpenGL и RSVG
Я рендерил огромный файл SVG с большим количеством элементов с помощью Cairo, OpenGL и rsvg. Я рисую svg на поверхности Каира через rsvg и создаю текстуру OpenGL, чтобы нарисовать ее. Все отлично. И теперь я должен взаимодействовать с элементами из SVG. Например, я хочу угадать элемент по координатам. И я хочу изменить фон какого-то пути в SVG. Я думаю, что в случае смены фона я могу изменить SVG DOM и каким-то образом перерисовать часть SVG. Но в случае элементов тестирования попадания я полностью смущен.
Итак, есть ли библиотека Python для взаимодействия с SVG? Можно ли остаться с cairo и rsvg и как я могу реализовать это сам? Или есть лучший способ визуализации SVG в OpenGL и взаимодействия с ним в Python? Все, что я хочу, это загрузить SVG, манипулировать его DOM и визуализировать его
4 ответа
Я не очень разбираюсь в librsvg, но, похоже, он не обновлялся с 2005 года, поэтому я бы порекомендовал использовать другую реализацию.
Если у вас нет зависимостей от каких-либо библиотек Python за пределами стандартной библиотеки, то вы можете использовать Jython вместе с Batik. Это позволяет добавлять обработчики событий, а также изменять DOM после рендеринга.
Для примера того, как сделать это с Java, смотрите эту ссылку.
Вот быстрый порт для 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
Альтернативным подходом было бы использование блендера. Он поддерживает импорт SVG и взаимодействие с использованием Python. Я не думаю, что это позволит вам редактировать дом после импорта.
Мне пришлось сделать то же самое (например, изменить цвет элемента) и изменить библиотеку rsvg, потому что все эти приятные функции существуют, но они скрыты. Вы должны сделать новый интерфейс для ссылки на приятные функции.
Вы можете использовать GObject introspection для взаимодействия с librsvg на Python 3; см. мой ответ на подобный вопрос здесь.