import xml.etree.ElementTree as ET
import os
from typing import Tuple
def get_canvas_size(svg_root) -> Tuple[float, float]:
"""获取SVG画布尺寸(优先viewBox,其次物理尺寸)"""
viewBox = svg_root.get('viewBox')
if viewBox:
x, y, width, height = map(float, viewBox.split())
return width, height # 直接使用viewBox定义的画布尺寸
width = float(svg_root.get('width', 100))
height = float(svg_root.get('height', 100))
return width, height
def process_svg(input_path: str, output_dir: str) -> None:
"""修正版:解决浏览器显示异常的镜像处理"""
try:
ET.register_namespace('', "http://www.w3.org/2000/svg")
ET.register_namespace('xlink', "http://www.w3.org/1999/xlink")
tree = ET.parse(input_path)
root = tree.getroot()
if not root.tag.endswith('svg'):
raise ValueError("无效的SVG文件")
# 获取画布尺寸(使用viewBox或物理尺寸)
canvas_width, canvas_height = get_canvas_size(root)
# 创建新组并应用**修正后的变换矩阵**
group = ET.Element('{http://www.w3.org/2000/svg}g')
# 核心修改:变换顺序改为 平移到右边界 → 镜像 → 修正原点
group.set('transform',
f'translate({canvas_width} 0) ' # 平移到右侧边界(水平镜像原点)
f'scale(-1 1) ' # 水平镜像
# 以下为可选垂直修正(根据是否需要上下翻转)
# f'translate(0 {canvas_height}) ' # 平移到下边界(垂直镜像原点)
# f'scale(1 -1) ' # 垂直镜像
)
# 移动可渲染元素(保留defs等元数据)
elements_to_move = [elem for elem in root
if elem.tag.split('}')[-1] not in ['defs', 'metadata', 'title', 'desc', 'style']]
for elem in elements_to_move:
group.append(elem)
# 重建根结构(保留原始属性+viewBox)
original_attrib = root.attrib.copy()
root.clear()
for elem in tree.findall('*'): # 恢复元数据顺序
if elem.tag.split('}')[-1] in ['defs', 'metadata', 'title', 'desc']:
root.append(elem)
root.append(group)
# 强制保留viewBox(避免物理尺寸冲突)
if 'viewBox' not in original_attrib:
root.set('viewBox', f'0 0 {canvas_width} {canvas_height}')
root.attrib.pop('width', None)
root.attrib.pop('height', None)
# 保存优化(美化格式+声明)
os.makedirs(output_dir, exist_ok=True)
filename = os.path.splitext(os.path.basename(input_path))[0]
output_path = os.path.join(output_dir, f"{filename}_fixed.svg")
rough_xml = ET.tostring(root, 'utf-8')
pretty_xml = rough_xml.decode().replace('ns0:', '').replace('\n', '').replace(' ', '') # 简化格式
with open(output_path, 'w', encoding='utf-8') as f:
f.write('<?xml version="1.0" encoding="UTF-8"?>\n' + pretty_xml)
print(f"✅ 修复完成:{output_path}")
except Exception as e:
print(f"❌ 处理失败:{str(e)}")
raise
if __name__ == "__main__":
input_svg = r"C:\Users\fushe\Desktop\buttonRight.svg"
output_folder = r"C:\Users\fushe\Desktop"
process_svg(input_svg, output_folder)
SVG图像镜像代码
最新推荐文章于 2025-04-30 11:28:26 发布