如何在FabricJS中修复Inkscape SVG的缩放和旋转?

时间:2014-02-21 17:03:24

标签: javascript svg fabricjs inkscape

我在使用FabricJS缩放和旋转SVG图像方面遇到了一些麻烦。

我一直在为我的网站制作一个图标构建器。用户可以添加图层,为该图层选择形状,然后设置一些选项,如着色和笔触宽度。我填充了可能的“形状”,为了最大限度地提高形状复杂性,我使用的是我用Inkscape创建的SVG文件。我使用FabricJS中的loadSVGFromURL功能来处理将文件加载到画布上。

问题是当我将一些(似乎是最多)这些SVG加载到画布上然后尝试使用手柄来缩放和旋转图像时,渲染的结果不会按预期显示:Octagon SVG Image and Action Results

在该图像上,不要担心“切片”边缘,这只是编辑器的边界。将octogon.svg加载到画布后,它看起来正确。当我旋转时,它会搞砸。我向右和向下旋转,图像向左上方移动。然后,当我缩放时,它会向相反方向垂直移动。

我尝试过以编程方式更改这些设置,但行为方式相同。我在这里和新闻组讨论中已经阅读了几个已发布的问题,但没有什么能让我得到一个可靠的解决方案

一个非常接近的解决方案是使用优化工具删除一些结构显然不太受欢迎的转换数据(该工具在http://petercollingridge.appspot.com/中找到)。它似乎有效,但不是每张图片都包括在内。实际上,无论我选择哪种优化选项,该工具都会改变八角形,因此它并不是真正可用作八角形的。该工具也是这个现有问题的参考:10470508(issue-with-svg-display-rendering-in-fabric-js)

我已经以各种格式从Inkscape中保存了SVG:Inkscape SVG,普通SVG和优化SVG - 没有任何区别。我还尝试在导出所有这些格式之前简化路径 - 再次,没有区别(虽然对于某些形状,这看起来确实有用)。

我已经阅读了许多错误以及与Kangax参与GitHub的相关讨论并尝试了centeredRotation属性和对象上的原点。

我注意到Inkscape的x,y为0,0是左下角,我认为这有点奇怪,并且认为可能至少与缩放有关。为了从这个角度尝试修复它,我在对象上设置flipY,但这根本不起作用。它出现在编辑小组的上方。它几乎感觉变换点位于边界框之上的某处。但我无法验证。我检查的所有设置似乎都设置正确。

我确实尝试过在Illustrator中制作的六边形,它看起来很有效,但我没有掌握Illustrator,并说这是一个“解决方案”有点不受欢迎。也许这更好地记录为一个bug,但是对于所有相关的聊天,我有点希望它已经解决,我只是没有找到正确的设置或流程组合。我真的需要能够使用Inkscape。 Kangax指出Inkscape SVG对FabricJS来说更麻烦,但他接着说他们正在变得更好。所以也许这有助于向前迈出一步。

我还在GitHub上查看了代码本身,但似乎无法确定我需要更改以修复此问题;但是,我不确定故障点在哪里 - 结构,我的设置或我的SVG文件。

更新2/21/2014美国东部时间下午10:27

我开始深入研究SVG文件结构,比较那些给我带来麻烦的文件结构。肯定看起来问题是由于路径,容器或其他对象标签上存在“transform”属性。我尝试的优化过程已经删除了它们,但我仍然没有找到一个适用于所有情况的可靠解决方案。我会告诉你更新。

3 个答案:

答案 0 :(得分:0)

我对fabricjs和Inkscape了解不多,但是使用svg DOM,以下内容将适用于单独应用于元素的旋转和缩放转换:也许你可以应用它。如果要旋转+缩放元素,可以附加变换字符串或使用变换矩阵。希望这有帮助

var bb=elem.getBBox()
var bbx=bb.x
var bby=bb.y
var bbw=bb.width
var bbh=bb.height
var cx=bbx+.5*bbw
var cy=bby+.5*bbh
//----rotate from center of elem---
elem.setAttribute("transform","rotate(angle "+cx+" "+cy+")") 
//---scale: translate center to(0,0)+scale+translate back---
elem.setAttribute("transform","translate("+cx+" "+cy+")scale(myScale)translate("+(-cx)+" "+(-cy+")")

答案 1 :(得分:0)

使用 XMLHttpRequest 将svg文件作为xml加载是否有利?然后,您可以将它们视为xml,对它们进行处理,然后通过克隆它们将它们作为SVG插入。 我觉得很无缝。您可以从XMLdoc中提取元素,并仅通过克隆它们将它们作为svg插入。您还可以在html中包含DIV,并将整个xml响应文本作为innerHTML转储到其中。然后一切都可用于DOM工作。

var  XMLdoc
function loadSVGasXML()
{
    var SVGFile="my.svg"
    var loadXML = new XMLHttpRequest;
    function handler()
    {
        if(loadXML.readyState == 4 && loadXML.status == 200)
        {
                //---responseText---
                var xmlString=loadXML.responseText
                //---mySVGDiv.innerHTML=xmlString ---
                //---DOMParser---
                var parser = new DOMParser();
                XMLdoc=parser.parseFromString(xmlString,"text/xml").documentElement ;
        }
    }
    if (loadXML != null)
    {
        loadXML.open("GET", SVGFile, true);
        loadXML.onreadystatechange = handler;
        loadXML.send();
    }
}

答案 2 :(得分:0)

与发布的其他问题一样,问题仍然存在于路径上的单个转换中。我发现的在线解决方案从来没有像我需要的那样好用;至少不是来自InkScape的SVG。从InkScape中将SVG保存为其他类型也不会影响最终结果。一些形状,当简化",很好;但是,它不够一致。所以,我开始着手开发解决方案。

在阅读SVG文件结构文档后,我专门创建了这个来处理InkScape SVG。有些SVG命令没有处理,但到目前为止,我还没有发现缺少命令的问题(仅仅由于时间而被排除)。

EvilEye Games - InkScape SVG Transform Remover

最后,我刚刚决定使用其他网站的一些免费SVG。所以这一切都不适合我。但是,我能够弄明白并解决问题。所以想想这可能会对其他人派上用场。它并不完美,但却能满足它的需要。