提问人:drm1217 提问时间:11/16/2023 最后编辑:drm1217 更新时间:11/17/2023 访问量:44
SVG 在 Web 浏览器中的渲染方式与 Adobe Illustrator 不同
SVG renders differently in web browsers vs Adobe Illustrator
问:
我使用 Python 脚本从 a 创建了一个 SVG。导出的 SVG 文件在 Web 浏览器(Safari、FireFox、Chrome 等)中正确呈现,但在 Adobe Illustrator 中看起来不正确。具体而言,并非 geojson 中的所有多边形都是在 Illustrator 中绘制的。我使用 W3C Validator 进行了检查,SVG 看起来没问题。关于这里发生了什么的任何想法?geojson
svgwrite
生成 SVG 的代码:
import svgwrite
import geopandas
from dotenv import dotenv_values
from os import listdir
from os.path import isfile, join
style = '''
g {
stroke-linejoin: bevel;
fill: none;
}
path {
stroke: #000000;
stroke-width: 1000px;
}
.example-ranges {
fill: #43AF6E;
}
.latin-american-boundaries {
stroke-width: 2000px
}
'''
class Map:
def __init__(self, name:str, scale:int=1, epsg:str='2163'):
self.name = name
self.base_path = dotenv_values(".env")["FILE_PATH"]
self.scale = scale
self.epsg = epsg
self.data_path = join(self.base_path, self.name)
self.gdfs = self.get_gdfs()
self.minx, self.miny, self.maxx, self.maxy = self.get_bounds()
self.dwg = self.init_drawing()
def get_gdfs(self) -> list:
print(self.data_path)
gdfs = []
for file in listdir(self.data_path):
if file.endswith('.geojson'):
gdf = geopandas.read_file(join(self.data_path, file))
gdfs.append({
'name': file.split('.')[0],
'gdf': gdf.to_crs(f'epsg:{self.epsg}')
})
return gdfs
def get_bounds(self):
minx = miny = maxx = maxy = 0
for gdf in self.gdfs:
_minx, _miny, _maxx, _maxy = [x * self.scale for x in gdf['gdf'].total_bounds]
minx = _minx if _minx < minx else minx
miny = _miny if _miny < miny else miny
maxx = _maxx if _maxx > maxx else maxx
maxy = _maxy if _maxy > maxy else maxy
return [minx, miny, maxx, maxy]
def get_viewbox(self):
return f'0 {0 - (self.maxy - self.miny)} {self.maxx - self.minx} {self.maxy - self.miny}'
def init_drawing(self):
return svgwrite.Drawing(
f'{self.base_path}/{self.name}.svg',
height='100%',
width='100%',
viewBox=self.get_viewbox(),
id='map'
)
def trans(self, coord: float, type: str):
if type == 'x':
m = (coord * self.scale) - self.minx
if type == 'y':
m = 0 - (coord * self.scale - self.miny)
return round(m, 4)
def add_path(self, coords: list, lyr):
data = [f"{(self.trans(x, 'x'))} {self.trans(y, 'y')}" for x, y in coords]
path_data = "M " + " ".join(data) + " Z"
path = self.dwg.path(
d=path_data,
)
path.scale(self.scale)
lyr.add(path)
def add_layer(self, gdf):
lyr = svgwrite.container.Group(class_=gdf['name'], id=gdf['name'])
for feature in gdf['gdf'].iterrows():
if 'name' in feature[1]:
group = svgwrite.container.Group(id=name.replace(' ', '-'))
else:
group = svgwrite.container.Group()
name = 'feature' if 'name' not in feature[1] else feature[1]['name']
print(feature)
geometry = feature[1]['geometry']
if geometry.geom_type == 'Polygon':
coordinates = geometry.exterior.coords
self.add_path(coordinates, group)
if geometry.geom_type == 'MultiPolygon':
coordinates_list = [list(x.exterior.coords) for x in geometry.geoms]
for coordinates in coordinates_list:
self.add_path(coordinates, group)
lyr.add(group)
self.dwg.add(lyr)
def save(self):
for gdf in self.gdfs:
self.add_layer(gdf)
self.dwg.embed_stylesheet(style)
self.dwg.save()
map = Map('north-america')
map.save()
SVG 代码摘录:
<?xml version="1.0" encoding="utf-8"?>
<svg baseProfile="full" height="100%" id="map" version="1.1"
viewBox="0 -5970769 6238439 5970769" width="100%"
xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs />
<g class="example-ranges" id="example-ranges">
<path
d="M 3105142.9506 -32938.6211 3094302.0224 -55180.2184 3087064.7285 -71713.278 3083023.7257 -82910.1436 3077742.3081 -92125.3977 3075637.6998 -96798.1838 3073004.9855 -99981.1093 3069727.7491 -102145.3881 3067417.1429 -103646.6451 3062078.0695 -103681.8678 3058193.7701 -102357.0232 3058289.4769 -100060.4703 3056614.3077 -99070.8656 3055978.9745 -79024.0893 3056365.7161 -63845.524 3054521.8344 -61724.582 3052682.3899 -58166.3599 3052034.982 -56066.8608 3050956.097 -52567.4711 3049575.3355 -50437.383 3049661.4522 -24864.9451 3051467.61 -22634.6884 3053977.8979 -21125.0244 3058801.1988 -16944.8917 3061152.127 -13353.6409 3064178.4849 -11173.6045 3068575.4161 -11356.2774 3074532.3332 -9298.3574 3078629.532 -7296.0449 3083269.1544 -5050.691 3092407.102 -4267.8405 3103568.6482 -5121.7845 3105142.9506 -32938.6211 Z" />
<path
d="M 3031630.1111 -196686.7707 3024334.0946 -198958.4428 3017595.1924 -203032.9032 3003786.6803 -204054.8141 3001343.6298 -201778.063 3001409.7627 -185564.694 3003357.8919 -174763.7179 3005708.8461 -169319.2759 3011607.3284 -165008.2374 3018467.6138 -162913.5004 3026231.6627 -164418.5914 3034477.2638 -164558.9579 3038479.7485 -159973.6944 3043334.3581 -155225.2776 3051830.7676 -154388.1375 3061332.9853 -154781.2864 3064116.1069 -159053.3257 3067955.731 -163368.9042 3067373.294 -187482.2938 3062778.647 -191049.5923 3057329.5235 -194779.2478 3054465.6944 -197429.3134 3046230.8649 -196891.6727 3042543.3594 -193971.2508 3037056.6788 -193547.8044 3031630.1111 -196686.7707 Z" />
<path
d="M 4861989.6231 -483370.5556 4858819.9277 -483156.6887 4857251.5424 -480416.6511 4854081.7307 -480203.1023 4852513.398 -477463.3235 4854114.7316 -474936.6986 4852546.302 -472196.7832 4849376.6847 -471983.887 4847808.3049 -469244.2286 4849409.3967 -466717.0718 4847840.9214 -463977.2752 4849441.5997 -461449.6458 4852610.5811 -461661.8727 4854179.2027 -464402.0636 4857348.0627 -464614.6057 4858916.7345 -467355.0532 4862085.4774 -467567.91 4863654.2025 -470308.6145 4866822.8232 -470521.7872 4868391.5967 -473262.7505 4866791.604 -475790.146 4868360.2796 -478530.974 4871529.0931 -478744.8017 4873097.8149 -481485.8903 4871497.5785 -484012.7558 4868328.4487 -483798.5895 4866759.8717 -481057.8963 4863590.6169 -480844.0481 4861989.6231 -483370.5556 Z" />
...
</g>
</svg>
答:
0赞
drm1217
11/17/2023
#1
Illustrator 似乎对任何路径都有 32,000 个点的限制。之后,路径被截断。Web 浏览器和 Illustrator 渲染 SVG 的方式之间的差异与一条 +40,000 点的大路径有关。最终的解决方案是使用 simplify 函数简化路径的几何形状。geopandas
评论