提供 x,y,width 和 height 值,我如何获得从中心缩放的 svg 变换矩阵

Posted

技术标签:

【中文标题】提供 x,y,width 和 height 值,我如何获得从中心缩放的 svg 变换矩阵【英文标题】:Providing the x,y,width and height value, how do I get the svg transform matrix that scales from center 【发布时间】:2019-06-12 04:13:31 【问题描述】:

我有一个使用 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- preserveAspectRatio="none" 
id="layer_1547759965149_0506449632092969"  
 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"   
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>

转变发生在这里

&lt;g id="translateLayer" transform="matrix(1 0 0 1 0 0)"&gt;&lt;/g&gt;

【问题讨论】:

我认为应该有一些 transform-origin 属性。但是,要获得具有“内置”原点的变换矩阵,您通常平移(移动)系统以将预期的变换原点设置为 (0;0),执行所有其他变换并将其移回(负平移) .通过按变换顺序将所有矩阵相乘,将所有步骤合并为一个矩阵。 en.wikipedia.org/wiki/Matrix_multiplication 您还可以将视口设置为在中心具有原点。 (我对 SVG 的了解不多,但我熟悉 VR 3D 开发。) 我猜这是css属性。我已经说过光栅化库 imagemagick 目前不解释 css 值。看看包含的 GIF 链接。我希望缩放从 center 转换。这可以使用矩阵转换来实现,但我只是不知道如何计算它。如果可能,提供示例 php 或 js 代码 我记得你实际上可以以某种方式将 SVG 的视口设置为负上/左。 @Quasimodo'sclone,查看 gif 以更好地理解。 transform="matrix(1 0 0 1 0 0)" 是动画发生的地方。刻度值随时间改变。可以使用平移矩阵值来实现中心原点。我的问题是如何得到它,因为矩阵不太好 【参考方案1】:

如果我理解正确,您只想通过设置 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- preserveAspectRatio="none"
          
         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"  
               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>

【讨论】:

【参考方案2】:

在与代码斗争了几个小时后,我得到了我正在寻找的解决方案。

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

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

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

【讨论】:

以上是关于提供 x,y,width 和 height 值,我如何获得从中心缩放的 svg 变换矩阵的主要内容,如果未能解决你的问题,请参考以下文章

canvas基础

如何设置wms参数(bbox、width、height、x、y)

h5 Canvas矩形的绘制

将当前photoshop层x,y,width,height复制到As3代码

canvas API

如何按 x,y,width,height 裁剪文件夹中的所有图像,调整它们的大小,然后保存它们?