【问题标题】:How to assign different color to each bar in the bar chart in d3.js如何为d3.js中条形图中的每个条分配不同的颜色
【发布时间】:2020-10-31 20:25:33
【问题描述】:

我正在尝试根据虚拟数据的 id 为条形图中的三个条形分配不同的颜色。但是由于某种原因我失败了,即使我创建了 colorArray 试图将其作为属性并附加到图表中。它应该相对容易,但不确定出了什么问题。请帮帮我!

const DUMMY_DATA = [
  { id: 'd1', level: 'High Happiness', value: 6.67 },
  { id: 'd2', level: 'Middle Happiness', value: 5.47 },
  { id: 'd3', level: 'Low Happiness', value: 4.35 },
  //{ id: 'd4', level: 'Germany', value: 6 },
];

const MARGINS = {top: 20, bottom: 10};
const CHART_WIDTH = 600; 
const CHART_HEIGHT = 400 - MARGINS.bottom - MARGINS.top; 

let selectedData = DUMMY_DATA;

const x = d3.scaleBand().rangeRound([0,CHART_WIDTH]).padding(0.1); 
const y = d3.scaleLinear().range([CHART_HEIGHT, 0]);
const colorArray = d3.scaleOrdinal().domain(["d1","d2","d3"]).range(["orange", "purple", "steelblue"]);

const chartContainer = d3.select("svg")
    .attr("width", CHART_WIDTH)
    .attr("height", CHART_HEIGHT + MARGINS.bottom + MARGINS.top);

    x.domain(DUMMY_DATA.map((d) => d.level));
    y.domain([0, d3.max(DUMMY_DATA, (d) => d.value) + 3] );


const chart = chartContainer.append("g");
chart.append("g")
    .call(d3.axisBottom(x).tickSizeOuter(0))
    .attr("transform", `translate(0, ${CHART_HEIGHT+10})`)
    .attr("color", "lighgray");
    
function renderChart(){
    chart
    .selectAll(".bar")
    .data(selectedData, data => data.id)
    .enter()
    .append("rect")
    .classed("bar", true)
    .attr("width", x.bandwidth())
    .attr("height", (data) => CHART_HEIGHT - y(data.value))
    .attr("x", (data) => x(data.level))
    .attr("y", (data) => y(data.value));
      
    chart.selectAll(".bar").data(selectedData, data => data.id).exit().remove();
    
    chart
    .selectAll(".label")
    .data(selectedData, data => data.id)
    .enter()
    .append("text")
    .text(data => data.value)
    .attr("x", data => x(data.level) + x.bandwidth()/2)
    .attr("y", data => y(data.value) - 20)
    .attr("text-anchor", "middle")
    .classed("label", true);
    
    chart.selectAll(".label").data(selectedData, data => data.id).exit().remove();
}

renderChart();

let unselectedIds = [];

const listItems =d3.select("#data")
.select("ul")
.selectAll("li")
.data(DUMMY_DATA)
.enter()
.append("li");

【问题讨论】:

    标签: javascript html css d3.js visualization


    【解决方案1】:

    您需要将数据值传递给您的 colorArray 函数并使用 fill 应用它们:

    chart.attr("fill", (data) => colorArray(data.id));
    

    使用您的代码的工作示例:

    const DUMMY_DATA = [
      { id: 'd1', level: 'High Happiness', value: 6.67 },
      { id: 'd2', level: 'Middle Happiness', value: 5.47 },
      { id: 'd3', level: 'Low Happiness', value: 4.35 },
    ];
    
    const MARGINS = {top: 20, bottom: 10};
    const CHART_WIDTH = 600; 
    const CHART_HEIGHT = 400 - MARGINS.bottom - MARGINS.top; 
    
    let selectedData = DUMMY_DATA;
    
    const x = d3.scaleBand().rangeRound([0,CHART_WIDTH]).padding(0.1); 
    const y = d3.scaleLinear().range([CHART_HEIGHT, 0]);
    const colorArray = d3.scaleOrdinal().domain(["d1","d2","d3"]).range(["orange", "purple", "steelblue"]);
    
    const chartContainer = d3.select("svg")
        .attr("width", CHART_WIDTH)
        .attr("height", CHART_HEIGHT + MARGINS.bottom + MARGINS.top);
    
        x.domain(DUMMY_DATA.map((d) => d.level));
        y.domain([0, d3.max(DUMMY_DATA, (d) => d.value) + 3] );
    
    
    const chart = chartContainer.append("g");
    chart.append("g")
        .call(d3.axisBottom(x).tickSizeOuter(0))
        .attr("transform", `translate(0, ${CHART_HEIGHT+10})`)
        .attr("color", "lighgray");
        
    function renderChart(){
        chart
        .selectAll(".bar")
        .data(selectedData, data => data.id)
        .enter()
        .append("rect")
        .classed("bar", true)
        .attr("width", x.bandwidth())
        .attr("height", (data) => CHART_HEIGHT - y(data.value))
        .attr("x", (data) => x(data.level))
        .attr("y", (data) => y(data.value))
        // *********** Apply colors below ***********
        .attr("fill", (data) => colorArray(data.id));
          
        chart.selectAll(".bar").data(selectedData, data => data.id).exit().remove();
        
        chart
        .selectAll(".label")
        .data(selectedData, data => data.id)
        .enter()
        .append("text")
        .text(data => data.value)
        .attr("x", data => x(data.level) + x.bandwidth()/2)
        .attr("y", data => y(data.value) - 20)
        .attr("text-anchor", "middle")
        .classed("label", true)
    
        
        chart.selectAll(".label").data(selectedData, data => data.id).exit().remove();
    }
    
    renderChart();
    
    let unselectedIds = [];
    
    const listItems =d3.select("#data")
    .select("ul")
    .selectAll("li")
    .data(DUMMY_DATA)
    .enter()
    .append("li");
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <svg></svg>

    【讨论】:

    • 谢谢!但是可以在 data.id 上运行它吗?只是好奇
    • 是的,只需将其更改为 data.id 而不是 data.value
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多