You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将SVG变换矩阵应用于文本字号?(Inkscape inkex场景)

如何将SVG变换矩阵应用到文本字号

我有一个带transform属性的SVG文本元素,需要将该变换应用到文本上。已通过将矩阵应用于坐标,成功得到元素正确变换后的x、y值,但无法将矩阵应用于单一值(即文本字号)。尝试将字号作为两个参数传入变换,但结果不正确。

使用的是Inkscape的inkex.transform模块中的apply_to_point函数。

补充代码片段:

selections = self.svg.selection
for s in selections:
    transStr = s.get('transform')
    if(transStr is not None):
        tr = inkex.transform.Transform(transStr)
        x = s.get('x')
        y = s.get('y')
        if(x is not None and y is not None):
            # apply transform to coordinates
            co = tr.apply_to_point((x, y))
            s.pop('transform')
            s.set('x', str(co[0]))
            s.set('y', str(co[1]))
            stStr = s.get('style')
            if(stStr is not None):
                style = inkex.styles.Style.parse_str(stStr)
                sizeStr = style.get('font-size')
                if(sizeStr is not None):
                    m = re.match('([0-9.]+)(.*)', sizeStr)
                    if(len(m.groups()) > 1):
                        size = m[1]
                        # apply transform to size 
                        # but this returns a tuple of 2 
                        # we need only one. 
                        # And even taking one element from tuple
                        # this doesn't work.
                        style['font-size'] = str(tr.apply_to_point((size, size)))
                s.set('style', style)

解决方案

apply_to_point是用来变换坐标点的,不能直接用来计算字号的缩放。要正确将变换矩阵的缩放效果应用到文本字号,需要提取变换矩阵中的缩放因子,再用该因子乘以原始字号。

SVG变换矩阵的结构为[a, b, c, d, e, f],其中:

  • x方向的缩放因子:scale_x = √(a² + c²)
  • y方向的缩放因子:scale_y = √(b² + d²)

对于水平文本,font-size控制的是文本的em高度,对应y方向的缩放,因此使用scale_y计算新字号即可;如果是均匀缩放,scale_x和scale_y数值相同,用任意一个均可。


修改后的代码

import re
import math
from inkex.transform import Transform
from inkex.styles import Style

selections = self.svg.selection
for s in selections:
    transStr = s.get('transform')
    if transStr is not None:
        tr = Transform(transStr)
        x = s.get('x')
        y = s.get('y')
        if x is not None and y is not None:
            # 应用变换到坐标
            co = tr.apply_to_point((x, y))
            s.pop('transform')
            s.set('x', str(co[0]))
            s.set('y', str(co[1]))
            
            stStr = s.get('style')
            if stStr is not None:
                style = Style.parse_str(stStr)
                sizeStr = style.get('font-size')
                if sizeStr is not None:
                    m = re.match(r'([0-9.]+)(.*)', sizeStr)
                    if m and len(m.groups()) > 1:
                        size_num = float(m[1])
                        unit = m[2]
                        
                        # 计算y方向的缩放因子(对应文本高度)
                        scale_y = math.sqrt(tr.b ** 2 + tr.d ** 2)
                        # 计算新字号
                        new_size = size_num * scale_y
                        
                        # 更新样式中的字号
                        style['font-size'] = f"{new_size}{unit}"
                
                s.set('style', style)

内容的提问来源于stack exchange,提问作者Loma Harshana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 05:27:27