Svg 路径以一定角度镜像

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

我应该对绿色路径应用什么变换,使其绕轴旋转并位于蓝色虚线路径的同一侧?

我提到了this,它完美地适用于需要水平或垂直翻转且不位于某个角度的svg路径。但路径是有一定角度的;如何以编程方式在同一轴上旋转它们以达到所需的效果。

总而言之,我希望变换的效果能够在与蓝色路径相同的一侧开始和结束绿色路径。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 720">
  <rect id="bg" width="1280" height="720" fill="#EFEFEF"></rect>
  <g id="lineLeft">
    <line id="lineLeft" x1="100" y1="100" x2="100" y2="600" stroke="black" stroke-width="0.5"></line>
  </g>
  <g id="lineRight">
    <line id="lineRight" x1="600" y1="100" x2="600" y2="600" stroke="black" stroke-width="0.5"></line>
  </g>
  <g id="straightLineG">
    <line x1="100" y1="150" x2="600" y2="550" stroke="red" stroke-width="0.5"></line>
  </g>
  <g id="cpOne">
    <path id="1" d="M100,150.989L104.951,151.113L109.901,151.254L114.851,151.411L119.802,151.588L124.752,151.788L129.703,152.012L134.654,152.265L139.604,152.549L144.554,152.868L149.505,153.227L154.455,153.63L159.406,154.083L164.356,154.593L169.307,155.165L174.257,155.807L179.208,156.527L184.158,157.336L189.109,158.242L194.059,159.258L199.01,160.395L203.96,161.669L208.911,163.093L213.861,164.684L218.812,166.46L223.762,168.441L228.713,170.647L233.663,173.101L238.614,175.828L243.564,178.851L248.515,182.198L253.465,185.895L258.416,189.971L263.366,194.454L268.317,199.37L273.267,204.746L278.218,210.606L283.168,216.972L288.119,223.86L293.069,231.285L298.02,239.252L302.97,247.759L307.921,256.8L312.871,266.354L317.822,276.395L322.772,286.884L327.723,297.773L332.673,309.005L337.624,320.514L342.574,332.225L347.525,344.061L352.475,355.939L357.426,367.775L362.376,379.486L367.327,390.995L372.277,402.227L377.228,413.116L382.178,423.605L387.129,433.646L392.079,443.2L397.03,452.241L401.98,460.748L406.931,468.715L411.881,476.14L416.832,483.028L421.782,489.394L426.733,495.254L431.683,500.63L436.634,505.546L441.584,510.029L446.535,514.105L451.485,517.802L456.436,521.149L461.386,524.172L466.337,526.899L471.287,529.353L476.238,531.559L481.188,533.54L486.139,535.316L491.089,536.907L496.04,538.331L500.99,539.605L505.941,540.742L510.891,541.758L515.842,542.664L520.792,543.473L525.743,544.193L530.693,544.835L535.644,545.407L540.594,545.917L545.545,546.37L550.495,546.773L555.446,547.132L560.396,547.451L565.346,547.735L570.297,547.988L575.248,548.212L580.198,548.412L585.148,548.589L590.099,548.746L595.049,548.887L600,549.011" stroke="blue" fill="none" stroke-dasharray="3"></path>
  </g>
  <g id="cpTwo">
    <path id="2" d="M100,150L105,161.538L110,172.222L115,182.143L120,191.379L125,200L130,208.065L135,215.625L140,222.727L145,229.412L150,235.714L155,241.667L160,247.297L165,252.632L170,257.692L175,262.5L180,267.073L185,271.429L190,275.581L195,279.545L200,283.333L205,286.957L210,290.426L215,293.75L220,296.939L225,300L230,302.941L235,305.769L240,308.491L245,311.111L250,313.636L255,316.071L260,318.421L265,320.69L270,322.881L275,325L280,327.049L285,329.032L290,330.952L295,332.813L300,334.615L305,336.364L310,338.06L315,339.706L320,341.304L325,342.857L330,344.366L335,345.833L340,347.26L345,348.649L350,350L355,351.351L360,352.74L365,354.167L370,355.634L375,357.143L380,358.696L385,360.294L390,361.94L395,363.636L400,365.385L405,367.188L410,369.048L415,370.968L420,372.951L425,375L430,377.119L435,379.31L440,381.579L445,383.929L450,386.364L455,388.889L460,391.509L465,394.231L470,397.059L475,400L480,403.061L485,406.25L490,409.574L495,413.043L500,416.667L505,420.455L510,424.419L515,428.571L520,432.927L525,437.5L530,442.308L535,447.368L540,452.703L545,458.333L550,464.286L555,470.588L560,477.273L565,484.375L570,491.935L575,500L580,508.621L585,517.857L590,527.778L595,538.462L600,550" stroke="green" fill="none"></path>
  </g>
</svg>

javascript svg transform
1个回答
2
投票

您需要五个基本转换的列表:

  • 将起点转换为 (0,0):
    translate(-100,-150)
  • 旋转,使终点的y值为0。通过计算atan2(550-150, 600-100)可以发现:
    rotate(-38.6598)
  • 取消 y 值(绕 x 轴镜像):
    scale(1,-1)
  • 向后旋转:
    rotate(38.6598)
  • 翻译回来:
    translate(100,150)

您可以将其作为变换列表应用到路径,但是需要从右到左排序

translate(100,150) rotate(38.6598) scale(1,-1) rotate(-38.6598) translate(-100,-150)

额外技巧: 这个转换列表可以合并到一个矩阵中,你甚至不需要自己做:

const cpTwo = document.getElementById('cpTwo');
cpTwo.setAttribute('transform', 'translate(100,150) rotate(38.66)scale(1,-1) rotate(-38.66) translate(-100,-150)';
cpTwo.transform.baseVal.consolidate();
cpTwo.getAttribute('transform')

> "matrix(0.219512, 0.97561, 0.97561, -0.219512, -68.2927, 85.3659)"

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 720">
  <rect id="bg" width="1280" height="720" fill="#EFEFEF"></rect>
  <g id="lineLeft">
    <line id="lineLeft" x1="100" y1="100" x2="100" y2="600" stroke="black" stroke-width="0.5"></line>
  </g>
  <g id="lineRight">
    <line id="lineRight" x1="600" y1="100" x2="600" y2="600" stroke="black" stroke-width="0.5"></line>
  </g>
  <g id="straightLineG">
    <line x1="100" y1="150" x2="600" y2="550" stroke="red" stroke-width="0.5"></line>
  </g>
  <g id="cpOne">
    <path id="1" d="M100,150.989L104.951,151.113L109.901,151.254L114.851,151.411L119.802,151.588L124.752,151.788L129.703,152.012L134.654,152.265L139.604,152.549L144.554,152.868L149.505,153.227L154.455,153.63L159.406,154.083L164.356,154.593L169.307,155.165L174.257,155.807L179.208,156.527L184.158,157.336L189.109,158.242L194.059,159.258L199.01,160.395L203.96,161.669L208.911,163.093L213.861,164.684L218.812,166.46L223.762,168.441L228.713,170.647L233.663,173.101L238.614,175.828L243.564,178.851L248.515,182.198L253.465,185.895L258.416,189.971L263.366,194.454L268.317,199.37L273.267,204.746L278.218,210.606L283.168,216.972L288.119,223.86L293.069,231.285L298.02,239.252L302.97,247.759L307.921,256.8L312.871,266.354L317.822,276.395L322.772,286.884L327.723,297.773L332.673,309.005L337.624,320.514L342.574,332.225L347.525,344.061L352.475,355.939L357.426,367.775L362.376,379.486L367.327,390.995L372.277,402.227L377.228,413.116L382.178,423.605L387.129,433.646L392.079,443.2L397.03,452.241L401.98,460.748L406.931,468.715L411.881,476.14L416.832,483.028L421.782,489.394L426.733,495.254L431.683,500.63L436.634,505.546L441.584,510.029L446.535,514.105L451.485,517.802L456.436,521.149L461.386,524.172L466.337,526.899L471.287,529.353L476.238,531.559L481.188,533.54L486.139,535.316L491.089,536.907L496.04,538.331L500.99,539.605L505.941,540.742L510.891,541.758L515.842,542.664L520.792,543.473L525.743,544.193L530.693,544.835L535.644,545.407L540.594,545.917L545.545,546.37L550.495,546.773L555.446,547.132L560.396,547.451L565.346,547.735L570.297,547.988L575.248,548.212L580.198,548.412L585.148,548.589L590.099,548.746L595.049,548.887L600,549.011" stroke="blue" fill="none" stroke-dasharray="3"></path>
  </g>
  <g id="cpTwo" transform="matrix(0.219512, 0.97561, 0.97561, -0.219512, -68.2927, 85.3659)">
    <path id="2" d="M100,150L105,161.538L110,172.222L115,182.143L120,191.379L125,200L130,208.065L135,215.625L140,222.727L145,229.412L150,235.714L155,241.667L160,247.297L165,252.632L170,257.692L175,262.5L180,267.073L185,271.429L190,275.581L195,279.545L200,283.333L205,286.957L210,290.426L215,293.75L220,296.939L225,300L230,302.941L235,305.769L240,308.491L245,311.111L250,313.636L255,316.071L260,318.421L265,320.69L270,322.881L275,325L280,327.049L285,329.032L290,330.952L295,332.813L300,334.615L305,336.364L310,338.06L315,339.706L320,341.304L325,342.857L330,344.366L335,345.833L340,347.26L345,348.649L350,350L355,351.351L360,352.74L365,354.167L370,355.634L375,357.143L380,358.696L385,360.294L390,361.94L395,363.636L400,365.385L405,367.188L410,369.048L415,370.968L420,372.951L425,375L430,377.119L435,379.31L440,381.579L445,383.929L450,386.364L455,388.889L460,391.509L465,394.231L470,397.059L475,400L480,403.061L485,406.25L490,409.574L495,413.043L500,416.667L505,420.455L510,424.419L515,428.571L520,432.927L525,437.5L530,442.308L535,447.368L540,452.703L545,458.333L550,464.286L555,470.588L560,477.273L565,484.375L570,491.935L575,500L580,508.621L585,517.857L590,527.778L595,538.462L600,550" stroke="green" fill="none"></path>
  </g>
</svg>

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