【问题标题】:Unite complex SVG files with paper.js将复杂的 SVG 文件与 paper.js 结合起来
【发布时间】:2020-09-21 17:53:56
【问题描述】:

我正在尝试将相对复杂的 SVG 联合起来,例如 this 之一。我想将制作“HELLO”字母的路径与后面的大“A”字母结合起来。在 Inkscape 上,我可以通过选择所有路径并转到 Path->Union 来做到这一点,因此路径是从这个转换而来的:

到这里:

请注意,在中心形成“HELLO”字母的路径现在如何与它们后面的大“A”结合在一起。我想通过使用paper.js 来达到同样的效果,因为它是我能找到的最好的解决方案,可以对 SVG 文件进行布尔运算而不对它们进行 poligonize,而且我无法在没有 GUI 的情况下使用 Inkscape CLI 来做到这一点。

我在paper.js 中创建this 草图以加载SVG 文件并在所有CompoundPathsPaths 之间建立一个联合,希望能达到相同的效果,但是,显然它不是那么简单,结果草图的路径是:

<path xmlns="http://www.w3.org/2000/svg" d="M-177.63334,-177.64819h755.85598v755.85598h-755.85598z" id="path32" fill="#000000" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"/>

这几乎是一条空路!有没有蚂蚁知道的方法来实现这一目标?我正在考虑像 Inkscape 那样检测形状的任何方法,我的意思是,在 Inkscape 上,您可以单独选择和操作每个字母作为单个形状,所以如果我可以识别每个形状(或闭合路径?)我可以进行联合操作他们之间。

我对如何实现这一点有点迷茫,所以任何算法、技巧、书籍、博客、代码或任何东西都会得到极大的赞赏!

【问题讨论】:

    标签: javascript svg paperjs


    【解决方案1】:

    我终于设法解决了!我必须确保不使用unite 用作clipMask 的路径,并确保使用closePath() 方法关闭所有路径。最终代码如下所示:

    var canvas = document.getElementById('canvas')
    var scope = paper.setup(new paper.Size(200, 200))
    
    var svg = `{put your svg string here}`;
    
    paper.project.importSVG(svg, function(pathItem) {
        // Get Path and CompoundPath which are children from this item
        let paths = pathItem.getItems({
            className: 'Path'
        });
        let compoundPaths = pathItem.getItems({
            className: 'CompoundPath'
        });
    
        // Filter paths that are inside CompoundPaths
        paths = paths
            .filter((p) => !compoundPaths.some((cp) => cp.children.includes(p)))
            // Filter paths that are used as clipping paths
            .filter((p) => !p.clipMask);
        compoundPaths = compoundPaths.filter((c) => !c.clipMask);
    
        // Close all paths to ensure a correct union
        for (const path of compoundPaths.filter((c) => !c.closed)) {
            path.closePath();
        }
        for (const path of paths.filter((c) => !c.closed)) {
            path.closePath();
        }
    
        // If not paths or compound paths are available, return the same input SVG
        if (!paths.length && !compoundPaths.length) {
            debugger;
        }
        else {
            // Merge all the paths to build a single path
            let unitedItem = undefined;
            let compoundPathsStartIndex = 0;
            if (paths.length) {
                unitedItem = paths[0];
                for (let n = 1; n < paths.length; ++n) {
                    const path = paths[n];
                    unitedItem = unitedItem.unite(path);
                }
            } else {
                unitedItem = compoundPaths[0];
                compoundPathsStartIndex = 1;
            }
    
            for (let n = compoundPathsStartIndex; n < compoundPaths.length; ++n) {
                const path = compoundPaths[n];
                unitedItem = unitedItem.unite(path);
            }
    
            // Set fill color otherwise paths exported in the server (which uses node 8) end up without
            //  a filling color
            unitedItem.fillColor = new paper.Color(0, 0, 0);
    
            // Generate the merged SVG string and save it
            const outputPathString = unitedItem.exportSVG({
                asString: true,
                bounds: new paper.Rectangle(0, 0, pathItem.getBounds().width, pathItem.getBounds().height)
            });
            // let outputSvg = outputPathString;
            let outputSvg = `<?xml version="1.0" encoding="utf-8"?>\n<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" width="${pathItem.getBounds().width}" height="${pathItem.getBounds().height}">`;
            outputSvg += outputPathString;
            outputSvg += '</svg>';
            
            console.log(outputSvg);
            debugger;
        }
    });
    

    包含 SVG 字符串的完整代码是 here,因为我在答案中包含它超过了最大正文长度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-08
      • 2018-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-21
      相关资源
      最近更新 更多