简体   繁体   English

雷达图的d3.js颜色组

[英]d3.js Color Groups for Radar Chart

I'm using this d3 Radar Chart , and now I want to color the groups. 我正在使用d3雷达图 ,现在我要为组着色。

Here's my data - 这是我的数据-

var data = [
  [
     {axis:"volume(N)",value:0.074095419,group:"one"},
     {axis:"heightBBOX(N)",value:0.618900916,group:"one"},
     {axis:"floor_area(N)",value:0.239036487,group:"one"},
     {axis:"RatioSunExp_TotWall",value:0.670908597,group:"one"
  }],
  [
     {axis:"volume(N)",value:0.373966243,group:"two"},
     {axis:"heightBBOX(N)",value:0.418068276,group:"two"},
     {axis:"floor_area(N)",value:0.039064467,group:"two"},
     {axis:"RatioSunExp_TotWall",value:0.341108011,group:"two"
  }],
  [
     {axis:"volume(N)",value:0.675991163,group:"two"},
     {axis:"heightBBOX(N)",value:0.815015265,group:"two"},
     {axis:"floor_area(N)",value:0.94061374,group:"two"},
     {axis:"RatioSunExp_TotWall",value:0.974062924,group:"two"
  }],
  [
     {axis:"volume(N)",value:0.875950233,group:"two"},
     {axis:"heightBBOX(N)",value:0.210852068,group:"two"},
     {axis:"floor_area(N)",value:0.540645865,group:"two"},
     {axis:"RatioSunExp_TotWall",value:0.074841546,group:"two"
  }]]

and these are my color options 这些是我的颜色选择

    var color = d3.scale.ordinal()
        .domain(["one","two"])
        .range(["#CC333F","#53e87d"]);

I want to color the group one with a specific color and the group two with another color. 我要的颜色组一个具有特定颜色和组的两个与另一种颜色。 How can i do? 我能怎么做?

update: when I use the code below, all the charts are yellow. 更新:当我使用下面的代码时,所有图表都是黄色的。 So I know that the group is undefined. 因此,我知道该组是不确定的。 How can I fix this ? 我怎样才能解决这个问题 ?

color: function(d){
    if(d.group == "one"){
        return "red";
        }
    if(d.group == "two"){
        return "green";
        }
    else{
        return "yellow";
    }
    }

The problem with your code is that in radarChartOptions this... 您的代码的问题是在radarChartOptions这...

color: function(d){

... doesn't retrieve the datum bound to each element. ...不会检索绑定到每个元素的datum

The best solution here is looking at the plugin, or emailing its author, to find out how he/she is passing the options. 最好的解决方案是查看插件,或通过电子邮件将其发送给作者,以了解他/她如何传递选项。 As I don't have time to check the plugin documentation, here is a simple solution, which paints the paths/circles after they are rendered: 由于我没有时间去检查插件文档,因此这是一个简单的解决方案,它渲染路径/圆后对其进行绘制:

d3.selectAll(".radarArea").each(function(d){
  d3.select(this).style("fill", color(d[0].group))
});

d3.selectAll(".radarStroke").each(function(d){
  d3.select(this).style("stroke", color(d[0].group))
});

d3.selectAll(".radarCircle").each(function(d){
  d3.select(this).style("fill", color(d.group))
});

Here is the updated fiddle: https://jsfiddle.net/1j59znu9/ 这是更新的小提琴: https : //jsfiddle.net/1j59znu9/

You may notice that by using a function insdide color you get a number from 0 to 3 which indicate the current array of your data that contains 4 arrays. 您可能会注意到,通过使用函数insdide color,您将获得一个介于0到3之间的数字,该数字指示包含4个数组的当前data数组。 And since you want to specify a color for each one, you can use another array on where you specfiy the color of each one. 并且由于要为每种颜色指定一种颜色,因此可以在指定每种颜色的位置使用另一个数组。 So you may have an array of 4 items like this: 因此,您可能会有以下4个项的数组:

var colors = ["two","one","one","two"];

and you can keep your data with the default structure: 您可以将数据保留为默认结构:

var data = [[
     {axis:"volume(N)",value:0.074095419},
     {axis:"heightBBOX(N)",value:0.618900916},
     {axis:"floor_area(N)",value:0.239036487},
     {axis:"RatioSunExp_TotWall",value:0.670908597
  }],
  [
     {axis:"volume(N)",value:0.373966243},
     {axis:"heightBBOX(N)",value:0.418068276},
     {axis:"floor_area(N)",value:0.039064467},
     {axis:"RatioSunExp_TotWall",value:0.341108011
  }],
  [
     {axis:"volume(N)",value:0.675991163},
     {axis:"heightBBOX(N)",value:0.815015265},
     {axis:"floor_area(N)",value:0.94061374},
     {axis:"RatioSunExp_TotWall",value:0.974062924
  }],
  [
     {axis:"volume(N)",value:0.875950233},
     {axis:"heightBBOX(N)",value:0.210852068},
     {axis:"floor_area(N)",value:0.540645865},
     {axis:"RatioSunExp_TotWall",value:0.074841546
  }]]

Then using the index you get in the function, test which type of group and assign the color needed: 然后使用进入函数的索引,测试组的类型并分配所需的颜色:

color: function(d){
        if(colors[d] === "one"){
           return "red";
        }
        else if(colors[d] == "two"){
            return "green";
        }
        else{
            return "yellow";
        }
    }

Like that you don't have to change the behavior of the code you are using and you only change your code. 这样,您不必更改正在使用的代码的行为,而只需更改代码。

Here is the full code : 这是完整的代码:

 function RadarChart(id, data, options) { var cfg = { w: 600, //Width of the circle h: 600, //Height of the circle margin: { top: 20, right: 20, bottom: 20, left: 20 }, //The margins of the SVG levels: 3, //How many levels or inner circles should there be drawn maxValue: 0, //What is the value that the biggest circle will represent labelFactor: 1.25, //How much farther than the radius of the outer circle should the labels be placed wrapWidth: 60, //The number of pixels after which a label needs to be given a new line opacityArea: 0.35, //The opacity of the area of the blob dotRadius: 4, //The size of the colored circles of each blog opacityCircles: 0.1, //The opacity of the circles of each blob strokeWidth: 2, //The width of the stroke around each blob roundStrokes: false, //If true the area and stroke will follow a round path (cardinal-closed) color: d3.scale.category10() //Color function }; //Put all of the options into a variable called cfg if ('undefined' !== typeof options) { for (var i in options) { if ('undefined' !== typeof options[i]) { cfg[i] = options[i]; } } //for i } //if //If the supplied maxValue is smaller than the actual one, replace by the max in the data var maxValue = Math.max(cfg.maxValue, d3.max(data, function(i) { return d3.max(i.map(function(o) { return o.value; })) })); var allAxis = (data[0].map(function(i, j) { return i.axis })), //Names of each axis total = allAxis.length, //The number of different axes radius = Math.min(cfg.w / 2, cfg.h / 2), //Radius of the outermost circle Format = d3.format('.3'), //Percentage formatting angleSlice = Math.PI * 2 / total; //The width in radians of each "slice" //Scale for the radius var rScale = d3.scale.linear() .range([0, radius]) .domain([0, maxValue]); ///////////////////////////////////////////////////////// //////////// Create the container SVG and g ///////////// ///////////////////////////////////////////////////////// //Remove whatever chart with the same id/class was present before d3.select(id).select("svg").remove(); //Initiate the radar chart SVG var svg = d3.select(id).append("svg") .attr("width", cfg.w + cfg.margin.left + cfg.margin.right) .attr("height", cfg.h + cfg.margin.top + cfg.margin.bottom) .attr("class", "radar" + id); //Append ag element var g = svg.append("g") .attr("transform", "translate(" + (cfg.w / 2 + cfg.margin.left) + "," + (cfg.h / 2 + cfg.margin.top) + ")"); ///////////////////////////////////////////////////////// ////////// Glow filter for some extra pizzazz /////////// ///////////////////////////////////////////////////////// //Filter for the outside glow var filter = g.append('defs').append('filter').attr('id', 'glow'), feGaussianBlur = filter.append('feGaussianBlur').attr('stdDeviation', '2.5').attr('result', 'coloredBlur'), feMerge = filter.append('feMerge'), feMergeNode_1 = feMerge.append('feMergeNode').attr('in', 'coloredBlur'), feMergeNode_2 = feMerge.append('feMergeNode').attr('in', 'SourceGraphic'); ///////////////////////////////////////////////////////// /////////////// Draw the Circular grid ////////////////// ///////////////////////////////////////////////////////// //Wrapper for the grid & axes var axisGrid = g.append("g").attr("class", "axisWrapper"); //Draw the background circles axisGrid.selectAll(".levels") .data(d3.range(1, (cfg.levels + 1)).reverse()) .enter() .append("circle") .attr("class", "gridCircle") .attr("r", function(d, i) { return radius / cfg.levels * d; }) .style("fill", "#CDCDCD") .style("stroke", "#CDCDCD") .style("fill-opacity", cfg.opacityCircles) .style("filter", "url(#glow)"); //Text indicating at what % each level is axisGrid.selectAll(".axisLabel") .data(d3.range(1, (cfg.levels + 1)).reverse()) .enter().append("text") .attr("class", "axisLabel") .attr("x", 4) .attr("y", function(d) { return -d * radius / cfg.levels; }) .attr("dy", "0.4em") .style("font-size", "10px") .attr("fill", "#737373") .text(function(d, i) { return Format(maxValue * d / cfg.levels); }); ///////////////////////////////////////////////////////// //////////////////// Draw the axes ////////////////////// ///////////////////////////////////////////////////////// //Create the straight lines radiating outward from the center var axis = axisGrid.selectAll(".axis") .data(allAxis) .enter() .append("g") .attr("class", "axis"); //Append the lines axis.append("line") .attr("x1", 0) .attr("y1", 0) .attr("x2", function(d, i) { return rScale(maxValue * 1.1) * Math.cos(angleSlice * i - Math.PI / 2); }) .attr("y2", function(d, i) { return rScale(maxValue * 1.1) * Math.sin(angleSlice * i - Math.PI / 2); }) .attr("class", "line") .style("stroke", "white") .style("stroke-width", "2px"); //Append the labels at each axis axis.append("text") .attr("class", "legend") .style("font-size", "11px") .attr("text-anchor", "middle") .attr("dy", "0.35em") .attr("x", function(d, i) { return rScale(maxValue * cfg.labelFactor) * Math.cos(angleSlice * i - Math.PI / 2); }) .attr("y", function(d, i) { return rScale(maxValue * cfg.labelFactor) * Math.sin(angleSlice * i - Math.PI / 2); }) .text(function(d) { return d }) .call(wrap, cfg.wrapWidth); ///////////////////////////////////////////////////////// ///////////// Draw the radar chart blobs //////////////// ///////////////////////////////////////////////////////// //The radial line function var radarLine = d3.svg.line.radial() .interpolate("linear-closed") .radius(function(d) { return rScale(d.value); }) .angle(function(d, i) { return i * angleSlice; }); if (cfg.roundStrokes) { radarLine.interpolate("cardinal-closed"); } //Create a wrapper for the blobs var blobWrapper = g.selectAll(".radarWrapper") .data(data) .enter().append("g") .attr("class", "radarWrapper"); //Append the backgrounds blobWrapper .append("path") .attr("class", "radarArea") .attr("d", function(d, i) { return radarLine(d); }) .style("fill", function(d, i) { return cfg.color(i); }) .style("fill-opacity", cfg.opacityArea) .on('mouseover', function(d, i) { //Dim all blobs d3.selectAll(".radarArea") .transition().duration(200) .style("fill-opacity", 0.1); //Bring back the hovered over blob d3.select(this) .transition().duration(200) .style("fill-opacity", 0.7); }) .on('mouseout', function() { //Bring back all blobs d3.selectAll(".radarArea") .transition().duration(200) .style("fill-opacity", cfg.opacityArea); }); //Create the outlines blobWrapper.append("path") .attr("class", "radarStroke") .attr("d", function(d, i) { return radarLine(d); }) .style("stroke-width", cfg.strokeWidth + "px") .style("stroke", function(d, i) { return cfg.color(i); }) .style("fill", "none") .style("filter", "url(#glow)"); //Append the circles blobWrapper.selectAll(".radarCircle") .data(function(d, i) { return d; }) .enter().append("circle") .attr("class", "radarCircle") .attr("r", cfg.dotRadius) .attr("cx", function(d, i) { return rScale(d.value) * Math.cos(angleSlice * i - Math.PI / 2); }) .attr("cy", function(d, i) { return rScale(d.value) * Math.sin(angleSlice * i - Math.PI / 2); }) .style("fill", function(d, i, j) { return cfg.color(j); }) .style("fill-opacity", 0.8); ///////////////////////////////////////////////////////// //////// Append invisible circles for tooltip /////////// ///////////////////////////////////////////////////////// //Wrapper for the invisible circles on top var blobCircleWrapper = g.selectAll(".radarCircleWrapper") .data(data) .enter().append("g") .attr("class", "radarCircleWrapper"); //Append a set of invisible circles on top for the mouseover pop-up blobCircleWrapper.selectAll(".radarInvisibleCircle") .data(function(d, i) { return d; }) .enter().append("circle") .attr("class", "radarInvisibleCircle") .attr("r", cfg.dotRadius * 1.5) .attr("cx", function(d, i) { return rScale(d.value) * Math.cos(angleSlice * i - Math.PI / 2); }) .attr("cy", function(d, i) { return rScale(d.value) * Math.sin(angleSlice * i - Math.PI / 2); }) .style("fill", "none") .style("pointer-events", "all") .on("mouseover", function(d, i) { newX = parseFloat(d3.select(this).attr('cx')) - 10; newY = parseFloat(d3.select(this).attr('cy')) - 10; tooltip .attr('x', newX) .attr('y', newY) .text(Format(d.value)) .transition().duration(200) .style('opacity', 1); }) .on("mouseout", function() { tooltip.transition().duration(200) .style("opacity", 0); }); //Set up the small tooltip for when you hover over a circle var tooltip = g.append("text") .attr("class", "tooltip") .style("opacity", 0); ///////////////////////////////////////////////////////// /////////////////// Helper Function ///////////////////// ///////////////////////////////////////////////////////// //Taken from http://bl.ocks.org/mbostock/7555321 //Wraps SVG text function wrap(text, width) { text.each(function() { var text = d3.select(this), words = text.text().split(/\\s+/).reverse(), word, line = [], lineNumber = 0, lineHeight = 1.4, // ems y = text.attr("y"), x = text.attr("x"), dy = parseFloat(text.attr("dy")), tspan = text.text(null).append("tspan").attr("x", x).attr("y", y).attr("dy", dy + "em"); while (word = words.pop()) { line.push(word); tspan.text(line.join(" ")); if (tspan.node().getComputedTextLength() > width) { line.pop(); tspan.text(line.join(" ")); line = [word]; tspan = text.append("tspan").attr("x", x).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word); } } }); } //wrap } //RadarChart /* Radar chart design created by Nadieh Bremer - VisualCinnamon.com */ ////////////////////////////////////////////////////////////// //////////////////////// Set-Up ////////////////////////////// ////////////////////////////////////////////////////////////// var margin = { top: 100, right: 100, bottom: 100, left: 100 }, width = Math.min(700, window.innerWidth - 10) - margin.left - margin.right, height = Math.min(width, window.innerHeight - margin.top - margin.bottom - 20); ////////////////////////////////////////////////////////////// ////////////////////////// Data ////////////////////////////// ////////////////////////////////////////////////////////////// var colors = ["two", "one", "one", "two"]; var data = [ [{ axis: "volume(N)", value: 0.074095419 }, { axis: "heightBBOX(N)", value: 0.618900916 }, { axis: "floor_area(N)", value: 0.239036487 }, { axis: "RatioSunExp_TotWall", value: 0.670908597 } ], [{ axis: "volume(N)", value: 0.373966243 }, { axis: "heightBBOX(N)", value: 0.418068276 }, { axis: "floor_area(N)", value: 0.039064467 }, { axis: "RatioSunExp_TotWall", value: 0.341108011 } ], [{ axis: "volume(N)", value: 0.675991163 }, { axis: "heightBBOX(N)", value: 0.815015265 }, { axis: "floor_area(N)", value: 0.94061374 }, { axis: "RatioSunExp_TotWall", value: 0.974062924 } ], [{ axis: "volume(N)", value: 0.875950233 }, { axis: "heightBBOX(N)", value: 0.210852068 }, { axis: "floor_area(N)", value: 0.540645865 }, { axis: "RatioSunExp_TotWall", value: 0.074841546 } ] ] ////////////////////////////////////////////////////////////// //////////////////// Draw the Chart ////////////////////////// ////////////////////////////////////////////////////////////// var colorFn = d3.scale.ordinal() .domain(["one", "two"]) .range(["red", "green"]); var radarChartOptions = { w: width, h: height, margin: margin, maxValue: 1, levels: 10, roundStrokes: true, color: function(d) { if (colors[d] === "one") { return "red"; } else if (colors[d] == "two") { return "green"; } else { return "yellow"; } }, }; //Call function to draw the Radar chart RadarChart(".radarChart", data, radarChartOptions); 
 body { font-family: 'Open Sans', sans-serif; font-size: 11px; font-weight: 300; fill: #242424; text-align: center; text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff, 0 -1px 0 #fff; cursor: default; } .legend { font-family: 'Raleway', sans-serif; fill: #333333; } .tooltip { fill: #333333; } 
 <!-- D3.js --> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script> <div class="radarChart"></div> 


You can also optimize by doing something like this: 您还可以通过执行以下操作来优化:

var colors = ["two","one","one","two"];
var colorDef = {"one":"red","two":"green"};

 color: function(d){
     return  colorDef[colors[d]];
  }

Full code: 完整代码:

https://jsfiddle.net/c3wu7ftr/3/ https://jsfiddle.net/c3wu7ftr/3/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM