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

Posted

技术标签:

【中文标题】如何修复 FabricJS 中 Inkscape SVG 的缩放和旋转?【英文标题】:How can I fix the Scaling and Rotating of an Inkscape SVG in FabricJS? 【发布时间】:2014-03-23 07:58:03 【问题描述】:

我在使用 FabricJS 缩放和旋转 SVG 图像时遇到了一些问题。

我一直在为我的网站开发图标构建器。用户可以添加图层,为该图层选择形状,然后设置许多选项,例如颜色和笔画宽度。我填充了可能的“形状”,并且为了在形状复杂性方面实现最大的灵活性,我使用了我用 Inkscape 创建的 SVG 文件。我使用 FabricJS 中的 loadSVGFromURL 功能来处理将文件加载到我的画布上。

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

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

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

一个非常接近的解决方案是使用优化工具来删除一些显然不被 Fabric 喜欢的转换数据(该工具可在此处找到 http://petercollingridge.appspot.com/)。它似乎有效,但并非适用于每一张图片,包括这张图片。事实上,无论我选择何种优化选项,该工具都对八角形进行了如此大的改动,它并不能真正用作八角形。在这个现有问题中也引用了该工具:10470508 (issue-with-svg-display-rendering-in-fabric-js)

我以各种格式从 Inkscape 中保存了 SVG:Inkscape SVG、plain SVG 和 Optimized SVG - 没有任何区别。在以所有这些格式导出之前,我还尝试过简化路径 - 同样,没有区别(尽管对于某些形状,这似乎确实有效)。

我在 GitHub 上阅读了许多 bug 以及与 Kangax 相关的相关讨论,并尝试了诸如 centeredRotation 属性和对象上的原点之类的东西。

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

我确实尝试过用 Illustrator 制作的六边形,它似乎可以工作,但我没有 Illustrator 可供我使用,并且说这是一个“解决方案”有点不可取。也许这最好记录为一个错误,但是对于所有相关的喋喋不休,我有点希望它得到解决,我只是没有找到要遵循的正确设置或流程组合。我真的需要能够为这些使用 Inkscape。 Kangax 指出 Inkscape SVG 对 FabricJS 来说更麻烦,但他接着说它们正在变得更好。所以也许这可以帮助我们向前迈出一步。

我还在 GitHub 上查看了代码本身,但似乎无法准确指出我需要更改哪些内容才能解决此问题;不过,我不确定故障点在哪里 - 结构、我的设置或我的 SVG 文件。

2014 年 2 月 21 日美国东部标准时间晚上 10:27 更新

我开始深入研究 SVG 文件结构,比较那些给我带来麻烦的和那些正常工作的。看起来问题确实是由于路径、容器或其他对象标记上存在“转换”属性。我尝试过的优化过程应该已将它们删除,但我仍然没有找到适用于所有情况的可靠解决方案。我会及时通知你。

【问题讨论】:

【参考方案1】:

我对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+")")

【讨论】:

【参考方案2】:

使用 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();
    

【讨论】:

这是一个有趣的想法。感谢您的输入(此处和之前);但是,我可能在这里弄错了,但我不知道我是否可以使用任何一种方法来与 Fabric 很好地搭配使用……我确实需要保持这种方式。不过,我会继续思考这个问题……也许有一些我可以使用它的原因。再次感谢。还没有答案,但非常感谢。 祝你好运..期待您在此列表中的未来访问。 谢谢...我会保持最新状态,希望我们能从中得到一个好的答案。 :)【参考方案3】:

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

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

EvilEye Games - InkScape SVG Transform Remover

不过,最后,我还是决定使用其他网站上的一些免费 SVG。所以这一切都是为了不适合我。但是,我能够弄清楚并解决问题。所以想也许这对其他人来说会派上用场。它并不完美,但它做了它需要做的事情。

【讨论】:

以上是关于如何修复 FabricJS 中 Inkscape SVG 的缩放和旋转?的主要内容,如果未能解决你的问题,请参考以下文章

fabricjs:缩放后如何显示对象大小

如何在fabricJS中应用.otf字体?

如何在Jupyter Notebook小部件中使用FabricJS

在 FabricJS 中调整窗口大小时如何始终将剪切区域居中?

如何从 JSON 重新加载自定义 fabricJS 画布对象?

如何清除画布属性和事件并将其添加回fabricjs?