代码之家  ›  专栏  ›  技术社区  ›  hierocles

使用str.replace()修复clipPath区分大小写的问题,使SVG文件不可编辑

  •  0
  • hierocles  · 技术社区  · 10 年前

    问题是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 回复  |  直到 10 年前
        1
  •  1
  •   Paul LeBeau    10 年前

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

    我做了什么:

    1. <clippath> -> <clipPath>
    2. href="#land" -> 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">
      
    推荐文章