水平翻转 SVG 中的元素但保持其原始位置

flip an element inside SVG horizontally but keeps it's original position

我想在不改变原始位置的情况下翻转 SVG 元素(路径、线条、多段线、文本...)。例如

<div id="canvas" style="width: 550px; height: 550px">
    <svg version="1.2" baseProfile="tiny" id="Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 250 250" xml:space="preserve">
        <text id="text" transform="matrix(1 0 0 1 31.1271 199.1222)" fill="#561010" font-family="'Roboto-Regular'" font-size="25.3945px">Nom d’entreprise</text>
        <g>
            <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="76.157" y1="87.0921" x2="70.9488" y2="44.8529"> <stop offset="0.0233" style="stop-color:#E92460"></stop> <stop offset="0.4636" style="stop-color:#F05C4B"></stop> <stop offset="0.9517" style="stop-color:#F36D38"></stop> </linearGradient>
            <path transform="matrix(1 0 0 1 0 0)" fill="url(#SVGID_2_)" d="M51.75,55.77c-0.27-0.39,3.97-5.2,10.38-7.74c1.79-0.71,11.97-4.75,21.31,0.8
    c8.61,5.12,11.99,15.71,10.53,24.27c-2.38,13.95-17.76,23.37-22.24,20.72c-0.97-0.57-1.32-2.75-1.99-7.09
    c-1.81-11.84-1.68-20.54-1.68-20.54c0.05-3.05,0.19-4.38-0.61-6.25c-1.42-3.32-4.9-6.23-8.62-6.47
    C54.84,53.21,51.97,56.08,51.75,55.77z"></path>
        </g>
    </svg>
</div>

我尝试了各种解决方案,例如将 transform 更改为 matrix(-1 0 0 1 -100 0)。我也尝试添加属性 transform-origin="center".

我得到的只是一个放错地方的元素。我一直在尝试以下操作:

flipHorizontal(){
    let viewBox_array = this.getViewBox(); // this returns ['0', '0', '250', '250']
    let canvas_width = $("#canvas").width();
    this.selectedElements.forEach(element =>{
      let element_width = element.getBoundingClientRect().width
      element.setAttribute("transform-origin", "center")
      var matrix = element.transform.baseVal[0].matrix;
      matrix.a = (-1) * matrix.a
      let diff = (element_width / (canvas_width / Number(viewBox_array[2])) )* Math.sign(matrix.a);
      matrix.e += diff;
    });
    this.edit_done();
}

也尝试了以下

flipHorizontal(){
    this.selectedElements.forEach(element =>{
      element.setAttribute("transform-origin", "center")
      let bbox = element.getBBox();
      var matrix = element.transform.baseVal[0].matrix;
      matrix.a = (-1) * matrix.a

      matrix.e += Math.sign(matrix.a) * (bbox.width + bbox.x);
    });
    this.edit_done();
}

您可以使用唯一的 CSS 执行此操作,例如:

.logo_text--flipped, .logo_image--flipped {
    transform-origin: center center;
    transform: scaleX(-1);
}
<div id="canvas" style="width: 550px; height: 550px">
  <svg version="1.2" baseProfile="tiny" id="Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 250 250" xml:space="preserve">
<g class="logo_text logo_text--flipped">
  <text id="text" transform="matrix(1 0 0 1 31.1271 199.1222)" fill="#561010" font-family="'Roboto-Regular'" font-size="25.3945px">Nom d’entreprise</text>
</g>
<g class="logo_image logo_image--flipped">
  <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="76.157" y1="87.0921" x2="70.9488" y2="44.8529">
    <stop offset="0.0233" style="stop-color:#E92460"></stop>
    <stop offset="0.4636" style="stop-color:#F05C4B"></stop>
    <stop offset="0.9517" style="stop-color:#F36D38"></stop>
  </linearGradient>
  <path transform="matrix(1 0 0 1 0 0)" fill="url(#SVGID_2_)" d="M51.75,55.77c-0.27-0.39,3.97-5.2,10.38-7.74c1.79-0.71,11.97-4.75,21.31,0.8
    c8.61,5.12,11.99,15.71,10.53,24.27c-2.38,13.95-17.76,23.37-22.24,20.72c-0.97-0.57-1.32-2.75-1.99-7.09
    c-1.81-11.84-1.68-20.54-1.68-20.54c0.05-3.05,0.19-4.38-0.61-6.25c-1.42-3.32-4.9-6.23-8.62-6.47
    C54.84,53.21,51.97,56.08,51.75,55.77z"></path>
</g>
  </svg>
</div>

因此您可以创建一个特定的 class 并通过 JS 切换它

my answer here中所述,原地翻转所需的变换函数为:

translate(<minX+maxX>,0) scale(-1, 1)

因此,您的代码的工作版本可能如下所示:

function flipHorizontal(selectedElements) {
  selectedElements.forEach(element => {
    // Get the bounds of the element
    let bbox = element.getBBox();
    // Get the current transform attribute (if any) of the element
    let currentTransform = element.getAttribute("transform") || "";
    // Append translate and scale functions to the transform that will flip the element in place
    element.setAttribute("transform", currentTransform + ' translate('+(bbox.x + bbox.x + bbox.width) + ',0) scale(-1, 1)');
  });
}


let elementsToFlip = document.querySelectorAll("path, text");
flipHorizontal( elementsToFlip );
<div id="canvas" style="width: 550px; height: 550px">
    <svg version="1.2" baseProfile="tiny" id="Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 250 250" xml:space="preserve">
        <text id="text" transform="matrix(1 0 0 1 31.1271 199.1222)" fill="#561010" font-family="'Roboto-Regular'" font-size="25.3945px">Nom d’entreprise</text>
        <g>
            <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="76.157" y1="87.0921" x2="70.9488" y2="44.8529"> <stop offset="0.0233" style="stop-color:#E92460"></stop> <stop offset="0.4636" style="stop-color:#F05C4B"></stop> <stop offset="0.9517" style="stop-color:#F36D38"></stop> </linearGradient>
            <path transform="matrix(1 0 0 1 0 0)" fill="url(#SVGID_2_)" d="M51.75,55.77c-0.27-0.39,3.97-5.2,10.38-7.74c1.79-0.71,11.97-4.75,21.31,0.8
    c8.61,5.12,11.99,15.71,10.53,24.27c-2.38,13.95-17.76,23.37-22.24,20.72c-0.97-0.57-1.32-2.75-1.99-7.09
    c-1.81-11.84-1.68-20.54-1.68-20.54c0.05-3.05,0.19-4.38-0.61-6.25c-1.42-3.32-4.9-6.23-8.62-6.47
    C54.84,53.21,51.97,56.08,51.75,55.77z"></path>
        </g>
    </svg>
</div>