问题
I am trying to create a barchart (not rowchart) using d3.js and dc.js. I can create the bars ok, but they are all the same colour.
I have tried :
- ordinalColors()
- scaleOrdinal.range()
- Renderlet
- colorAccessor
but they all give the one colour for all bars, except colorAccessor which displays no bars at all.
I am using dc.js (version 3.0.2) and d3.js (version 5.4.0) and crossfilter (version 1.3.5).
Could someone please tell me an approach that will work to get different colours on each of my bars please?
Here is my code:
fruits = [{
"name": "apple",
"cnt": 10
},
{
"name": "orange",
"cnt": 15
},
{
"name": "banana",
"cnt": 12
},
{
"name": "grapefruit",
"cnt": 2
},
{
"name": "grapefruit",
"cnt": 4
},
{
"name": "pomegranate",
"cnt": 1
},
{
"name": "lime",
"cnt": 12
},
{
"name": "grape",
"cnt": 50
}
];
var ndx = crossfilter(fruits);
fruitDimension = ndx.dimension(function(d) {
return d.name;
}),
sumGroup = fruitDimension.group().reduceSum(function(d) {
return d.cnt;
});
fruitColours = d3.scaleOrdinal().range(["red", "yellow", "purple", "pink", "green", "orange", "blue"]);
barChart
// .ordinalColors(["red", "yellow", "purple", "pink", "green", "orange", "blue"])
// .ordinalColors(fruitColours)
// .ordinalColors(["#79CED7", "#66AFB2", "#C96A23", "#D3D1C5", "#F5821F"])
.width(768)
.height(380)
.x(d3.scaleBand())
.xUnits(dc.units.ordinal)
.brushOn(false)
.xAxisLabel('Fruit')
.yAxisLabel('Quantity Sold')
.dimension(fruitDimension)
.barPadding(0.1)
.outerPadding(0.05)
.group(sumGroup)
.colorAccessor(["#79CED7", "#66AFB2", "#C96A23", "#D3D1C5", "#F5821F", "grey", "purple"])
// .on("renderlet", function(chart){
// var colors =d3.scaleOrdinal().domain(["apple", "orange", "banana", "grapefruit", "pomegranate", "lime", "grape"])
// .range(["steelblue", "brown", "red", "green", "yellow", "grey", "purple"]);
// chart.selectAll('rect.bar').each(function(d){
//// d3.select(this).attr("style", "fill: " + colors(d.key)); // use key accessor if you are using a custom accessor
// d3.select(this).attr("style", "fill: " + colors(d.name)); // use key accessor if you are using a custom accessor
// });
// });
;
dc.renderAll();
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>School Donations Dashboard</title>
<link rel="stylesheet" href="vendor/css/bootstrap.min.css" />
<link rel="stylesheet" href="vendor/css/dc.css" />
<link rel="stylesheet" href="vendor/css/keen-dashboards.css" />
<link rel="stylesheet" href="css/custom.css" />
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="index.xhtml">Dashboard</a>
</div>
</div>
</div>
<div id="outer" class="container-fluid">
<!-- Test Bar Chart -->
<div class="chartWrapper">
<div class="chartTitle">
Bar Chart
</div>
<div class="chartStage">
<div id="barChart"></div>
</div>
</div>
<!-- Test Bar Chart -->
</div>
<!-- /outer -->
<hr />
<script src="vendor/js/jquery.min.js">
</script>
<script src="vendor" name="js/bootstrap.min.js">
</script>
<script src="vendor" name="js/crossfilter.js">
</script>
<script src="vendor/js/d3-v5.min.js">
</script>
<script src="vendor/js/d3-scale.min.js">
</script>
<script src="vendor/js/dc.js">
</script>
<script src="vendor/js/queue.js">
</script>
<script src="vendor/js/keen.min.js">
</script>
<script src="js/graph.js">
</script>
</body>
</html>
回答1:
It looks like the problem you ran into is confusion between the role of the color accessor (.colorAccessor()) and the color scale (.colors()).
In all dc.js charts, an accessor function will be used to fetch the value that should determine the color. Then this value will be passed through a color scale in order to determine the actual color.
This is handy because for the most part your data is not going to have actual colors in it. The color scale takes some value from your data and maps it to a color.
When you specify the colorAccessor
you need to give it a function which takes the data supplied by the group, in {key, value}
form, and extracts the value you want mapped to a color.
If you want to change the colors used, you can use .colors(), supplying a d3 scale appropriate for your data, or you can use the convenience functions .ordinalColors() or .linearColors() and give the colors you want.
That's all you need for most charts. But for stacked charts (bar and line), you also need to specify the color accessor. This is because by default the stack mixin uses the layer (stack name) to key the color:
_chart.colorAccessor(function (d) {
var layer = this.layer || this.name || d.name || d.layer;
return layer;
});
(source)
So if you want unique colors for each bar, basing the color accessor on the group key is a good bet:
chart
.colorAccessor(d => d.key)
.ordinalColors(["#79CED7", "#66AFB2", "#C96A23", "#D3D1C5", "#F5821F", "grey", "purple"]);
However you'll need to make sure to specify at least as many ordinal colors as there are bars because an ordinal scale will repeat when the domain is larger size than the range.
Demo fiddle.
来源:https://stackoverflow.com/questions/50774206/different-colours-for-dc-js-barchart