SVG图像镜像代码

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JMFS1119

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值