使用str.replace()来修复clipPath区分大小写使得SVG文件不可编辑

时间:2016-07-07 21:47:27

标签: node.js d3.js svg data-visualization

我正在构建一个基于节点的命令行界面来生成SVG映射。我在制作可以在Inkscape等程序中编辑的SVG文件时遇到了麻烦,但这限制了该实用程序的实用性。

问题是WebKit错误会导致D3生成的clipPath元素变为全小写clippath元素,这当然不是正确的SVG,最终会破坏图像。为了解决这个问题,我做了一个全局替换,将它转换回camelCase。

该解决方法生成一个SVG文件,可以在浏览器中正常查看,但不能在像Inkscape这样的SVG编辑程序中编辑。如果我进行全局替换,则可以编辑该文件。

有任何线索如何解决这个问题?

GitHub repo,您​​可以自己测试CLI:https://github.com/hierocles/housemapper-cli

相关代码:

function makeMap(fileName) {
  var document = jsdom.jsdom();

  var us = JSON.parse(fs.readFileSync( __dirname + '/jsonfiles/us.json', 'utf8'));
  var congress = JSON.parse(fs.readFileSync(__dirname + '/jsonfiles/us-cong-114.json', 'utf8'));

  var css = "<![CDATA[ \
      .background { \
        fill: none; \
      } \
      .district { \
        fill: #ccc; \
      } \
      .district-dem-yes { \
        fill: #394DE5; \
      } \
      .district-dem-no { \
        fill: #7585FF; \
      } \
      .district-rep-yes { \
        fill: #EA513C; \
      } \
      .district-rep-no { \
        fill: #EA998F; \
      } \
      .district-yes { \
        fill: #03BC82; \
      } \
      .district-no { \
        fill: #3BE2AD; \
      } \
      .state-boundaries { \
        fill: none; \
        stroke: #fff; \
        stroke-width: 1px; \
      } \
      .district-boundaries { \
        fill: none; \
        stroke: #fff; \
        stroke-width: 0.5px; \
        stroke-linecap: round; \
        stroke-linejoin: round; \
      }\
  ]]>";

  var width = 960,
      height = 500;

  var projection = d3.geo.albersUsa()
      .scale(1000)
      .translate([width/2, height/2]);

  var path = d3.geo.path()
      .projection(projection);

  var svg = d3.select(document.body).append('svg')
      .attr('xmlns', 'http://www.w3.org/2000/svg')
      .attr('width', width)
      .attr('height', height);

      svg.append("rect")
          .attr("class", "background")
          .attr("width", width)
          .attr("height", height);

  var defs = svg.append('defs');

      defs.append('path')
        .attr('id', 'land')
        .datum(topojson.feature(us, us.objects.land))
        .attr('d', path);

      defs.append('style')
          .attr('type', 'text/css')
          .text(css);

      defs.append('clipPath')
          .attr('id', 'clip-land')
        .append('use')
          .attr('xlink:href', '#land');

  var g = svg.append('g');

      g.attr('clip-path', 'url(#clip-land)')
        .selectAll('path')
          .data(topojson.feature(congress, congress.objects.districts).features)
        .enter().append('path')
          .attr('d', path)
          .attr('class', function(d) { return getColor(d); });

      g.append('path')
        .datum(topojson.mesh(congress, congress.objects.districts, function(a, b) { return a !== b && (a.id / 1000 | 0) === (b.id / 1000 | 0); }))
        .attr('class', 'district-boundaries')
        .attr('d', path);

      g.append('path')
        .datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
        .attr('class', 'state-boundaries')
        .attr('d', path);

  // This file cannot be edited:
  var output = d3.select(document.body).html().replace(/clippath/g, 'clipPath');

  // This file can be edited:
  //var output = d3.select(document.body).html();

  fs.writeFileSync(fileName, output);

}

1 个答案:

答案 0 :(得分:1)

output2.svg的剩余问题是剪辑路径元素中的<use>引用不正确。

我做了什么:

  1. <clippath> - &gt; <clipPath>
  2. href="#land" - &gt; xlink:href="#land"
  3. 将xlink命名空间添加到根元素

    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="960" height="500">