提供x,y,宽度和高度值,如何获得从中心缩放的svg变换矩阵

时间:2019-01-17 21:48:23

标签: php svg imagemagick

我有一个使用php和imagemagick从svg生成gif文件的代码。 以下是示例svg代码。 假设要通过将比例转换比例值从0过渡到1来创建动画,如何使用svg元素属性x,y,width,height获得将转换原点居中的转换矩阵?

注意:我使用php进行所有计算,并使用Imagemagick转换为栅格,我认为它不支持css转换起源样式。

当前,过渡从左侧开始。我想使用矩阵对其进行翻译。

下面的链接是当前实现的示例gif https://i.imgur.com/juMX3uD.gifv

转换后的SVG

<svg xmlns="http://www.w3.org/2000/svg" class="layer" overflow="visible" 
stroke="none" stroke-width="0" preserveAspectRatio="none" 
id="layer_1547759965149_0506449632092969" width="135.24545454545" 
height="110.9375" x="86.896363636365" y="84.286250000001"><g 
    id="translateLayer" transform="matrix(1 0 0 1 0 0)"><g id="effectLayer" 
transform="rotate(44.596407613288 67.622727272727 55.46875)" 
fill="#FF4400"><svg viewBox="0 0 657.01 569" width="100%" height="100%" 
preserveAspectRatio="none" overflow="hidden"><g id="Layer_2" data- 
name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon points="0 569 
328.49 0 657.01 569 0 569"/></g></g></svg></g></g></svg>

转换发生在这里

<g id="translateLayer" transform="matrix(1 0 0 1 0 0)"></g>

2 个答案:

答案 0 :(得分:0)

如果我理解正确,那么您只想应用特定的转换,而无需通过设置viewBox来更改SVG的用户坐标系,这会变得更加容易。

原点是三角形的中心点。在这种情况下,这是图像的一半width和2/3 height

那么,为什么不仅仅应用后续的变换而不是努力进行矩阵计算呢?而且rotation函数甚至带有原点参数。

    var
      svg = document.getElementById('layer_1547759965149_0506449632092969'),
      sca = svg.getElementById('translateLayer'),
      rot = svg.getElementById('effectLayer'),
      deg = 0,

      cx = svg.getAttribute('width') / 2,
      cy = svg.getAttribute('height') * 2/3
    ;

    function rotate()
    {
      deg++;
      let scale = 1 + Math.sin(deg/180*Math.PI);
      rot.setAttribute('transform',  (()=>`rotate(${deg} ${cx} ${cy})`)());
      sca.setAttribute('transform',  (()=>`translate(${cx} ${cy}) scale(${scale} ${scale}) translate(-${cx} -${cy})`)());
    }
    setInterval(rotate, 50);
    <svg xmlns="http://www.w3.org/2000/svg" class="layer" id="layer_1547759965149_0506449632092969"
         overflow="visible"
         stroke="none" stroke-width="0" preserveAspectRatio="none"
         width="135.24545454545" height="110.9375"
         x="86.896363636365" y="84.286250000001">
      <!--<g id="translateLayer" transform="matrix(0 67.622727272725 0  0 73.95833333333333   0)">-->
      <g id="translateLayer" transform="matrix(2 0 0 2 0.5 0.5)" transform-origin(200,100)>
        <g id="effectLayer"
           fill="#FF4400">
          <svg viewBox="0 0 657.01 569" width="100%" height="100%"
               preserveAspectRatio="none" overflow="hidden">
            <g id="Layer_2" data-name="Layer 2">
              <g id="Layer_1-2" data-name="Layer 1">
                <polygon points="0 569  328.49 0   657.01 569   0 569"/>
              </g>
            </g>
          </svg>
        </g>
      </g>
    </svg>

答案 1 :(得分:0)

经过数小时的代码争夺,我得到了想要的解决方案。

下面是我实现的最终矩阵计算

x = (x/2);
y = (y/2);
matrix(scaleX 0 0 scaleY (x-scaleX*x) (y-scaleY*y));

https://i.imgur.com/qAaZ1Tl.gifv