SVG 在 Web 浏览器中与 Adobe Illustrator 中的渲染方式不同

问题描述 投票:0回答:1

我已经使用

geojson
通过 Python 脚本从
svgwrite
创建了一个 SVG。导出的 SVG 文件可以在 Web 浏览器(Safari、FireFox、Chrome 等)中正确呈现,但在 Adobe Illustrator 中看起来不正确。具体来说,并非 geojson 中的所有多边形都是在 Illustrator 中绘制的。我使用 W3C Validator 进行了检查,SVG 看起来没问题。对这里发生的事情有什么想法吗?

链接到 SVG

下面是在网络浏览器中呈现的图像:

下图是在 Illustrator 中渲染的图像:

生成 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>
python html svg gis adobe
1个回答
0
投票

Illustrator 似乎对任何路径都有 32,000 点的限制。之后,路径将被截断。 Web 浏览器和 Illustrator 渲染 SVG 的方式之间的差异与超过 40,000 个点的大路径有关。最终的解决方案是使用

geopandas
简化功能来简化路径的几何形状。

© www.soinside.com 2019 - 2024. All rights reserved.