在 Python Pygame 上显示 SVG(来自字符串)
Display SVG (from string) on Python Pygame
我有一个用字符串表示的 SVG 图形
svg_string='<svg height="100" width="500"><ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" /><ellipse cx="220" cy="50" rx="190" ry="20" style="fill:white" /></svg>'
我想在Python发起的window上显示svg_string
表示的图形,即2个椭圆。
伪代码应该是这样的
import pygame
def display_svg_figure(screen, svg_string):
# Code that draws the rendered SVG string on
# the screen
pass
background_colour = (255, 255, 255)
(width, height) = (900, 900)
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Display SVG')
screen.fill(background_colour)
pygame.display.flip()
svg_string='<svg height="100" width="500"><ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" /><ellipse cx="220" cy="50" rx="190" ry="20" style="fill:white" /></svg>'
display_svg_figure(screen, svg_string)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
我基本上是在看方法的实现 display_svg_figure(screen,svg_string)
我也愿意使用非 pygame 库,只要它遵循以下简单接口并且可以将其包含在 pygame
中
from SOME_LIBRARY import SOME_COMPONENT
svg_string="......"
SOME_COMPONENT.display(svg_string)
我已经看过 pynanosvg
但它不再受支持并且失败了,所以不能满足我的需要。
中给出的解决方案似乎不符合要求,因为它在 PyGame 中不起作用。如果有人能让它工作,请告诉我。
如何阅读 Scalable Vector Graphics (SVG) file is answered at SVG rendering in a PyGame application.
Pygame 2.0 版支持 SVG 文件。自版本 2.0.2 起,SDL Image 支持 SVG (Scalable Vector Graphics) files (see SDL_image 2.0). Therefore, with pygame version 2.0.1, SVG files can be loaded into a pygame.Surface
object with pygame.image.load()
from a stream (io.BytesIO
):
svg_string = '<svg height="100" width="500"><ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" /><ellipse cx="220" cy="50" rx="190" ry="20" style="fill:white" /></svg>'
pygame_surface = pygame.image.load(io.BytesIO(svg_string.encode()))
最小示例:
import pygame
import io
pygame.init()
window = pygame.display.set_mode((500, 200))
clock = pygame.time.Clock()
svg_string = '<svg height="100" width="500"><ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" /><ellipse cx="220" cy="50" rx="190" ry="20" style="fill:white" /></svg>'
pygame_surface = pygame.image.load(io.BytesIO(svg_string.encode()))
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill((255, 255, 255))
window.blit(pygame_surface, pygame_surface.get_rect(center = window.get_rect().center))
pygame.display.flip()
pygame.quit()
exit()
在 Pygame 2 之前,您必须实现 Scalable Vector Graphics 加载其他库。呈现 SVG 字符串有多种可能性。
一个简单的可能性是使用 svglib。安装 svglib:
pip install svglib
编写一个函数来解析和栅格化 SVG 字符串并创建一个 pygame.Surface
对象:
from svglib.svglib import svg2rlg
import io
def load_svg(svg_string):
svg_io = io.StringIO(svg_string)
drawing = svg2rlg(svg_io)
str = drawing.asString("png")
byte_io = io.BytesIO(str)
return pygame.image.load(byte_io)
但是,透明背景似乎有问题。这个主题有一个问题 How to make the png background transparent? #171。
另一种解决方案(显然速度较慢)是使用 CairoSVG. With the function cairosvg.svg2png
, an Vector Graphics (SVG) 文件可以直接转换为 [便携式网络图形 (PNG)] 文件
安装CairoSVG.
pip install CairoSVG
编写一个将SVF文件转换为PNG的函数(ByteIO
)并创建一个pygame.Surface
对象可能如下所示:
import cairosvg
import io
def load_svg(filename):
new_bites = cairosvg.svg2png(url = filename)
byte_io = io.BytesIO(new_bites)
return pygame.image.load(byte_io)
另见 svgsurf.py。
最小示例:
from svglib.svglib import svg2rlg
import pygame
import io
def load_svg_svglib(svg_string):
svg_io = io.StringIO(svg_string)
drawing = svg2rlg(svg_io)
str = drawing.asString("png")
byte_io = io.BytesIO(str)
svg_surf = pygame.image.load(byte_io)
return svg_surf
def display_svg_figure(screen, svg_string):
surf = load_svg_svglib(svg_string)
screen.blit(surf, (0, 0))
background_colour = (255, 255, 255)
(width, height) = (900, 900)
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Display SVG')
screen.fill(background_colour)
svg_string='<svg height="100" width="500"><ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" /><ellipse cx="220" cy="50" rx="190" ry="20" style="fill:white" /></svg>'
display_svg_figure(screen, svg_string)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.flip()
我有一个用字符串表示的 SVG 图形
svg_string='<svg height="100" width="500"><ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" /><ellipse cx="220" cy="50" rx="190" ry="20" style="fill:white" /></svg>'
我想在Python发起的window上显示svg_string
表示的图形,即2个椭圆。
伪代码应该是这样的
import pygame
def display_svg_figure(screen, svg_string):
# Code that draws the rendered SVG string on
# the screen
pass
background_colour = (255, 255, 255)
(width, height) = (900, 900)
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Display SVG')
screen.fill(background_colour)
pygame.display.flip()
svg_string='<svg height="100" width="500"><ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" /><ellipse cx="220" cy="50" rx="190" ry="20" style="fill:white" /></svg>'
display_svg_figure(screen, svg_string)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
我基本上是在看方法的实现 display_svg_figure(screen,svg_string)
我也愿意使用非 pygame 库,只要它遵循以下简单接口并且可以将其包含在 pygame
中from SOME_LIBRARY import SOME_COMPONENT
svg_string="......"
SOME_COMPONENT.display(svg_string)
我已经看过 pynanosvg
但它不再受支持并且失败了,所以不能满足我的需要。
如何阅读 Scalable Vector Graphics (SVG) file is answered at SVG rendering in a PyGame application.
Pygame 2.0 版支持 SVG 文件。自版本 2.0.2 起,SDL Image 支持 SVG (Scalable Vector Graphics) files (see SDL_image 2.0). Therefore, with pygame version 2.0.1, SVG files can be loaded into a pygame.Surface
object with pygame.image.load()
from a stream (io.BytesIO
):
svg_string = '<svg height="100" width="500"><ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" /><ellipse cx="220" cy="50" rx="190" ry="20" style="fill:white" /></svg>'
pygame_surface = pygame.image.load(io.BytesIO(svg_string.encode()))
最小示例:
import pygame
import io
pygame.init()
window = pygame.display.set_mode((500, 200))
clock = pygame.time.Clock()
svg_string = '<svg height="100" width="500"><ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" /><ellipse cx="220" cy="50" rx="190" ry="20" style="fill:white" /></svg>'
pygame_surface = pygame.image.load(io.BytesIO(svg_string.encode()))
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill((255, 255, 255))
window.blit(pygame_surface, pygame_surface.get_rect(center = window.get_rect().center))
pygame.display.flip()
pygame.quit()
exit()
在 Pygame 2 之前,您必须实现 Scalable Vector Graphics 加载其他库。呈现 SVG 字符串有多种可能性。
一个简单的可能性是使用 svglib。安装 svglib:
pip install svglib
编写一个函数来解析和栅格化 SVG 字符串并创建一个 pygame.Surface
对象:
from svglib.svglib import svg2rlg
import io
def load_svg(svg_string):
svg_io = io.StringIO(svg_string)
drawing = svg2rlg(svg_io)
str = drawing.asString("png")
byte_io = io.BytesIO(str)
return pygame.image.load(byte_io)
但是,透明背景似乎有问题。这个主题有一个问题 How to make the png background transparent? #171。
另一种解决方案(显然速度较慢)是使用 CairoSVG. With the function cairosvg.svg2png
, an Vector Graphics (SVG) 文件可以直接转换为 [便携式网络图形 (PNG)] 文件
安装CairoSVG.
pip install CairoSVG
编写一个将SVF文件转换为PNG的函数(ByteIO
)并创建一个pygame.Surface
对象可能如下所示:
import cairosvg
import io
def load_svg(filename):
new_bites = cairosvg.svg2png(url = filename)
byte_io = io.BytesIO(new_bites)
return pygame.image.load(byte_io)
另见 svgsurf.py。
最小示例:
from svglib.svglib import svg2rlg
import pygame
import io
def load_svg_svglib(svg_string):
svg_io = io.StringIO(svg_string)
drawing = svg2rlg(svg_io)
str = drawing.asString("png")
byte_io = io.BytesIO(str)
svg_surf = pygame.image.load(byte_io)
return svg_surf
def display_svg_figure(screen, svg_string):
surf = load_svg_svglib(svg_string)
screen.blit(surf, (0, 0))
background_colour = (255, 255, 255)
(width, height) = (900, 900)
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Display SVG')
screen.fill(background_colour)
svg_string='<svg height="100" width="500"><ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" /><ellipse cx="220" cy="50" rx="190" ry="20" style="fill:white" /></svg>'
display_svg_figure(screen, svg_string)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.flip()