用getCTM理解SVG变换矩阵

时间:2017-03-19 12:17:19

标签: javascript svg matrix transformation mathml

我一直在SVG元素上使用简单的transform translate。现在我将转换转换为矩阵(并在此过程中拉动我的头发)。

SVG元素上,在click上,我使用基于当前pageX&的简单变换转换渲染元素。 pageY(鼠标坐标)。

<svg width="1366" height="612" class="svg" viewBox="-78.48 43.82 752.30 337.05" xmlns="http://www.w3.org/2000/svg">
  <g class="elementParent">
    <g id="cry20Cyc_0.d7h" class="ele" data-action="ele" transform="translate(269.013,169.974)">
      <rect x="0" y="0" width="44" height="44" opacity="1" fill="#d1d1d1" stroke-width="1" vector-effect="non-scaling-stroke" class="selectRect"></rect>
      <path d="M0,22c0,12.2,9.9,22,22,22s22-9.8,22-22S34.2,0,22,0S0,9.9,0,22" fill="#482956"></path>
    </g>
  </g>
</svg>

请注意g上的翻译(269.013,169.974)。当我打电话给getCTM()时,我会得到这个相当重要的价值:

  SVGMatrix { a: 1.8157544136047363, b: 0, c: 0, d: 1.8157544136047363, e: 630.9659423828125, f: 229.06468200683594 }

根据我的理解,矩阵中的值&#39; a&#39; &安培; &#39; d&#39;代表缩放。但是,我还没有应用任何缩放,这个值来自哪里?

当我在元素上运行transform时。变换数组返回更合理的值:

SVGAnimatedTransformList { 
  baseVal: SVGTransformList[1], // {a:1 b:0 c:0 d:1 e:269.013 f:169.974} 
  animVal: SVGTransformList[1] }

我的推定是否正确getCTM可能会将viewbox值合并到getCTM的总输出中?

我的主要问题是如何将鼠标位置pageX pageY转换为元素的正确矩阵值,同时考虑到viewbox&amp;在翻译之前,元素必须按比例缩放。

更新: 我已经发现是的,getCTM确实包含了视图框值以返回CTM。回想起来,它非常有意义。现在,如果有人可以帮助合并鼠标坐标和数学扩展到getCTM输出,这将是伟大的:)

1 个答案:

答案 0 :(得分:1)

我知道这有点晚了,但最近类似的问题引起了我的注意。我修改了原始getCTM的返回值,并将其添加到原型中,如下所示:

!function(prt){
    prt._getAbsoluteCTM = function(){
        var owner = this.ownerSVGElement || this,
            height = owner.height.baseVal.value,
            width = owner.width.baseVal.value,
            viewBoxRect = owner.viewBox.baseVal,
            vHeight = viewBoxRect.height,
            vWidth = viewBoxRect.width;
        if(!vWidth || !vHeight){
            return this.getCTM();
        }
        var sH = height/vHeight,
            sW = width/vWidth,
            matrix = owner.createSVGMatrix();
        matrix.a = sW;
        matrix.d = sH
        var realCTM = this.getCTM().multiply(matrix.inverse());
        realCTM.e = realCTM.e/sW + viewBoxRect.x;
        realCTM.f = realCTM.f/sH + viewBoxRect.y;
        return realCTM;
    }
}(SVGGraphicsElement.prototype);

用法是:element._getAbsoluteCTM()并确保在绘图之前包含polyfill。

如果检测到viewBox属性,它将返回“absolute CTM”,否则它将返回与element.getCTM相同的值

这是一个最小的示例,您可以使用检查器上的值: https://jsfiddle.net/ibowankenobi/1mmh7rs6/6/