首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >D3图圈填充图着色

D3图圈填充图着色
EN

Stack Overflow用户
提问于 2020-04-10 20:35:57
回答 1查看 191关注 0票数 1

我用d3.js (版本3.4.11)绘制了一个可缩放的圆填充图(也称为耀斑图)。

代码语言:javascript
复制
displayFlareGraph: function (containerId, options, json) {
        options.width = options.width || 1280; // circle width
        options.height = options.height || 800; // circle height
        options.radius = options.radius || 720; // circle radius
        var w = options.width,
            h = options.height,
            r = options.radius,
            x = d3.scale.linear().range([0, r]),
            y = d3.scale.linear().range([0, r]),
            node,
            root;

        var color = (key) => Palette.pickColor("labels_colors", key);

        var pack = d3.layout.pack()
            .size([r, r])
            .value(function (d) {
                return d.size;
            })

        var vis = d3.select(containerId).insert("svg:svg", "h2")
            .attr("width", w)
            .attr("height", h)
            .append("svg:g")
            .attr("transform", "translate(" + (w - r) / 2 + "," + (h - r) / 2 + ")");

        function zoom(d, i) {
            var k = r / d.r / 2;
            x.domain([d.x - d.r, d.x + d.r]);
            y.domain([d.y - d.r, d.y + d.r]);

            var t = vis.transition()
                .duration(d3.event.altKey ? 7500 : 750);

            t.selectAll("circle")
                .attr("cx", function (d) {
                    return x(d.x);
                })
                .attr("cy", function (d) {
                    return y(d.y);
                })
                .attr("r", function (d) {
                    return k * d.r;
                })

            t.selectAll("text")
                .attr("x", function (d) {
                    return x(d.x);
                })
                .attr("y", function (d) {
                    return d.children ? y(d.y) : y(d.y + 10);
                })
                .style("opacity", function (d) {
                    return k * d.r > 20 ? 1 : 0;
                });

            node = d;
            d3.event.stopPropagation();
        } //zoom

        node = root = json;
        var nodes = pack.nodes(root);
        vis.selectAll("circle")
            .data(nodes)
            .enter().append("svg:circle")
            .attr("class", function (d) {
                return d.children ? "parent" : "child";
            })
            .attr("cx", function (d) {
                return d.x;
            })
            .attr("cy", function (d) {
                return d.y;
            })
            .attr("r", function (d) {
                return d.r;
            })
            .attr("fill", d => color(d.height))
            .on("click", function (d) {
                return zoom(node == d ? root : d);
            });

        vis.selectAll("text")
            .data(nodes)
            .enter().append("svg:text")
            .attr("class", function (d) {
                return d.children ? "parent" : "child";
            })
            .attr("x", function (d) {
                return d.x;
            })
            .attr("y", function (d) {
                return d.children ? d.y : d.y + 10;
            })
            .attr("dy", ".35em")
            .attr("text-anchor", "middle")
            .style("opacity", function (d) {
                return d.r > 20 ? 1 : 0;
            })
            .text(function (d) {
                return d.name;
            });

        d3.select(window).on("click", function () {
            zoom(root);
        });

    } //displayFlareGraph

我现在想给圆圈涂上颜色,我已经尝试过像这样使用fill属性

代码语言:javascript
复制
.attr("r", function (d) {
    return d.r;
})
.attr("fill", d => color(d.height))

其中,我的color函数返回一个随机的RGB颜色。我有一个默认的CSS,使圆圈的颜色。但是fill似乎没有覆盖这些设置。

代码语言:javascript
复制
var displayFlareGraph = function(containerId, options, json) {
  options.width = options.width || 1280; // circle width
  options.height = options.height || 800; // circle height
  options.radius = options.radius || 720; // circle radius
  var w = options.width,
    h = options.height,
    r = options.radius,
    x = d3.scale.linear().range([0, r]),
    y = d3.scale.linear().range([0, r]),
    node,
    root;

  var color = (key) => {
    return {
               "r": ~~(Math.random() * 255), 
               "g": ~~(Math.random() * 255), 
               "b": ~~(Math.random() * 255),
               "opacity": 0.9
         }
  }

  var pack = d3.layout.pack()
    .size([r, r])
    .value(function(d) {
      return d.size;
    })

  var vis = d3.select(containerId).insert("svg:svg", "h2")
    .attr("width", w)
    .attr("height", h)
    .append("svg:g")
    .attr("transform", "translate(" + (w - r) / 2 + "," + (h - r) / 2 + ")");

  function zoom(d, i) {
    var k = r / d.r / 2;
    x.domain([d.x - d.r, d.x + d.r]);
    y.domain([d.y - d.r, d.y + d.r]);

    var t = vis.transition()
      .duration(d3.event.altKey ? 7500 : 750);

    t.selectAll("circle")
      .attr("cx", function(d) {
        return x(d.x);
      })
      .attr("cy", function(d) {
        return y(d.y);
      })
      .attr("r", function(d) {
        return k * d.r;
      })

    t.selectAll("text")
      .attr("x", function(d) {
        return x(d.x);
      })
      .attr("y", function(d) {
        return d.children ? y(d.y) : y(d.y + 10);
      })
      .style("opacity", function(d) {
        return k * d.r > 20 ? 1 : 0;
      });

    node = d;
    d3.event.stopPropagation();
  } //zoom

  node = root = json;
  var nodes = pack.nodes(root);
  vis.selectAll("circle")
    .data(nodes)
    .enter().append("svg:circle")
    .attr("class", function(d) {
      return d.children ? "parent" : "child";
    })
    .attr("cx", function(d) {
      return d.x;
    })
    .attr("cy", function(d) {
      return d.y;
    })
    .attr("r", function(d) {
      return d.r;
    })
    .attr("fill", d => color(d.height))
    .on("click", function(d) {
      return zoom(node == d ? root : d);
    });

  vis.selectAll("text")
    .data(nodes)
    .enter().append("svg:text")
    .attr("class", function(d) {
      return d.children ? "parent" : "child";
    })
    .attr("x", function(d) {
      return d.x;
    })
    .attr("y", function(d) {
      return d.children ? d.y : d.y + 10;
    })
    .attr("dy", ".35em")
    .attr("text-anchor", "middle")
    .style("opacity", function(d) {
      return d.r > 20 ? 1 : 0;
    })
    .text(function(d) {
      return d.name;
    });

  d3.select(window).on("click", function() {
    zoom(root);
  });

} //displayFlareGraph
//https://observablehq.com/@d3/zoomable-circle-packing


$(document).ready(function() {
  displayFlareGraph('#graph', {
    width: 400,
    height: 300,
    radius: 400
  }, NODES);
})

const NODES = {
  "children": [{
    "name": "#0",
    "children": [{
      "name": "back",
      "size": 0.086
    }, {
      "name": "time",
      "size": 0.036
    }, {
      "name": "dance",
      "size": 0.036
    }, {
      "name": "make",
      "size": 0.034
    }, {
      "name": "summer",
      "size": 0.029
    }, {
      "name": "stay",
      "size": 0.029
    }, {
      "name": "white",
      "size": 0.022
    }, {
      "name": "lying",
      "size": 0.022
    }, {
      "name": "whoa",
      "size": 0.021
    }]
  }, {
    "name": "#1",
    "children": [{
      "name": "heart",
      "size": 0.086
    }, {
      "name": "broke",
      "size": 0.072
    }, {
      "name": "story",
      "size": 0.061
    }, {
      "name": "life",
      "size": 0.05
    }, {
      "name": "give",
      "size": 0.048
    }, {
      "name": "start",
      "size": 0.025
    }, {
      "name": "time",
      "size": 0.022
    }]
  }, {
    "name": "#2",
    "children": [{
      "name": "make",
      "size": 0.087
    }, {
      "name": "beautiful",
      "size": 0.071
    }, {
      "name": "world",
      "size": 0.068
    }, {
      "name": "baby",
      "size": 0.033
    }, {
      "name": "hair",
      "size": 0.03
    }, {
      "name": "understand",
      "size": 0.029
    }, {
      "name": "light",
      "size": 0.025
    }, {
      "name": "hard",
      "size": 0.025
    }, {
      "name": "ground",
      "size": 0.024
    }, {
      "name": "smile",
      "size": 0.023
    }, {
      "name": "heads",
      "size": 0.022
    }, {
      "name": "hear",
      "size": 0.021
    }, {
      "name": "flip",
      "size": 0.021
    }, {
      "name": "overwhelmed",
      "size": 0.02
    }, {
      "name": "nana",
      "size": 0.02
    }]
  }, {
    "name": "#3",
    "children": [{
      "name": "words",
      "size": 0.044
    }, {
      "name": "tears",
      "size": 0.041
    }, {
      "name": "rock",
      "size": 0.036
    }, {
      "name": "stop",
      "size": 0.031
    }, {
      "name": "half",
      "size": 0.027
    }, {
      "name": "heart",
      "size": 0.026
    }]
  }, {
    "name": "#4",
    "children": [{
      "name": "gonna",
      "size": 0.12
    }, {
      "name": "wanna",
      "size": 0.093
    }, {
      "name": "girl",
      "size": 0.047
    }, {
      "name": "steal",
      "size": 0.042
    }, {
      "name": "meet",
      "size": 0.038
    }, {
      "name": "belongs",
      "size": 0.037
    }, {
      "name": "hold",
      "size": 0.036
    }, {
      "name": "getcha",
      "size": 0.034
    }, {
      "name": "alright",
      "size": 0.029
    }]
  }, {
    "name": "#5",
    "children": [{
      "name": "love",
      "size": 0.23
    }, {
      "name": "things",
      "size": 0.063
    }, {
      "name": "make",
      "size": 0.047
    }, {
      "name": "perfect",
      "size": 0.024
    }, {
      "name": "heart",
      "size": 0.021
    }]
  }, {
    "name": "#6",
    "children": [{
      "name": "night",
      "size": 0.14
    }, {
      "name": "song",
      "size": 0.093
    }, {
      "name": "danced",
      "size": 0.074
    }, {
      "name": "forget",
      "size": 0.069
    }, {
      "name": "remember",
      "size": 0.056
    }, {
      "name": "home",
      "size": 0.035
    }, {
      "name": "afraid",
      "size": 0.034
    }, {
      "name": "line",
      "size": 0.029
    }, {
      "name": "wildest",
      "size": 0.02
    }, {
      "name": "dreaming",
      "size": 0.02
    }]
  }, {
    "name": "#7",
    "children": [{
      "name": "feel",
      "size": 0.082
    }, {
      "name": "tonight",
      "size": 0.039
    }, {
      "name": "gonna",
      "size": 0.038
    }, {
      "name": "eyes",
      "size": 0.037
    }, {
      "name": "calls",
      "size": 0.034
    }, {
      "name": "longer",
      "size": 0.031
    }, {
      "name": "heart",
      "size": 0.031
    }, {
      "name": "saved",
      "size": 0.028
    }, {
      "name": "turning",
      "size": 0.027
    }, {
      "name": "hold",
      "size": 0.026
    }, {
      "name": "falling",
      "size": 0.025
    }, {
      "name": "love",
      "size": 0.021
    }, {
      "name": "light",
      "size": 0.02
    }]
  }, {
    "name": "#8",
    "children": [{
      "name": "baby",
      "size": 0.13
    }, {
      "name": "wanna",
      "size": 0.077
    }, {
      "name": "moving",
      "size": 0.031
    }, {
      "name": "kiss",
      "size": 0.031
    }, {
      "name": "girl",
      "size": 0.029
    }, {
      "name": "stay",
      "size": 0.026
    }, {
      "name": "feel",
      "size": 0.026
    }, {
      "name": "find",
      "size": 0.023
    }, {
      "name": "good",
      "size": 0.021
    }, {
      "name": "change",
      "size": 0.021
    }, {
      "name": "hold",
      "size": 0.02
    }]
  }, {
    "name": "#9",
    "children": [{
      "name": "forever",
      "size": 0.09
    }, {
      "name": "live",
      "size": 0.062
    }, {
      "name": "life",
      "size": 0.053
    }, {
      "name": "young",
      "size": 0.04
    }, {
      "name": "kids",
      "size": 0.03
    }, {
      "name": "happenin",
      "size": 0.022
    }]
  }]
}
代码语言:javascript
复制
body>svg {
  position: absolute;
  top: -80px;
  left: -160px;
}

text {
  font-size: 11px;
  pointer-events: none;
}

text.parent {
  fill: #1f77b4;
}

circle {
  fill: #ccc;
  stroke: #999;
  pointer-events: all;
}

circle.parent {
  fill: #1f77b4;
  fill-opacity: .1;
  stroke: steelblue;
}

circle.parent:hover {
  stroke: #ff7f0e;
  stroke-width: .5px;
}

circle.child {
  pointer-events: none;
}
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-cloud/1.2.4/d3.layout.cloud.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="graph"></div>

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-10 21:11:51

有两个问题阻止随机颜色的产生。

  1. 定义的css fill优先于fill SVG属性。因此,不应该使用selection.attr('fill'...,而应该使用selection.style('fill'...。阅读this answer获取详细信息。
  2. color函数返回一个对象,而不是一个颜色字符串。这在开发人员控制台的DOM检查面板中是可见的。其中圆有属性fill="[object object]"

颜色函数可以调整如下,以便返回字符串而不是数组:

代码语言:javascript
复制
var color = () => {
    return 'rgba(' 
        + ~~(Math.random() * 255) + ',' 
        +  ~~(Math.random() * 255) + ',' 
        + ~~(Math.random() * 255) + ', .9)'
}

备注:没有必要将d.key作为参数传递给颜色函数,因为它根本不被使用。

演示在下面的片段。

代码语言:javascript
复制
var displayFlareGraph = function(containerId, options, json) {
  options.width = options.width || 1280; // circle width
  options.height = options.height || 800; // circle height
  options.radius = options.radius || 720; // circle radius
  var w = options.width,
    h = options.height,
    r = options.radius,
    x = d3.scale.linear().range([0, r]),
    y = d3.scale.linear().range([0, r]),
    node,
    root;

  var color = () => {
    return 'rgba(' + ~~(Math.random() * 255) + ',' +  ~~(Math.random() * 255) + ',' + ~~(Math.random() * 255) + ', .9)'
  }

  var pack = d3.layout.pack()
    .size([r, r])
    .value(function(d) {
      return d.size;
    })

  var vis = d3.select(containerId).insert("svg:svg", "h2")
    .attr("width", w)
    .attr("height", h)
    .append("svg:g")
    .attr("transform", "translate(" + (w - r) / 2 + "," + (h - r) / 2 + ")");

  function zoom(d, i) {
    var k = r / d.r / 2;
    x.domain([d.x - d.r, d.x + d.r]);
    y.domain([d.y - d.r, d.y + d.r]);

    var t = vis.transition()
      .duration(d3.event.altKey ? 7500 : 750);

    t.selectAll("circle")
      .attr("cx", function(d) {
        return x(d.x);
      })
      .attr("cy", function(d) {
        return y(d.y);
      })
      .attr("r", function(d) {
        return k * d.r;
      })

    t.selectAll("text")
      .attr("x", function(d) {
        return x(d.x);
      })
      .attr("y", function(d) {
        return d.children ? y(d.y) : y(d.y + 10);
      })
      .style("opacity", function(d) {
        return k * d.r > 20 ? 1 : 0;
      });

    node = d;
    d3.event.stopPropagation();
  } //zoom

  node = root = json;
  var nodes = pack.nodes(root);
  vis.selectAll("circle")
    .data(nodes)
    .enter().append("circle")
    .attr("class", function(d) {
      return d.children ? "parent" : "child";
    })
    .attr("cx", function(d) {
      return d.x;
    })
    .attr("cy", function(d) {
      return d.y;
    })
    .attr("r", function(d) {
      return d.r;
    })
    .style("fill", d => color())
    .on("click", function(d) {
      return zoom(node == d ? root : d);
    });

  vis.selectAll("text")
    .data(nodes)
    .enter().append("svg:text")
    .attr("class", function(d) {
      return d.children ? "parent" : "child";
    })
    .attr("x", function(d) {
      return d.x;
    })
    .attr("y", function(d) {
      return d.children ? d.y : d.y + 10;
    })
    .attr("dy", ".35em")
    .attr("text-anchor", "middle")
    .style("opacity", function(d) {
      return d.r > 20 ? 1 : 0;
    })
    .text(function(d) {
      return d.name;
    });

  d3.select(window).on("click", function() {
    zoom(root);
  });

} //displayFlareGraph
//https://observablehq.com/@d3/zoomable-circle-packing


$(document).ready(function() {
  displayFlareGraph('#graph', {
    width: 400,
    height: 300,
    radius: 400
  }, NODES);
})

const NODES = {
  "children": [{
    "name": "#0",
    "children": [{
      "name": "back",
      "size": 0.086
    }, {
      "name": "time",
      "size": 0.036
    }, {
      "name": "dance",
      "size": 0.036
    }, {
      "name": "make",
      "size": 0.034
    }, {
      "name": "summer",
      "size": 0.029
    }, {
      "name": "stay",
      "size": 0.029
    }, {
      "name": "white",
      "size": 0.022
    }, {
      "name": "lying",
      "size": 0.022
    }, {
      "name": "whoa",
      "size": 0.021
    }]
  }, {
    "name": "#1",
    "children": [{
      "name": "heart",
      "size": 0.086
    }, {
      "name": "broke",
      "size": 0.072
    }, {
      "name": "story",
      "size": 0.061
    }, {
      "name": "life",
      "size": 0.05
    }, {
      "name": "give",
      "size": 0.048
    }, {
      "name": "start",
      "size": 0.025
    }, {
      "name": "time",
      "size": 0.022
    }]
  }, {
    "name": "#2",
    "children": [{
      "name": "make",
      "size": 0.087
    }, {
      "name": "beautiful",
      "size": 0.071
    }, {
      "name": "world",
      "size": 0.068
    }, {
      "name": "baby",
      "size": 0.033
    }, {
      "name": "hair",
      "size": 0.03
    }, {
      "name": "understand",
      "size": 0.029
    }, {
      "name": "light",
      "size": 0.025
    }, {
      "name": "hard",
      "size": 0.025
    }, {
      "name": "ground",
      "size": 0.024
    }, {
      "name": "smile",
      "size": 0.023
    }, {
      "name": "heads",
      "size": 0.022
    }, {
      "name": "hear",
      "size": 0.021
    }, {
      "name": "flip",
      "size": 0.021
    }, {
      "name": "overwhelmed",
      "size": 0.02
    }, {
      "name": "nana",
      "size": 0.02
    }]
  }, {
    "name": "#3",
    "children": [{
      "name": "words",
      "size": 0.044
    }, {
      "name": "tears",
      "size": 0.041
    }, {
      "name": "rock",
      "size": 0.036
    }, {
      "name": "stop",
      "size": 0.031
    }, {
      "name": "half",
      "size": 0.027
    }, {
      "name": "heart",
      "size": 0.026
    }]
  }, {
    "name": "#4",
    "children": [{
      "name": "gonna",
      "size": 0.12
    }, {
      "name": "wanna",
      "size": 0.093
    }, {
      "name": "girl",
      "size": 0.047
    }, {
      "name": "steal",
      "size": 0.042
    }, {
      "name": "meet",
      "size": 0.038
    }, {
      "name": "belongs",
      "size": 0.037
    }, {
      "name": "hold",
      "size": 0.036
    }, {
      "name": "getcha",
      "size": 0.034
    }, {
      "name": "alright",
      "size": 0.029
    }]
  }, {
    "name": "#5",
    "children": [{
      "name": "love",
      "size": 0.23
    }, {
      "name": "things",
      "size": 0.063
    }, {
      "name": "make",
      "size": 0.047
    }, {
      "name": "perfect",
      "size": 0.024
    }, {
      "name": "heart",
      "size": 0.021
    }]
  }, {
    "name": "#6",
    "children": [{
      "name": "night",
      "size": 0.14
    }, {
      "name": "song",
      "size": 0.093
    }, {
      "name": "danced",
      "size": 0.074
    }, {
      "name": "forget",
      "size": 0.069
    }, {
      "name": "remember",
      "size": 0.056
    }, {
      "name": "home",
      "size": 0.035
    }, {
      "name": "afraid",
      "size": 0.034
    }, {
      "name": "line",
      "size": 0.029
    }, {
      "name": "wildest",
      "size": 0.02
    }, {
      "name": "dreaming",
      "size": 0.02
    }]
  }, {
    "name": "#7",
    "children": [{
      "name": "feel",
      "size": 0.082
    }, {
      "name": "tonight",
      "size": 0.039
    }, {
      "name": "gonna",
      "size": 0.038
    }, {
      "name": "eyes",
      "size": 0.037
    }, {
      "name": "calls",
      "size": 0.034
    }, {
      "name": "longer",
      "size": 0.031
    }, {
      "name": "heart",
      "size": 0.031
    }, {
      "name": "saved",
      "size": 0.028
    }, {
      "name": "turning",
      "size": 0.027
    }, {
      "name": "hold",
      "size": 0.026
    }, {
      "name": "falling",
      "size": 0.025
    }, {
      "name": "love",
      "size": 0.021
    }, {
      "name": "light",
      "size": 0.02
    }]
  }, {
    "name": "#8",
    "children": [{
      "name": "baby",
      "size": 0.13
    }, {
      "name": "wanna",
      "size": 0.077
    }, {
      "name": "moving",
      "size": 0.031
    }, {
      "name": "kiss",
      "size": 0.031
    }, {
      "name": "girl",
      "size": 0.029
    }, {
      "name": "stay",
      "size": 0.026
    }, {
      "name": "feel",
      "size": 0.026
    }, {
      "name": "find",
      "size": 0.023
    }, {
      "name": "good",
      "size": 0.021
    }, {
      "name": "change",
      "size": 0.021
    }, {
      "name": "hold",
      "size": 0.02
    }]
  }, {
    "name": "#9",
    "children": [{
      "name": "forever",
      "size": 0.09
    }, {
      "name": "live",
      "size": 0.062
    }, {
      "name": "life",
      "size": 0.053
    }, {
      "name": "young",
      "size": 0.04
    }, {
      "name": "kids",
      "size": 0.03
    }, {
      "name": "happenin",
      "size": 0.022
    }]
  }]
}
代码语言:javascript
复制
body>svg {
  position: absolute;
  top: -80px;
  left: -160px;
}

text {
  font-size: 11px;
  pointer-events: none;
}

text.parent {
  fill: #1f77b4;
}

circle {
  fill: #ccc;
  stroke: #999;
  pointer-events: all;
}

circle.parent {
  fill: #1f77b4;
  fill-opacity: .1;
  stroke: steelblue;
}

circle.parent:hover {
  stroke: #ff7f0e;
  stroke-width: .5px;
}

circle.child {
  pointer-events: none;
}
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-cloud/1.2.4/d3.layout.cloud.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="graph"></div>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61148292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档