修改SVG路径元素的d属性数据,使生成的路径翻转

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

我有一个 SVG,其中包含一个绘制特定形状的

<path>
元素。该路径的坐标包含在路径的
'd'
属性值中。我需要这个形状水平翻转。当我尝试在 Adobe Illustrator 中完成此操作(例如使用 Reflect 工具)时,我在
'd'
属性值中获得双倍的数据大小,因此 SVG 文件的大小也增加了一倍,这实在是太痛苦了。我可以使用
transform
scale
函数来翻转形状,而不更改
'd'
中的坐标,但随后我会增加渲染时间和 CPU 使用率,因为我为浏览器或渲染 SVG 的软件添加了额外的工作。 合乎逻辑的做法是将
'd'
内的坐标本身更改为其“相反”,以实现形状的翻转。

我可以编写一个脚本来执行此操作,但可惜我不知道这些坐标的存储格式以及它们实际代表的内容。既有字母也有数字。

所以,我的问题是,如何更改

<path>
元素的
'd'
的坐标以实现整个形状的水平翻转?

这是我用于说明的示例 SVG:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px">

  <path id="example" class="st0" d="M492 534h-96q-37 0 -53.5 -12.5t-30.5 -50.5q-20 -54 -44 -165q-17 -79 -17 -105q0 -49 38 -58q17 -3 51 -3h67q41 0 56 7.5t23 32.5h27l-24 -106q-10 -42 -27 -58q-18 -15 -50 -19t-139 -4q-89 0 -128 5.5t-63 21.5q-54 35 -54 122q0 53 25 177q31 146 62 218t76 101 t124 29h258l-18 -80q-7 -34 -19 -43.5t-44 -9.5z"/>

</svg>
css svg vector adobe-illustrator
1个回答
0
投票

这里有一个如何翻转路径的示例。我在两个不同的函数中执行此操作,因为

moveElm()
在其他情况下可能很有用。对于这两个函数来说,数学并不难,基本上只是理解 d 属性中不同命令的作用即可。实现并不完整,但它适用于问题中给出的示例。

这个问题没有说明您想使用哪种编程语言。我在示例中使用的唯一特定语言是getBBox()。在Python中,你可以在包svgpathtools中找到类似的东西,在那里你可以找到方法

path.bbox()
(参见这个答案:https://stackoverflow.com/a/76076555/322084)。找到路径的位置和大小对于移动(和缩放)路径是必要的。

let path = document.getElementById('example');
let path_bbox = path.getBBox();
let x = Math.round(path_bbox.width + 2 * path_bbox.x);

flipElm(path);
moveElm(path, x, 0);

function moveElm(path_elm, x, y){
  let d = path_elm.getAttribute('d');
  let regexp = /([a-zA-Z])([\s\d\-\.]*)/g;
  let new_d = [...d.matchAll(regexp)].map(command => {
    let arr = command[2].trim().split(/\s/).map(val => parseFloat(val));
    let return_arr = arr;
    switch(command[1]){
      case 'M':
      case 'L':
      case 'H':
      case 'V':
      case 'Q':
      case 'T':
        return_arr = [arr[0] + x, arr[1] + y];
        break;
      case 'z':
      case 'Z':
        return_arr = [];
        break;
    }
    return `${command[1]}${return_arr.join(' ')}`;
  }).join(' ');
  path_elm.setAttribute('d', new_d);
}

function flipElm(path_elm) {
  let d = path_elm.getAttribute('d');
  let regexp = /([a-zA-Z])([\s\d\-\.]*)/g;
  let new_d = [...d.matchAll(regexp)].map(command => {
    let arr = command[2].trim().split(/\s/).map(val => parseFloat(val));
    let return_arr = [];
    switch (command[1]) {
      case 'A':
      case 'a':
        return_arr = arr.map((num, i) => "not implemented");
        break;
      case 'z':
      case 'Z':
        return_arr = [];
        break;
      default:
        return_arr = arr.map((num, i) => (i % 2) ? num : num * -1);
        break;
    }
    return `${command[1]}${return_arr.join(' ')}`;
  }).join(' ');
  path_elm.setAttribute('d', new_d);
}
svg {
  border: solid thin black;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -10 600 680" height="200">
  <path class="st0" d="M492 534h-96q-37 0 -53.5 -12.5t-30.5 -50.5q-20 -54 -44 -165q-17 -79 -17 -105q0 -49 38 -58q17 -3 51 -3h67q41 0 56 7.5t23 32.5h27l-24 -106q-10 -42 -27 -58q-18 -15 -50 -19t-139 -4q-89 0 -128 5.5t-63 21.5q-54 35 -54 122q0 53 25 177q31 146 62 218t76 101 t124 29h258l-18 -80q-7 -34 -19 -43.5t-44 -9.5z"/>
</svg>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -10 600 680" height="200">
  <path id="example" class="st0" d="M492 534h-96q-37 0 -53.5 -12.5t-30.5 -50.5q-20 -54 -44 -165q-17 -79 -17 -105q0 -49 38 -58q17 -3 51 -3h67q41 0 56 7.5t23 32.5h27l-24 -106q-10 -42 -27 -58q-18 -15 -50 -19t-139 -4q-89 0 -128 5.5t-63 21.5q-54 35 -54 122q0 53 25 177q31 146 62 218t76 101 t124 29h258l-18 -80q-7 -34 -19 -43.5t-44 -9.5z"/>
</svg>

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