【问题标题】:D3 v4 url(#gradient) not returning the fill colorD3 v4 url​​(#gradient)不返回填充颜色
【发布时间】:2021-05-29 12:30:18
【问题描述】:

所以我在 d3.js 中完成了这个颜色编码的网格。有些方块应该是一半一种颜色,一半是另一种颜色。我已经根据其他示例布置了渐变。但是当我调用 url(#gridfill7) 时,它不会返回渐变 - 使用渐变的正方形是空的。

看其他问题,可能是浏览器的bug,但我不能确定。

这是一个演示问题的 sn-p:

var gridvis = null;


function highlightGrid() {
  var gridData = [];

var squareSize = 30;
var squarePad =5;
var numPerRow = 9;
var margin = {top: 10, right: 30, bottom: 30, left: 60};
var width = 750 - margin.left - margin.right;
var height = 520 - margin.top - margin.bottom;


var d = d3.csvParse(d3.select("pre").remove().text());

 for (var i = 0; i < d.length; i++) {
    //  console.log(d[i].report_num);
    //  console.log(d[i].platform_medium);
      d[i].report_num = +d[i].report_num;
      d[i].platform_medium = +d[i].platform_medium;
      
      d[i].col = i % numPerRow;
      d[i].x = d[i].col * (squareSize + squarePad);
      d[i].row = Math.floor(i/numPerRow);
      d[i].y = d[i].row * (squareSize + squarePad);
      gridData.push(d[i]);
  }


  let platformData = gridData;
    
  //console.log(gridData);

  var gridvis = d3.select("#chart2")
                  .append("svg")
                  .attr("width", width)
                  .attr("height", height)
                  .append("g")
                  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  

  // square grid
  // @v4 Using .merge here to ensure
  // new and old data have same attrs applied
  //console.log(platformData);
    
  var squares = gridvis.selectAll('.square').data(platformData, function (d) {  return d.report_num; });


  var gridFill7 = gridvis
                         .append("linearGradient")
                         .attr("id", "gridFill7")
                         .attr("x1", "0%")
                        .attr("x2", "0%")
                        .attr("y1", "0%")
                        .attr("y2", "100%")//since its a vertical linear gradient 
                        .attr("gradientUnits", "userSpaceOnUse");

  gridFill7.append("stop")
           .style("offset", "50%")
           .style("stop-color", "#0652DD")
           .style("stop-opacity", 1);

  gridFill7.append("stop")
           .style("offset", "100%")
           .style("stop-color", "#C4E538")
           .style("stop-opacity", 1);

  var gridFill8 = gridvis
                         .append("linearGradient")
                         .attr("id", "gridFill8")
                         .attr("x1", "0%")
                        .attr("x2", "0%")
                        .attr("y1", "0%")
                        .attr("y2", "100%")//since its a vertical linear gradient 
                        .attr("gradientUnits", "userSpaceOnUse");

  gridFill8.append("stop")
           .style("offset", "50%")
           .style("stop-color", "#0652DD")
           .style("stop-opacity", 1);

  gridFill8.append("stop")
           .style("offset", "100%")
           .style("stop-color", "#EE5A24")
           .style("stop-opacity", 1);

  var squaresE = squares.enter()
                        .append('rect')
                        .classed('square', true);

  var squares = squares.merge(squaresE)
                       .attr('width', squareSize)
                       .attr('height', squareSize)
                       .attr('fill', "#fff")
                       .classed('fill-square', function (d) { return d.platform_medium; })
                       .attr('x', function (d) { return d.x;})
                       .attr('y', function (d) { return d.y;})
                       .attr('opacity', 1);

                       gridvis.selectAll('.fill-square')
                       .transition()
                       .duration(800)
                       .attr('opacity', 1.0)
                       .attr('fill', function (d) { 
                                                       if (d.platform_medium===1) {return "#0652DD";}
                                                       else if (d.platform_medium===2) {return "#9980FA";}
                                                       else if (d.platform_medium===3) {return "#C4E538";}
                                                       else if (d.platform_medium===4) {return "#ED4C67";}
                                                       else if (d.platform_medium===5) {return "#F79F1F";}
                                                       else if (d.platform_medium===6) {return "#EE5A24";}
                                                       else if (d.platform_medium===7) {return "url(#gridfill7)";}
                                                       else if (d.platform_medium===8) {return "url(#gridfill8)";}

                                                   });
                  }
              
   highlightGrid();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<div id="chart2"></div>
<pre>report_num,covid_related,platform_medium
1,0,1
2,0,1
3,0,1
4,0,1
5,0,1
6,0,3
7,0,1
8,0,3
9,0,1
10,0,3
11,0,1
12,0,3
13,1,2
14,1,1
15,1,3
16,1,1
17,1,1
18,1,1
19,1,1
20,1,1
21,1,1
22,1,1
23,1,1
24,0,1
25,0,7
26,1,1
27,1,1
28,1,1
29,1,1
30,1,1
31,1,1
32,1,1
33,1,1
34,1,1
35,1,1
36,0,1
37,0,1
38,0,2
39,0,7
40,1,1
41,1,1
42,1,1
43,1,1
44,1,1
45,1,1
46,0,5
47,0,5
48,0,1
49,0,1
50,0,1
51,0,1
52,1,1
53,1,1
54,1,1
55,0,1
56,0,5
57,0,1
58,0,1
59,0,1
60,0,1
61,0,7
62,0,1
63,0,1
64,0,1
65,0,1
66,0,1
67,1,5
68,1,1
69,1,1
70,1,3
71,1,3
72,1,1
73,1,1
74,1,7
75,1,8
76,1,1
77,1,4
78,1,2</pre>

【问题讨论】:

    标签: javascript svg d3.js


    【解决方案1】:

    如果我们检查你的渐变,我们会发现一些奇怪的东西:

    停靠点没有偏移值,但您设置了一个。问题是stopoffset 值是一个属性而不是不能用作css 属性的东西,unlikestop-opacitystop-colorselection.style 设置 css 属性,selection.attr 设置属性。所以我们需要更新您的代码以使用selection.attr,如下所示:

      gridFill7.append("stop")
           .attr("offset", "50%")  // also for the other gridFill7 stop and gridFill8 of course
           ...
    

    现在我们有一个渐变如下,带有偏移属性:

    我们在渐变中仍然存在问题 - 我们不想将渐变单位设置为 userSpaceOnUse - 在此坐标空间中“百分比表示相对于当前 SVG 视口的值”。 (MDN)。我们可以使用默认的objectBoundingBox,其中“百分比表示相对于对象边界框的值”。这听起来更合适。由于这是默认选项,我们只需删除我们设置渐变单位的位置即可。

    下一个问题是一个错字:

      else if (d.platform_medium===7) {return "url(#gridfill7)";}
      else if (d.platform_medium===8) {return "url(#gridfill8)";}
    

    您的渐变 id 在 Fill 中使用大写的 f,但在分配填充时您正在寻找小写的 fs。

    修正后,我们应该会看到所需的最终结果:

    但是,过渡仍然有问题。 D3 转换从起始值移动到结束值。 D3 相当聪明,它可以识别表示颜色名称的字符串并将它们视为颜色,然后 D3 可以在起始颜色和结束颜色之间进行插值,这相对简单。

    但是您有一个表示渐变 url 的字符串和另一个表示颜色的字符串 - D3 的插值器不知道如何顺利​​地从颜色 (#fff) 移动到字符串 (url(#gridFill7))。中途会出现什么价值? D3 会为过渡创建新的渐变吗?照原样,过渡只在其整个持续时间内使用结束值。

    解决方案是将不透明度从 0 开始,然后使用首次创建元素时指定的填充过渡到不透明度 1。 D3 会很高兴地在 0 和 1 之间进行插值:

    var gridvis = null;
    
    
    function highlightGrid() {
      var gridData = [];
    
    var squareSize = 30;
    var squarePad =5;
    var numPerRow = 9;
    var margin = {top: 10, right: 30, bottom: 30, left: 60};
    var width = 750 - margin.left - margin.right;
    var height = 520 - margin.top - margin.bottom;
    
    
    var d = d3.csvParse(d3.select("pre").remove().text());
    
     for (var i = 0; i < d.length; i++) {
        //  console.log(d[i].report_num);
        //  console.log(d[i].platform_medium);
          d[i].report_num = +d[i].report_num;
          d[i].platform_medium = +d[i].platform_medium;
          
          d[i].col = i % numPerRow;
          d[i].x = d[i].col * (squareSize + squarePad);
          d[i].row = Math.floor(i/numPerRow);
          d[i].y = d[i].row * (squareSize + squarePad);
          gridData.push(d[i]);
      }
    
    
      let platformData = gridData;
        
      //console.log(gridData);
    
      var gridvis = d3.select("#chart2")
                      .append("svg")
                      .attr("width", width)
                      .attr("height", height)
                      .append("g")
                      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
      
    
      // square grid
      // @v4 Using .merge here to ensure
      // new and old data have same attrs applied
      //console.log(platformData);
        
      var squares = gridvis.selectAll('.square').data(platformData, function (d) {  return d.report_num; });
    
     var gridFill7 = gridvis
                             .append("linearGradient")
                             .attr("id", "gridFill7")
                             .attr("x1", "0%")
                            .attr("x2", "0%")
                            .attr("y1", "0%")
                            .attr("y2", "100%")//since its a vertical linear gradient 
                           // .attr("gradientUnits", "userSpaceOnUse");
    
      gridFill7.append("stop")
               .attr("offset", "50%")
               .style("stop-color", "#0652DD")
               .style("stop-opacity", 1);
    
      gridFill7.append("stop")
               .attr("offset", "100%")
               .style("stop-color", "#C4E538")
               .style("stop-opacity", 1);
    
      var gridFill8 = gridvis
                             .append("linearGradient")
                             .attr("id", "gridFill8")
                             .attr("x1", "0%")
                            .attr("x2", "0%")
                            .attr("y1", "0%")
                            .attr("y2", "100%")//since its a vertical linear gradient 
                           // .attr("gradientUnits", "userSpaceOnUse");
    
      gridFill8.append("stop")
               .attr("offset", "50%")
               .style("stop-color", "#0652DD")
               .style("stop-opacity", 1);
    
      gridFill8.append("stop")
               .attr("offset", "100%")
               .style("stop-color", "#EE5A24")
               .style("stop-opacity", 1);
    
      var squaresE = squares.enter()
                            .append('rect')
                            .classed('square', true);
    
      var squares = squares.merge(squaresE)
                           .attr('width', squareSize)
                           .attr('height', squareSize)
                           .attr('fill', function (d) { 
                                                           if (d.platform_medium===1) {return "#0652DD";}
                                                           else if (d.platform_medium===2) {return "#9980FA";}
                                                           else if (d.platform_medium===3) {return "#C4E538";}
                                                           else if (d.platform_medium===4) {return "#ED4C67";}
                                                           else if (d.platform_medium===5) {return "#F79F1F";}
                                                           else if (d.platform_medium===6) {return "#EE5A24";}
                                                           else if (d.platform_medium===7) {return "url(#gridFill7)";}
                                                           else if (d.platform_medium===8) {return "url(#gridFill8)";}
                                       
                            })
                           .classed('fill-square', function (d) { return d.platform_medium; })
                           .attr('x', function (d) { return d.x;})
                           .attr('y', function (d) { return d.y;})
                           .attr('opacity', 0);
    
                           gridvis.selectAll('.fill-square')
                           .transition()
                           .duration(800)
                           .attr('opacity', 1.0)
                          
    
                      }
                  
       highlightGrid();
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <div id="chart2"></div>
    <pre>report_num,covid_related,platform_medium
    1,0,1
    2,0,1
    3,0,1
    4,0,1
    5,0,1
    6,0,3
    7,0,1
    8,0,3
    9,0,1
    10,0,3
    11,0,1
    12,0,3
    13,1,2
    14,1,1
    15,1,3
    16,1,1
    17,1,1
    18,1,1
    19,1,1
    20,1,1
    21,1,1
    22,1,1
    23,1,1
    24,0,1
    25,0,7
    26,1,1
    27,1,1
    28,1,1
    29,1,1
    30,1,1
    31,1,1
    32,1,1
    33,1,1
    34,1,1
    35,1,1
    36,0,1
    37,0,1
    38,0,2
    39,0,7
    40,1,1
    41,1,1
    42,1,1
    43,1,1
    44,1,1
    45,1,1
    46,0,5
    47,0,5
    48,0,1
    49,0,1
    50,0,1
    51,0,1
    52,1,1
    53,1,1
    54,1,1
    55,0,1
    56,0,5
    57,0,1
    58,0,1
    59,0,1
    60,0,1
    61,0,7
    62,0,1
    63,0,1
    64,0,1
    65,0,1
    66,0,1
    67,1,5
    68,1,1
    69,1,1
    70,1,3
    71,1,3
    72,1,1
    73,1,1
    74,1,7
    75,1,8
    76,1,1
    77,1,4
    78,1,2</pre>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-27
      • 2016-01-11
      • 1970-01-01
      • 2016-12-11
      • 1970-01-01
      • 1970-01-01
      • 2015-03-02
      • 1970-01-01
      相关资源
      最近更新 更多